* frame.c (Vdelete_frame_functions): New variable.
[emacs.git] / src / macfns.c
blobf1e42d17aecd66dbaf5edb6a1f827d09a19d1c20
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 /* A definition of XColor for non-X frames. */
103 #ifndef HAVE_X_WINDOWS
104 typedef struct {
105 unsigned long pixel;
106 unsigned short red, green, blue;
107 char flags;
108 char pad;
109 } XColor;
110 #endif
112 extern char *lispy_function_keys[];
114 /* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
115 it, and including `bitmaps/gray' more than once is a problem when
116 config.h defines `static' as an empty replacement string. */
118 int gray_bitmap_width = gray_width;
119 int gray_bitmap_height = gray_height;
120 unsigned char *gray_bitmap_bits = gray_bits;
122 /* The name we're using in resource queries. */
124 Lisp_Object Vx_resource_name;
126 /* Non-zero means we're allowed to display an hourglass cursor. */
128 int display_hourglass_p;
130 /* The background and shape of the mouse pointer, and shape when not
131 over text or in the modeline. */
133 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
134 Lisp_Object Vx_hourglass_pointer_shape;
136 /* The shape when over mouse-sensitive text. */
138 Lisp_Object Vx_sensitive_text_pointer_shape;
140 /* If non-nil, the pointer shape to indicate that windows can be
141 dragged horizontally. */
143 Lisp_Object Vx_window_horizontal_drag_shape;
145 /* Color of chars displayed in cursor box. */
147 Lisp_Object Vx_cursor_fore_pixel;
149 /* Nonzero if using Windows. */
151 static int mac_in_use;
153 /* Non nil if no window manager is in use. */
155 Lisp_Object Vx_no_window_manager;
157 /* Search path for bitmap files. */
159 Lisp_Object Vx_bitmap_file_path;
161 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
163 Lisp_Object Vx_pixel_size_width_font_regexp;
165 /* Evaluate this expression to rebuild the section of syms_of_macfns
166 that initializes and staticpros the symbols declared below. Note
167 that Emacs 18 has a bug that keeps C-x C-e from being able to
168 evaluate this expression.
170 (progn
171 ;; Accumulate a list of the symbols we want to initialize from the
172 ;; declarations at the top of the file.
173 (goto-char (point-min))
174 (search-forward "/\*&&& symbols declared here &&&*\/\n")
175 (let (symbol-list)
176 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
177 (setq symbol-list
178 (cons (buffer-substring (match-beginning 1) (match-end 1))
179 symbol-list))
180 (forward-line 1))
181 (setq symbol-list (nreverse symbol-list))
182 ;; Delete the section of syms_of_... where we initialize the symbols.
183 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
184 (let ((start (point)))
185 (while (looking-at "^ Q")
186 (forward-line 2))
187 (kill-region start (point)))
188 ;; Write a new symbol initialization section.
189 (while symbol-list
190 (insert (format " %s = intern (\"" (car symbol-list)))
191 (let ((start (point)))
192 (insert (substring (car symbol-list) 1))
193 (subst-char-in-region start (point) ?_ ?-))
194 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
195 (setq symbol-list (cdr symbol-list)))))
199 /*&&& symbols declared here &&&*/
200 Lisp_Object Qauto_raise;
201 Lisp_Object Qauto_lower;
202 Lisp_Object Qborder_color;
203 Lisp_Object Qborder_width;
204 Lisp_Object Qcursor_color;
205 Lisp_Object Qcursor_type;
206 Lisp_Object Qgeometry;
207 Lisp_Object Qicon_left;
208 Lisp_Object Qicon_top;
209 Lisp_Object Qicon_type;
210 Lisp_Object Qicon_name;
211 Lisp_Object Qinternal_border_width;
212 Lisp_Object Qleft;
213 Lisp_Object Qright;
214 Lisp_Object Qmouse_color;
215 Lisp_Object Qnone;
216 Lisp_Object Qparent_id;
217 Lisp_Object Qscroll_bar_width;
218 Lisp_Object Qsuppress_icon;
219 Lisp_Object Qundefined_color;
220 Lisp_Object Qvertical_scroll_bars;
221 Lisp_Object Qvisibility;
222 Lisp_Object Qwindow_id;
223 Lisp_Object Qx_frame_parameter;
224 Lisp_Object Qx_resource_name;
225 Lisp_Object Quser_position;
226 Lisp_Object Quser_size;
227 Lisp_Object Qscreen_gamma;
228 Lisp_Object Qline_spacing;
229 Lisp_Object Qcenter;
230 Lisp_Object Qcancel_timer;
231 Lisp_Object Qhyper;
232 Lisp_Object Qsuper;
233 Lisp_Object Qmeta;
234 Lisp_Object Qalt;
235 Lisp_Object Qctrl;
236 Lisp_Object Qcontrol;
237 Lisp_Object Qshift;
239 extern Lisp_Object Qtop;
240 extern Lisp_Object Qdisplay;
241 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
242 extern Lisp_Object Qtool_bar_lines;
244 /* These are defined in frame.c. */
245 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
246 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
247 extern Lisp_Object Qtool_bar_lines;
249 extern Lisp_Object Vwindow_system_version;
251 extern Lisp_Object Qbox;
253 Lisp_Object Qface_set_after_frame_default;
255 extern int mac_initialized;
257 /* Functions in macterm.c. */
258 extern void x_set_offset (struct frame *, int, int, int);
259 extern void x_wm_set_icon_position (struct frame *, int, int);
260 extern void x_display_cursor (struct window *, int, int, int, int, int);
261 extern void x_set_window_size (struct frame *, int, int, int);
262 extern void x_make_frame_visible (struct frame *);
263 extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
264 extern struct font_info *x_get_font_info (FRAME_PTR, int);
265 extern struct font_info *x_load_font (struct frame *, char *, int);
266 extern void x_find_ccl_program (struct font_info *);
267 extern struct font_info *x_query_font (struct frame *, char *);
268 extern void mac_initialize ();
270 /* compare two strings ignoring case */
272 static int
273 stricmp (const char *s, const char *t)
275 for ( ; tolower (*s) == tolower (*t); s++, t++)
276 if (*s == '\0')
277 return 0;
278 return tolower (*s) - tolower (*t);
281 /* compare two strings up to n characters, ignoring case */
283 static int
284 strnicmp (const char *s, const char *t, unsigned int n)
286 for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
287 if (*s == '\0')
288 return 0;
289 return n == 0 ? 0 : tolower (*s) - tolower (*t);
293 /* Error if we are not running on Mac OS. */
295 void
296 check_mac ()
298 if (! mac_in_use)
299 error ("Mac OS not in use or not initialized");
302 /* Nonzero if we can use mouse menus.
303 You should not call this unless HAVE_MENUS is defined. */
306 have_menus_p ()
308 return mac_in_use;
311 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
312 and checking validity for Mac. */
314 FRAME_PTR
315 check_x_frame (frame)
316 Lisp_Object frame;
318 FRAME_PTR f;
320 if (NILP (frame))
321 frame = selected_frame;
322 CHECK_LIVE_FRAME (frame);
323 f = XFRAME (frame);
324 if (! FRAME_MAC_P (f))
325 error ("non-mac frame used");
326 return f;
329 /* Let the user specify an display with a frame.
330 nil stands for the selected frame--or, if that is not a mac frame,
331 the first display on the list. */
333 static struct mac_display_info *
334 check_x_display_info (frame)
335 Lisp_Object frame;
337 if (!mac_initialized)
339 mac_initialize ();
340 mac_initialized = 1;
343 if (NILP (frame))
345 struct frame *sf = XFRAME (selected_frame);
347 if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
348 return FRAME_MAC_DISPLAY_INFO (sf);
349 else
350 return &one_mac_display_info;
352 else if (STRINGP (frame))
353 return x_display_info_for_name (frame);
354 else
356 FRAME_PTR f;
358 CHECK_LIVE_FRAME (frame);
359 f = XFRAME (frame);
360 if (! FRAME_MAC_P (f))
361 error ("non-mac frame used");
362 return FRAME_MAC_DISPLAY_INFO (f);
366 /* Return the Emacs frame-object corresponding to an mac window.
367 It could be the frame's main window or an icon window. */
369 /* This function can be called during GC, so use GC_xxx type test macros. */
371 struct frame *
372 x_window_to_frame (dpyinfo, wdesc)
373 struct mac_display_info *dpyinfo;
374 WindowPtr wdesc;
376 Lisp_Object tail, frame;
377 struct frame *f;
379 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
381 frame = XCAR (tail);
382 if (!GC_FRAMEP (frame))
383 continue;
384 f = XFRAME (frame);
385 if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
386 continue;
387 /*if (f->output_data.w32->hourglass_window == wdesc)
388 return f;*/
390 /* MAC_TODO: Check tooltips when supported. */
391 if (FRAME_MAC_WINDOW (f) == wdesc)
392 return f;
394 return 0;
399 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
400 id, which is just an int that this section returns. Bitmaps are
401 reference counted so they can be shared among frames.
403 Bitmap indices are guaranteed to be > 0, so a negative number can
404 be used to indicate no bitmap.
406 If you use x_create_bitmap_from_data, then you must keep track of
407 the bitmaps yourself. That is, creating a bitmap from the same
408 data more than once will not be caught. */
411 /* Functions to access the contents of a bitmap, given an id. */
414 x_bitmap_height (f, id)
415 FRAME_PTR f;
416 int id;
418 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
422 x_bitmap_width (f, id)
423 FRAME_PTR f;
424 int id;
426 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
429 #if 0 /* MAC_TODO : not used anywhere (?) */
431 x_bitmap_pixmap (f, id)
432 FRAME_PTR f;
433 int id;
435 return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
437 #endif
439 /* Allocate a new bitmap record. Returns index of new record. */
441 static int
442 x_allocate_bitmap_record (f)
443 FRAME_PTR f;
445 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
446 int i;
448 if (dpyinfo->bitmaps == NULL)
450 dpyinfo->bitmaps_size = 10;
451 dpyinfo->bitmaps = (struct mac_bitmap_record *)
452 xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
453 dpyinfo->bitmaps_last = 1;
454 return 1;
457 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
458 return ++dpyinfo->bitmaps_last;
460 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
461 if (dpyinfo->bitmaps[i].refcount == 0)
462 return i + 1;
464 dpyinfo->bitmaps_size *= 2;
465 dpyinfo->bitmaps = (struct mac_bitmap_record *)
466 xrealloc (dpyinfo->bitmaps,
467 dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
468 return ++dpyinfo->bitmaps_last;
471 /* Add one reference to the reference count of the bitmap with id
472 ID. */
474 void
475 x_reference_bitmap (f, id)
476 FRAME_PTR f;
477 int id;
479 ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
482 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
483 BITS. */
486 x_create_bitmap_from_data (f, bits, width, height)
487 struct frame *f;
488 char *bits;
489 unsigned int width, height;
491 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
492 int id;
494 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
496 id = x_allocate_bitmap_record (f);
498 if (width % 16 != 0)
499 return -1;
501 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
502 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
503 return -1;
505 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
507 dpyinfo->bitmaps[id - 1].refcount = 1;
508 dpyinfo->bitmaps[id - 1].height = height;
509 dpyinfo->bitmaps[id - 1].width = width;
511 return id;
514 /* Create bitmap from file FILE for frame F. */
517 x_create_bitmap_from_file (f, file)
518 struct frame *f;
519 Lisp_Object file;
521 return -1;
522 #if 0 /* MAC_TODO : bitmap support */
523 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
524 unsigned int width, height;
525 HBITMAP bitmap;
526 int xhot, yhot, result, id;
527 Lisp_Object found;
528 int fd;
529 char *filename;
530 HINSTANCE hinst;
532 /* Look for an existing bitmap with the same name. */
533 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
535 if (dpyinfo->bitmaps[id].refcount
536 && dpyinfo->bitmaps[id].file
537 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
539 ++dpyinfo->bitmaps[id].refcount;
540 return id + 1;
544 /* Search bitmap-file-path for the file, if appropriate. */
545 fd = openp (Vx_bitmap_file_path, file, "", &found, Qnil);
546 if (fd < 0)
547 return -1;
548 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
549 if (fd == 0)
550 return -1;
551 emacs_close (fd);
553 filename = (char *) SDATA (found);
555 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
557 if (hinst == NULL)
558 return -1;
561 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
562 filename, &width, &height, &bitmap, &xhot, &yhot);
563 if (result != BitmapSuccess)
564 return -1;
566 id = x_allocate_bitmap_record (f);
567 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
568 dpyinfo->bitmaps[id - 1].refcount = 1;
569 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SCHARS (file) + 1);
570 dpyinfo->bitmaps[id - 1].depth = 1;
571 dpyinfo->bitmaps[id - 1].height = height;
572 dpyinfo->bitmaps[id - 1].width = width;
573 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
575 return id;
576 #endif /* MAC_TODO */
579 /* Remove reference to bitmap with id number ID. */
581 void
582 x_destroy_bitmap (f, id)
583 FRAME_PTR f;
584 int id;
586 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
588 if (id > 0)
590 --dpyinfo->bitmaps[id - 1].refcount;
591 if (dpyinfo->bitmaps[id - 1].refcount == 0)
593 BLOCK_INPUT;
594 dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
595 UNBLOCK_INPUT;
600 /* Free all the bitmaps for the display specified by DPYINFO. */
602 static void
603 x_destroy_all_bitmaps (dpyinfo)
604 struct mac_display_info *dpyinfo;
606 int i;
607 for (i = 0; i < dpyinfo->bitmaps_last; i++)
608 if (dpyinfo->bitmaps[i].refcount > 0)
609 xfree (dpyinfo->bitmaps[i].bitmap_data);
610 dpyinfo->bitmaps_last = 0;
613 /* Connect the frame-parameter names for W32 frames
614 to the ways of passing the parameter values to the window system.
616 The name of a parameter, as a Lisp symbol,
617 has an `x-frame-parameter' property which is an integer in Lisp
618 but can be interpreted as an `enum x_frame_parm' in C. */
620 struct x_frame_parm_table
622 char *name;
623 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
626 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
627 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
628 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
629 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
630 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
631 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
632 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
633 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
634 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
635 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
636 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
637 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
638 Lisp_Object));
639 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
640 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
641 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
642 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
643 Lisp_Object));
644 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
645 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
646 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
647 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
648 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
649 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
650 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
651 Lisp_Object));
652 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
653 Lisp_Object));
654 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
655 Lisp_Object,
656 Lisp_Object,
657 char *, char *,
658 int));
659 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
661 static struct x_frame_parm_table x_frame_parms[] =
663 "auto-raise", x_set_autoraise,
664 "auto-lower", x_set_autolower,
665 "background-color", x_set_background_color,
666 "border-color", x_set_border_color,
667 "border-width", x_set_border_width,
668 "cursor-color", x_set_cursor_color,
669 "cursor-type", x_set_cursor_type,
670 "font", x_set_font,
671 "foreground-color", x_set_foreground_color,
672 "icon-name", x_set_icon_name,
673 #if 0 /* MAC_TODO: no icons for Mac */
674 "icon-type", x_set_icon_type,
675 #endif
676 "internal-border-width", x_set_internal_border_width,
677 "menu-bar-lines", x_set_menu_bar_lines,
678 "mouse-color", x_set_mouse_color,
679 "name", x_explicitly_set_name,
680 "scroll-bar-width", x_set_scroll_bar_width,
681 "title", x_set_title,
682 "unsplittable", x_set_unsplittable,
683 "vertical-scroll-bars", x_set_vertical_scroll_bars,
684 "visibility", x_set_visibility,
685 "tool-bar-lines", x_set_tool_bar_lines,
686 #if 0 /* MAC_TODO: cannot set color of scroll bar on the Mac? */
687 "scroll-bar-foreground", x_set_scroll_bar_foreground,
688 "scroll-bar-background", x_set_scroll_bar_background,
689 #endif
690 "screen-gamma", x_set_screen_gamma,
691 "line-spacing", x_set_line_spacing
694 /* Attach the `x-frame-parameter' properties to
695 the Lisp symbol names of parameters relevant to Mac. */
697 void
698 init_x_parm_symbols ()
700 int i;
702 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
703 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
704 make_number (i));
707 /* Change the parameters of frame F as specified by ALIST.
708 If a parameter is not specially recognized, do nothing;
709 otherwise call the `x_set_...' function for that parameter. */
711 void
712 x_set_frame_parameters (f, alist)
713 FRAME_PTR f;
714 Lisp_Object alist;
716 Lisp_Object tail;
718 /* If both of these parameters are present, it's more efficient to
719 set them both at once. So we wait until we've looked at the
720 entire list before we set them. */
721 int width, height;
723 /* Same here. */
724 Lisp_Object left, top;
726 /* Same with these. */
727 Lisp_Object icon_left, icon_top;
729 /* Record in these vectors all the parms specified. */
730 Lisp_Object *parms;
731 Lisp_Object *values;
732 int i, p;
733 int left_no_change = 0, top_no_change = 0;
734 int icon_left_no_change = 0, icon_top_no_change = 0;
736 struct gcpro gcpro1, gcpro2;
738 i = 0;
739 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
740 i++;
742 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
743 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
745 /* Extract parm names and values into those vectors. */
747 i = 0;
748 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
750 Lisp_Object elt;
752 elt = Fcar (tail);
753 parms[i] = Fcar (elt);
754 values[i] = Fcdr (elt);
755 i++;
757 /* TAIL and ALIST are not used again below here. */
758 alist = tail = Qnil;
760 GCPRO2 (*parms, *values);
761 gcpro1.nvars = i;
762 gcpro2.nvars = i;
764 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
765 because their values appear in VALUES and strings are not valid. */
766 top = left = Qunbound;
767 icon_left = icon_top = Qunbound;
769 /* Provide default values for HEIGHT and WIDTH. */
770 if (FRAME_NEW_WIDTH (f))
771 width = FRAME_NEW_WIDTH (f);
772 else
773 width = FRAME_WIDTH (f);
775 if (FRAME_NEW_HEIGHT (f))
776 height = FRAME_NEW_HEIGHT (f);
777 else
778 height = FRAME_HEIGHT (f);
780 /* Process foreground_color and background_color before anything else.
781 They are independent of other properties, but other properties (e.g.,
782 cursor_color) are dependent upon them. */
783 for (p = 0; p < i; p++)
785 Lisp_Object prop, val;
787 prop = parms[p];
788 val = values[p];
789 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
791 register Lisp_Object param_index, old_value;
793 param_index = Fget (prop, Qx_frame_parameter);
794 old_value = get_frame_param (f, prop);
795 store_frame_param (f, prop, val);
796 if (NATNUMP (param_index)
797 && (XFASTINT (param_index)
798 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
799 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
803 /* Now process them in reverse of specified order. */
804 for (i--; i >= 0; i--)
806 Lisp_Object prop, val;
808 prop = parms[i];
809 val = values[i];
811 if (EQ (prop, Qwidth) && NUMBERP (val))
812 width = XFASTINT (val);
813 else if (EQ (prop, Qheight) && NUMBERP (val))
814 height = XFASTINT (val);
815 else if (EQ (prop, Qtop))
816 top = val;
817 else if (EQ (prop, Qleft))
818 left = val;
819 else if (EQ (prop, Qicon_top))
820 icon_top = val;
821 else if (EQ (prop, Qicon_left))
822 icon_left = val;
823 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
824 /* Processed above. */
825 continue;
826 else
828 register Lisp_Object param_index, old_value;
830 param_index = Fget (prop, Qx_frame_parameter);
831 old_value = get_frame_param (f, prop);
832 store_frame_param (f, prop, val);
833 if (NATNUMP (param_index)
834 && (XFASTINT (param_index)
835 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
836 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
840 /* Don't die if just one of these was set. */
841 if (EQ (left, Qunbound))
843 left_no_change = 1;
844 if (f->output_data.mac->left_pos < 0)
845 left = Fcons (Qplus,
846 Fcons (make_number (f->output_data.mac->left_pos),
847 Qnil));
848 else
849 XSETINT (left, f->output_data.mac->left_pos);
851 if (EQ (top, Qunbound))
853 top_no_change = 1;
854 if (f->output_data.mac->top_pos < 0)
855 top = Fcons (Qplus,
856 Fcons (make_number (f->output_data.mac->top_pos), Qnil));
857 else
858 XSETINT (top, f->output_data.mac->top_pos);
861 /* If one of the icon positions was not set, preserve or default it. */
862 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
864 icon_left_no_change = 1;
865 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
866 if (NILP (icon_left))
867 XSETINT (icon_left, 0);
869 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
871 icon_top_no_change = 1;
872 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
873 if (NILP (icon_top))
874 XSETINT (icon_top, 0);
877 /* Don't set these parameters unless they've been explicitly
878 specified. The window might be mapped or resized while we're in
879 this function, and we don't want to override that unless the lisp
880 code has asked for it.
882 Don't set these parameters unless they actually differ from the
883 window's current parameters; the window may not actually exist
884 yet. */
886 Lisp_Object frame;
888 check_frame_size (f, &height, &width);
890 XSETFRAME (frame, f);
892 if (width != FRAME_WIDTH (f)
893 || height != FRAME_HEIGHT (f)
894 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
895 Fset_frame_size (frame, make_number (width), make_number (height));
897 if ((!NILP (left) || !NILP (top))
898 && ! (left_no_change && top_no_change)
899 && ! (NUMBERP (left) && XINT (left) == f->output_data.mac->left_pos
900 && NUMBERP (top) && XINT (top) == f->output_data.mac->top_pos))
902 int leftpos = 0;
903 int toppos = 0;
905 /* Record the signs. */
906 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
907 if (EQ (left, Qminus))
908 f->output_data.mac->size_hint_flags |= XNegative;
909 else if (INTEGERP (left))
911 leftpos = XINT (left);
912 if (leftpos < 0)
913 f->output_data.mac->size_hint_flags |= XNegative;
915 else if (CONSP (left) && EQ (XCAR (left), Qminus)
916 && CONSP (XCDR (left))
917 && INTEGERP (XCAR (XCDR (left))))
919 leftpos = - XINT (XCAR (XCDR (left)));
920 f->output_data.mac->size_hint_flags |= XNegative;
922 else if (CONSP (left) && EQ (XCAR (left), Qplus)
923 && CONSP (XCDR (left))
924 && INTEGERP (XCAR (XCDR (left))))
926 leftpos = XINT (XCAR (XCDR (left)));
929 if (EQ (top, Qminus))
930 f->output_data.mac->size_hint_flags |= YNegative;
931 else if (INTEGERP (top))
933 toppos = XINT (top);
934 if (toppos < 0)
935 f->output_data.mac->size_hint_flags |= YNegative;
937 else if (CONSP (top) && EQ (XCAR (top), Qminus)
938 && CONSP (XCDR (top))
939 && INTEGERP (XCAR (XCDR (top))))
941 toppos = - XINT (XCAR (XCDR (top)));
942 f->output_data.mac->size_hint_flags |= YNegative;
944 else if (CONSP (top) && EQ (XCAR (top), Qplus)
945 && CONSP (XCDR (top))
946 && INTEGERP (XCAR (XCDR (top))))
948 toppos = XINT (XCAR (XCDR (top)));
952 /* Store the numeric value of the position. */
953 f->output_data.mac->top_pos = toppos;
954 f->output_data.mac->left_pos = leftpos;
956 f->output_data.mac->win_gravity = NorthWestGravity;
958 /* Actually set that position, and convert to absolute. */
959 x_set_offset (f, leftpos, toppos, -1);
962 if ((!NILP (icon_left) || !NILP (icon_top))
963 && ! (icon_left_no_change && icon_top_no_change))
964 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
967 UNGCPRO;
970 /* Store the screen positions of frame F into XPTR and YPTR.
971 These are the positions of the containing window manager window,
972 not Emacs's own window. */
974 void
975 x_real_positions (f, xptr, yptr)
976 FRAME_PTR f;
977 int *xptr, *yptr;
979 Point pt;
980 GrafPtr oldport;
982 #ifdef TARGET_API_MAC_CARBON
984 Rect r;
986 GetWindowPortBounds (f->output_data.mac->mWP, &r);
987 SetPt (&pt, r.left, r.top);
989 #else /* not TARGET_API_MAC_CARBON */
990 SetPt (&pt,
991 f->output_data.mac->mWP->portRect.left,
992 f->output_data.mac->mWP->portRect.top);
993 #endif /* not TARGET_API_MAC_CARBON */
994 GetPort (&oldport);
995 LocalToGlobal (&pt);
996 SetPort (oldport);
998 *xptr = pt.h;
999 *yptr = pt.v;
1002 /* Insert a description of internally-recorded parameters of frame X
1003 into the parameter alist *ALISTPTR that is to be given to the user.
1004 Only parameters that are specific to Mac and whose values are not
1005 correctly recorded in the frame's param_alist need to be considered
1006 here. */
1008 void
1009 x_report_frame_params (f, alistptr)
1010 struct frame *f;
1011 Lisp_Object *alistptr;
1013 char buf[16];
1014 Lisp_Object tem;
1016 /* Represent negative positions (off the top or left screen edge)
1017 in a way that Fmodify_frame_parameters will understand correctly. */
1018 XSETINT (tem, f->output_data.mac->left_pos);
1019 if (f->output_data.mac->left_pos >= 0)
1020 store_in_alist (alistptr, Qleft, tem);
1021 else
1022 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1024 XSETINT (tem, f->output_data.mac->top_pos);
1025 if (f->output_data.mac->top_pos >= 0)
1026 store_in_alist (alistptr, Qtop, tem);
1027 else
1028 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1030 store_in_alist (alistptr, Qborder_width,
1031 make_number (f->output_data.mac->border_width));
1032 store_in_alist (alistptr, Qinternal_border_width,
1033 make_number (f->output_data.mac->internal_border_width));
1034 sprintf (buf, "%ld", (long) FRAME_MAC_WINDOW (f));
1035 store_in_alist (alistptr, Qwindow_id,
1036 build_string (buf));
1037 store_in_alist (alistptr, Qicon_name, f->icon_name);
1038 FRAME_SAMPLE_VISIBILITY (f);
1039 store_in_alist (alistptr, Qvisibility,
1040 (FRAME_VISIBLE_P (f) ? Qt
1041 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1042 store_in_alist (alistptr, Qdisplay,
1043 XCAR (FRAME_MAC_DISPLAY_INFO (f)->name_list_element));
1046 /* The default colors for the Mac color map */
1047 typedef struct colormap_t
1049 unsigned long color;
1050 char *name;
1051 } colormap_t;
1053 colormap_t mac_color_map[] =
1055 { RGB_TO_ULONG(255, 250, 250), "snow" },
1056 { RGB_TO_ULONG(248, 248, 255), "ghost white" },
1057 { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
1058 { RGB_TO_ULONG(245, 245, 245), "white smoke" },
1059 { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
1060 { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
1061 { RGB_TO_ULONG(255, 250, 240), "floral white" },
1062 { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
1063 { RGB_TO_ULONG(253, 245, 230), "old lace" },
1064 { RGB_TO_ULONG(253, 245, 230), "OldLace" },
1065 { RGB_TO_ULONG(250, 240, 230), "linen" },
1066 { RGB_TO_ULONG(250, 235, 215), "antique white" },
1067 { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
1068 { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
1069 { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
1070 { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
1071 { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
1072 { RGB_TO_ULONG(255, 228, 196), "bisque" },
1073 { RGB_TO_ULONG(255, 218, 185), "peach puff" },
1074 { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
1075 { RGB_TO_ULONG(255, 222, 173), "navajo white" },
1076 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
1077 { RGB_TO_ULONG(255, 228, 181), "moccasin" },
1078 { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
1079 { RGB_TO_ULONG(255, 255, 240), "ivory" },
1080 { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
1081 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
1082 { RGB_TO_ULONG(255, 245, 238), "seashell" },
1083 { RGB_TO_ULONG(240, 255, 240), "honeydew" },
1084 { RGB_TO_ULONG(245, 255, 250), "mint cream" },
1085 { RGB_TO_ULONG(245, 255, 250), "MintCream" },
1086 { RGB_TO_ULONG(240, 255, 255), "azure" },
1087 { RGB_TO_ULONG(240, 248, 255), "alice blue" },
1088 { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
1089 { RGB_TO_ULONG(230, 230, 250), "lavender" },
1090 { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
1091 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
1092 { RGB_TO_ULONG(255, 228, 225), "misty rose" },
1093 { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
1094 { RGB_TO_ULONG(255, 255, 255), "white" },
1095 { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
1096 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
1097 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
1098 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
1099 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
1100 { RGB_TO_ULONG(105, 105, 105), "dim gray" },
1101 { RGB_TO_ULONG(105, 105, 105), "DimGray" },
1102 { RGB_TO_ULONG(105, 105, 105), "dim grey" },
1103 { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
1104 { RGB_TO_ULONG(112, 128, 144), "slate gray" },
1105 { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
1106 { RGB_TO_ULONG(112, 128, 144), "slate grey" },
1107 { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
1108 { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
1109 { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
1110 { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
1111 { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
1112 { RGB_TO_ULONG(190, 190, 190), "gray" },
1113 { RGB_TO_ULONG(190, 190, 190), "grey" },
1114 { RGB_TO_ULONG(211, 211, 211), "light grey" },
1115 { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
1116 { RGB_TO_ULONG(211, 211, 211), "light gray" },
1117 { RGB_TO_ULONG(211, 211, 211), "LightGray" },
1118 { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
1119 { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
1120 { RGB_TO_ULONG(0 , 0 , 128), "navy" },
1121 { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
1122 { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
1123 { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
1124 { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
1125 { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
1126 { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
1127 { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
1128 { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
1129 { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
1130 { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
1131 { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
1132 { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
1133 { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
1134 { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
1135 { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
1136 { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
1137 { RGB_TO_ULONG(0 , 0 , 255), "blue" },
1138 { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
1139 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
1140 { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
1141 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
1142 { RGB_TO_ULONG(135, 206, 235), "sky blue" },
1143 { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
1144 { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
1145 { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
1146 { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
1147 { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
1148 { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
1149 { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
1150 { RGB_TO_ULONG(173, 216, 230), "light blue" },
1151 { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
1152 { RGB_TO_ULONG(176, 224, 230), "powder blue" },
1153 { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
1154 { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
1155 { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
1156 { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
1157 { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
1158 { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
1159 { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
1160 { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
1161 { RGB_TO_ULONG(0 , 255, 255), "cyan" },
1162 { RGB_TO_ULONG(224, 255, 255), "light cyan" },
1163 { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
1164 { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
1165 { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
1166 { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
1167 { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
1168 { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
1169 { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
1170 { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
1171 { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
1172 { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
1173 { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
1174 { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
1175 { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
1176 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
1177 { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
1178 { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
1179 { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
1180 { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
1181 { RGB_TO_ULONG(152, 251, 152), "pale green" },
1182 { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
1183 { RGB_TO_ULONG(0 , 255, 127), "spring green" },
1184 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
1185 { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
1186 { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
1187 { RGB_TO_ULONG(0 , 255, 0 ), "green" },
1188 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
1189 { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
1190 { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
1191 { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
1192 { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
1193 { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
1194 { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
1195 { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
1196 { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
1197 { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
1198 { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
1199 { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
1200 { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
1201 { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
1202 { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
1203 { RGB_TO_ULONG(240, 230, 140), "khaki" },
1204 { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
1205 { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
1206 { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
1207 { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
1208 { RGB_TO_ULONG(255, 255, 224), "light yellow" },
1209 { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
1210 { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
1211 { RGB_TO_ULONG(255, 215, 0 ), "gold" },
1212 { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
1213 { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
1214 { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
1215 { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
1216 { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
1217 { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
1218 { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
1219 { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
1220 { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
1221 { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
1222 { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
1223 { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
1224 { RGB_TO_ULONG(205, 133, 63 ), "peru" },
1225 { RGB_TO_ULONG(222, 184, 135), "burlywood" },
1226 { RGB_TO_ULONG(245, 245, 220), "beige" },
1227 { RGB_TO_ULONG(245, 222, 179), "wheat" },
1228 { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
1229 { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
1230 { RGB_TO_ULONG(210, 180, 140), "tan" },
1231 { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
1232 { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
1233 { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
1234 { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
1235 { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
1236 { RGB_TO_ULONG(250, 128, 114), "salmon" },
1237 { RGB_TO_ULONG(255, 160, 122), "light salmon" },
1238 { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
1239 { RGB_TO_ULONG(255, 165, 0 ), "orange" },
1240 { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
1241 { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
1242 { RGB_TO_ULONG(255, 127, 80 ), "coral" },
1243 { RGB_TO_ULONG(240, 128, 128), "light coral" },
1244 { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
1245 { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
1246 { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
1247 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
1248 { RGB_TO_ULONG(255, 0 , 0 ), "red" },
1249 { RGB_TO_ULONG(255, 105, 180), "hot pink" },
1250 { RGB_TO_ULONG(255, 105, 180), "HotPink" },
1251 { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
1252 { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
1253 { RGB_TO_ULONG(255, 192, 203), "pink" },
1254 { RGB_TO_ULONG(255, 182, 193), "light pink" },
1255 { RGB_TO_ULONG(255, 182, 193), "LightPink" },
1256 { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
1257 { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
1258 { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
1259 { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
1260 { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
1261 { RGB_TO_ULONG(208, 32 , 144), "violet red" },
1262 { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
1263 { RGB_TO_ULONG(255, 0 , 255), "magenta" },
1264 { RGB_TO_ULONG(238, 130, 238), "violet" },
1265 { RGB_TO_ULONG(221, 160, 221), "plum" },
1266 { RGB_TO_ULONG(218, 112, 214), "orchid" },
1267 { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
1268 { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
1269 { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
1270 { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
1271 { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
1272 { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
1273 { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
1274 { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
1275 { RGB_TO_ULONG(160, 32 , 240), "purple" },
1276 { RGB_TO_ULONG(147, 112, 219), "medium purple" },
1277 { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
1278 { RGB_TO_ULONG(216, 191, 216), "thistle" },
1279 { RGB_TO_ULONG(255, 250, 250), "snow1" },
1280 { RGB_TO_ULONG(238, 233, 233), "snow2" },
1281 { RGB_TO_ULONG(205, 201, 201), "snow3" },
1282 { RGB_TO_ULONG(139, 137, 137), "snow4" },
1283 { RGB_TO_ULONG(255, 245, 238), "seashell1" },
1284 { RGB_TO_ULONG(238, 229, 222), "seashell2" },
1285 { RGB_TO_ULONG(205, 197, 191), "seashell3" },
1286 { RGB_TO_ULONG(139, 134, 130), "seashell4" },
1287 { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
1288 { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
1289 { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
1290 { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
1291 { RGB_TO_ULONG(255, 228, 196), "bisque1" },
1292 { RGB_TO_ULONG(238, 213, 183), "bisque2" },
1293 { RGB_TO_ULONG(205, 183, 158), "bisque3" },
1294 { RGB_TO_ULONG(139, 125, 107), "bisque4" },
1295 { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
1296 { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
1297 { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
1298 { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
1299 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
1300 { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
1301 { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
1302 { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
1303 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
1304 { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
1305 { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
1306 { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
1307 { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
1308 { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
1309 { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
1310 { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
1311 { RGB_TO_ULONG(255, 255, 240), "ivory1" },
1312 { RGB_TO_ULONG(238, 238, 224), "ivory2" },
1313 { RGB_TO_ULONG(205, 205, 193), "ivory3" },
1314 { RGB_TO_ULONG(139, 139, 131), "ivory4" },
1315 { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
1316 { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
1317 { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
1318 { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
1319 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
1320 { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
1321 { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
1322 { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
1323 { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
1324 { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
1325 { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
1326 { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
1327 { RGB_TO_ULONG(240, 255, 255), "azure1" },
1328 { RGB_TO_ULONG(224, 238, 238), "azure2" },
1329 { RGB_TO_ULONG(193, 205, 205), "azure3" },
1330 { RGB_TO_ULONG(131, 139, 139), "azure4" },
1331 { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
1332 { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
1333 { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
1334 { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
1335 { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
1336 { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
1337 { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
1338 { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
1339 { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
1340 { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
1341 { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
1342 { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
1343 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
1344 { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
1345 { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
1346 { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
1347 { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
1348 { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
1349 { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
1350 { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
1351 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
1352 { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
1353 { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
1354 { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
1355 { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
1356 { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
1357 { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
1358 { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
1359 { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
1360 { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
1361 { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
1362 { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
1363 { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
1364 { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
1365 { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
1366 { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
1367 { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
1368 { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
1369 { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
1370 { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
1371 { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
1372 { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
1373 { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
1374 { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
1375 { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
1376 { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
1377 { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
1378 { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
1379 { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
1380 { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
1381 { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
1382 { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
1383 { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
1384 { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
1385 { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
1386 { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
1387 { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
1388 { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
1389 { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
1390 { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
1391 { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
1392 { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
1393 { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
1394 { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
1395 { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
1396 { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
1397 { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
1398 { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
1399 { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
1400 { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
1401 { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
1402 { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
1403 { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
1404 { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
1405 { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
1406 { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
1407 { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
1408 { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
1409 { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
1410 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
1411 { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
1412 { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
1413 { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
1414 { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
1415 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
1416 { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
1417 { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
1418 { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
1419 { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
1420 { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
1421 { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
1422 { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
1423 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
1424 { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
1425 { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
1426 { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
1427 { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
1428 { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
1429 { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
1430 { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
1431 { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
1432 { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
1433 { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
1434 { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
1435 { RGB_TO_ULONG(255, 246, 143), "khaki1" },
1436 { RGB_TO_ULONG(238, 230, 133), "khaki2" },
1437 { RGB_TO_ULONG(205, 198, 115), "khaki3" },
1438 { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
1439 { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
1440 { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
1441 { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
1442 { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
1443 { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
1444 { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
1445 { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
1446 { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
1447 { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
1448 { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
1449 { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
1450 { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
1451 { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
1452 { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
1453 { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
1454 { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
1455 { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
1456 { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
1457 { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
1458 { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
1459 { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
1460 { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
1461 { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
1462 { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
1463 { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
1464 { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
1465 { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
1466 { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
1467 { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
1468 { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
1469 { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
1470 { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
1471 { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
1472 { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
1473 { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
1474 { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
1475 { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
1476 { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
1477 { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
1478 { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
1479 { RGB_TO_ULONG(255, 231, 186), "wheat1" },
1480 { RGB_TO_ULONG(238, 216, 174), "wheat2" },
1481 { RGB_TO_ULONG(205, 186, 150), "wheat3" },
1482 { RGB_TO_ULONG(139, 126, 102), "wheat4" },
1483 { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
1484 { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
1485 { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
1486 { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
1487 { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
1488 { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
1489 { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
1490 { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
1491 { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
1492 { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
1493 { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
1494 { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
1495 { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
1496 { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
1497 { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
1498 { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
1499 { RGB_TO_ULONG(255, 140, 105), "salmon1" },
1500 { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
1501 { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
1502 { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
1503 { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
1504 { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
1505 { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
1506 { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
1507 { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
1508 { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
1509 { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
1510 { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
1511 { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
1512 { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
1513 { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
1514 { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
1515 { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
1516 { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
1517 { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
1518 { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
1519 { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
1520 { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
1521 { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
1522 { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
1523 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
1524 { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
1525 { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
1526 { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
1527 { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
1528 { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
1529 { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
1530 { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
1531 { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
1532 { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
1533 { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
1534 { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
1535 { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
1536 { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
1537 { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
1538 { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
1539 { RGB_TO_ULONG(255, 181, 197), "pink1" },
1540 { RGB_TO_ULONG(238, 169, 184), "pink2" },
1541 { RGB_TO_ULONG(205, 145, 158), "pink3" },
1542 { RGB_TO_ULONG(139, 99 , 108), "pink4" },
1543 { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
1544 { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
1545 { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
1546 { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
1547 { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
1548 { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
1549 { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
1550 { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
1551 { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
1552 { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
1553 { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
1554 { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
1555 { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
1556 { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
1557 { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
1558 { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
1559 { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
1560 { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
1561 { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
1562 { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
1563 { RGB_TO_ULONG(255, 131, 250), "orchid1" },
1564 { RGB_TO_ULONG(238, 122, 233), "orchid2" },
1565 { RGB_TO_ULONG(205, 105, 201), "orchid3" },
1566 { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
1567 { RGB_TO_ULONG(255, 187, 255), "plum1" },
1568 { RGB_TO_ULONG(238, 174, 238), "plum2" },
1569 { RGB_TO_ULONG(205, 150, 205), "plum3" },
1570 { RGB_TO_ULONG(139, 102, 139), "plum4" },
1571 { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
1572 { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
1573 { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
1574 { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
1575 { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
1576 { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
1577 { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
1578 { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
1579 { RGB_TO_ULONG(155, 48 , 255), "purple1" },
1580 { RGB_TO_ULONG(145, 44 , 238), "purple2" },
1581 { RGB_TO_ULONG(125, 38 , 205), "purple3" },
1582 { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
1583 { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
1584 { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
1585 { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
1586 { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
1587 { RGB_TO_ULONG(255, 225, 255), "thistle1" },
1588 { RGB_TO_ULONG(238, 210, 238), "thistle2" },
1589 { RGB_TO_ULONG(205, 181, 205), "thistle3" },
1590 { RGB_TO_ULONG(139, 123, 139), "thistle4" },
1591 { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
1592 { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
1593 { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
1594 { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
1595 { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
1596 { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
1597 { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
1598 { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
1599 { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
1600 { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
1601 { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
1602 { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
1603 { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
1604 { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
1605 { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
1606 { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
1607 { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
1608 { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
1609 { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
1610 { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
1611 { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
1612 { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
1613 { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
1614 { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
1615 { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
1616 { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
1617 { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
1618 { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
1619 { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
1620 { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
1621 { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
1622 { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
1623 { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
1624 { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
1625 { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
1626 { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
1627 { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
1628 { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
1629 { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
1630 { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
1631 { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
1632 { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
1633 { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
1634 { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
1635 { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
1636 { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
1637 { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
1638 { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
1639 { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
1640 { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
1641 { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
1642 { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
1643 { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
1644 { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
1645 { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
1646 { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
1647 { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
1648 { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
1649 { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
1650 { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
1651 { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
1652 { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
1653 { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
1654 { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
1655 { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
1656 { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
1657 { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
1658 { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
1659 { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
1660 { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
1661 { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
1662 { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
1663 { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
1664 { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
1665 { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
1666 { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
1667 { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
1668 { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
1669 { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
1670 { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
1671 { RGB_TO_ULONG(102, 102, 102), "gray40" },
1672 { RGB_TO_ULONG(102, 102, 102), "grey40" },
1673 { RGB_TO_ULONG(105, 105, 105), "gray41" },
1674 { RGB_TO_ULONG(105, 105, 105), "grey41" },
1675 { RGB_TO_ULONG(107, 107, 107), "gray42" },
1676 { RGB_TO_ULONG(107, 107, 107), "grey42" },
1677 { RGB_TO_ULONG(110, 110, 110), "gray43" },
1678 { RGB_TO_ULONG(110, 110, 110), "grey43" },
1679 { RGB_TO_ULONG(112, 112, 112), "gray44" },
1680 { RGB_TO_ULONG(112, 112, 112), "grey44" },
1681 { RGB_TO_ULONG(115, 115, 115), "gray45" },
1682 { RGB_TO_ULONG(115, 115, 115), "grey45" },
1683 { RGB_TO_ULONG(117, 117, 117), "gray46" },
1684 { RGB_TO_ULONG(117, 117, 117), "grey46" },
1685 { RGB_TO_ULONG(120, 120, 120), "gray47" },
1686 { RGB_TO_ULONG(120, 120, 120), "grey47" },
1687 { RGB_TO_ULONG(122, 122, 122), "gray48" },
1688 { RGB_TO_ULONG(122, 122, 122), "grey48" },
1689 { RGB_TO_ULONG(125, 125, 125), "gray49" },
1690 { RGB_TO_ULONG(125, 125, 125), "grey49" },
1691 { RGB_TO_ULONG(127, 127, 127), "gray50" },
1692 { RGB_TO_ULONG(127, 127, 127), "grey50" },
1693 { RGB_TO_ULONG(130, 130, 130), "gray51" },
1694 { RGB_TO_ULONG(130, 130, 130), "grey51" },
1695 { RGB_TO_ULONG(133, 133, 133), "gray52" },
1696 { RGB_TO_ULONG(133, 133, 133), "grey52" },
1697 { RGB_TO_ULONG(135, 135, 135), "gray53" },
1698 { RGB_TO_ULONG(135, 135, 135), "grey53" },
1699 { RGB_TO_ULONG(138, 138, 138), "gray54" },
1700 { RGB_TO_ULONG(138, 138, 138), "grey54" },
1701 { RGB_TO_ULONG(140, 140, 140), "gray55" },
1702 { RGB_TO_ULONG(140, 140, 140), "grey55" },
1703 { RGB_TO_ULONG(143, 143, 143), "gray56" },
1704 { RGB_TO_ULONG(143, 143, 143), "grey56" },
1705 { RGB_TO_ULONG(145, 145, 145), "gray57" },
1706 { RGB_TO_ULONG(145, 145, 145), "grey57" },
1707 { RGB_TO_ULONG(148, 148, 148), "gray58" },
1708 { RGB_TO_ULONG(148, 148, 148), "grey58" },
1709 { RGB_TO_ULONG(150, 150, 150), "gray59" },
1710 { RGB_TO_ULONG(150, 150, 150), "grey59" },
1711 { RGB_TO_ULONG(153, 153, 153), "gray60" },
1712 { RGB_TO_ULONG(153, 153, 153), "grey60" },
1713 { RGB_TO_ULONG(156, 156, 156), "gray61" },
1714 { RGB_TO_ULONG(156, 156, 156), "grey61" },
1715 { RGB_TO_ULONG(158, 158, 158), "gray62" },
1716 { RGB_TO_ULONG(158, 158, 158), "grey62" },
1717 { RGB_TO_ULONG(161, 161, 161), "gray63" },
1718 { RGB_TO_ULONG(161, 161, 161), "grey63" },
1719 { RGB_TO_ULONG(163, 163, 163), "gray64" },
1720 { RGB_TO_ULONG(163, 163, 163), "grey64" },
1721 { RGB_TO_ULONG(166, 166, 166), "gray65" },
1722 { RGB_TO_ULONG(166, 166, 166), "grey65" },
1723 { RGB_TO_ULONG(168, 168, 168), "gray66" },
1724 { RGB_TO_ULONG(168, 168, 168), "grey66" },
1725 { RGB_TO_ULONG(171, 171, 171), "gray67" },
1726 { RGB_TO_ULONG(171, 171, 171), "grey67" },
1727 { RGB_TO_ULONG(173, 173, 173), "gray68" },
1728 { RGB_TO_ULONG(173, 173, 173), "grey68" },
1729 { RGB_TO_ULONG(176, 176, 176), "gray69" },
1730 { RGB_TO_ULONG(176, 176, 176), "grey69" },
1731 { RGB_TO_ULONG(179, 179, 179), "gray70" },
1732 { RGB_TO_ULONG(179, 179, 179), "grey70" },
1733 { RGB_TO_ULONG(181, 181, 181), "gray71" },
1734 { RGB_TO_ULONG(181, 181, 181), "grey71" },
1735 { RGB_TO_ULONG(184, 184, 184), "gray72" },
1736 { RGB_TO_ULONG(184, 184, 184), "grey72" },
1737 { RGB_TO_ULONG(186, 186, 186), "gray73" },
1738 { RGB_TO_ULONG(186, 186, 186), "grey73" },
1739 { RGB_TO_ULONG(189, 189, 189), "gray74" },
1740 { RGB_TO_ULONG(189, 189, 189), "grey74" },
1741 { RGB_TO_ULONG(191, 191, 191), "gray75" },
1742 { RGB_TO_ULONG(191, 191, 191), "grey75" },
1743 { RGB_TO_ULONG(194, 194, 194), "gray76" },
1744 { RGB_TO_ULONG(194, 194, 194), "grey76" },
1745 { RGB_TO_ULONG(196, 196, 196), "gray77" },
1746 { RGB_TO_ULONG(196, 196, 196), "grey77" },
1747 { RGB_TO_ULONG(199, 199, 199), "gray78" },
1748 { RGB_TO_ULONG(199, 199, 199), "grey78" },
1749 { RGB_TO_ULONG(201, 201, 201), "gray79" },
1750 { RGB_TO_ULONG(201, 201, 201), "grey79" },
1751 { RGB_TO_ULONG(204, 204, 204), "gray80" },
1752 { RGB_TO_ULONG(204, 204, 204), "grey80" },
1753 { RGB_TO_ULONG(207, 207, 207), "gray81" },
1754 { RGB_TO_ULONG(207, 207, 207), "grey81" },
1755 { RGB_TO_ULONG(209, 209, 209), "gray82" },
1756 { RGB_TO_ULONG(209, 209, 209), "grey82" },
1757 { RGB_TO_ULONG(212, 212, 212), "gray83" },
1758 { RGB_TO_ULONG(212, 212, 212), "grey83" },
1759 { RGB_TO_ULONG(214, 214, 214), "gray84" },
1760 { RGB_TO_ULONG(214, 214, 214), "grey84" },
1761 { RGB_TO_ULONG(217, 217, 217), "gray85" },
1762 { RGB_TO_ULONG(217, 217, 217), "grey85" },
1763 { RGB_TO_ULONG(219, 219, 219), "gray86" },
1764 { RGB_TO_ULONG(219, 219, 219), "grey86" },
1765 { RGB_TO_ULONG(222, 222, 222), "gray87" },
1766 { RGB_TO_ULONG(222, 222, 222), "grey87" },
1767 { RGB_TO_ULONG(224, 224, 224), "gray88" },
1768 { RGB_TO_ULONG(224, 224, 224), "grey88" },
1769 { RGB_TO_ULONG(227, 227, 227), "gray89" },
1770 { RGB_TO_ULONG(227, 227, 227), "grey89" },
1771 { RGB_TO_ULONG(229, 229, 229), "gray90" },
1772 { RGB_TO_ULONG(229, 229, 229), "grey90" },
1773 { RGB_TO_ULONG(232, 232, 232), "gray91" },
1774 { RGB_TO_ULONG(232, 232, 232), "grey91" },
1775 { RGB_TO_ULONG(235, 235, 235), "gray92" },
1776 { RGB_TO_ULONG(235, 235, 235), "grey92" },
1777 { RGB_TO_ULONG(237, 237, 237), "gray93" },
1778 { RGB_TO_ULONG(237, 237, 237), "grey93" },
1779 { RGB_TO_ULONG(240, 240, 240), "gray94" },
1780 { RGB_TO_ULONG(240, 240, 240), "grey94" },
1781 { RGB_TO_ULONG(242, 242, 242), "gray95" },
1782 { RGB_TO_ULONG(242, 242, 242), "grey95" },
1783 { RGB_TO_ULONG(245, 245, 245), "gray96" },
1784 { RGB_TO_ULONG(245, 245, 245), "grey96" },
1785 { RGB_TO_ULONG(247, 247, 247), "gray97" },
1786 { RGB_TO_ULONG(247, 247, 247), "grey97" },
1787 { RGB_TO_ULONG(250, 250, 250), "gray98" },
1788 { RGB_TO_ULONG(250, 250, 250), "grey98" },
1789 { RGB_TO_ULONG(252, 252, 252), "gray99" },
1790 { RGB_TO_ULONG(252, 252, 252), "grey99" },
1791 { RGB_TO_ULONG(255, 255, 255), "gray100" },
1792 { RGB_TO_ULONG(255, 255, 255), "grey100" },
1793 { RGB_TO_ULONG(169, 169, 169), "dark grey" },
1794 { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
1795 { RGB_TO_ULONG(169, 169, 169), "dark gray" },
1796 { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
1797 { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
1798 { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
1799 { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
1800 { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
1801 { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
1802 { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
1803 { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
1804 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1805 { RGB_TO_ULONG(144, 238, 144), "light green" },
1806 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1809 unsigned long
1810 mac_color_map_lookup (colorname)
1811 char *colorname;
1813 Lisp_Object ret = Qnil;
1814 int i;
1816 BLOCK_INPUT;
1818 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
1819 if (stricmp (colorname, mac_color_map[i].name) == 0)
1821 ret = mac_color_map[i].color;
1822 break;
1825 UNBLOCK_INPUT;
1827 return ret;
1830 Lisp_Object
1831 x_to_mac_color (colorname)
1832 char * colorname;
1834 register Lisp_Object tail, ret = Qnil;
1836 BLOCK_INPUT;
1838 if (colorname[0] == '#')
1840 /* Could be an old-style RGB Device specification. */
1841 char *color;
1842 int size;
1843 color = colorname + 1;
1845 size = strlen(color);
1846 if (size == 3 || size == 6 || size == 9 || size == 12)
1848 unsigned long colorval;
1849 int i, pos;
1850 pos = 0;
1851 size /= 3;
1852 colorval = 0;
1854 for (i = 0; i < 3; i++)
1856 char *end;
1857 char t;
1858 unsigned long value;
1860 /* The check for 'x' in the following conditional takes into
1861 account the fact that strtol allows a "0x" in front of
1862 our numbers, and we don't. */
1863 if (!isxdigit(color[0]) || color[1] == 'x')
1864 break;
1865 t = color[size];
1866 color[size] = '\0';
1867 value = strtoul(color, &end, 16);
1868 color[size] = t;
1869 if (errno == ERANGE || end - color != size)
1870 break;
1871 switch (size)
1873 case 1:
1874 value = value * 0x10;
1875 break;
1876 case 2:
1877 break;
1878 case 3:
1879 value /= 0x10;
1880 break;
1881 case 4:
1882 value /= 0x100;
1883 break;
1885 colorval |= (value << pos);
1886 pos += 0x8;
1887 if (i == 2)
1889 UNBLOCK_INPUT;
1890 return (colorval);
1892 color = end;
1896 else if (strnicmp(colorname, "rgb:", 4) == 0)
1898 char *color;
1899 unsigned long colorval;
1900 int i, pos;
1901 pos = 0;
1903 colorval = 0;
1904 color = colorname + 4;
1905 for (i = 0; i < 3; i++)
1907 char *end;
1908 unsigned long value;
1910 /* The check for 'x' in the following conditional takes into
1911 account the fact that strtol allows a "0x" in front of
1912 our numbers, and we don't. */
1913 if (!isxdigit(color[0]) || color[1] == 'x')
1914 break;
1915 value = strtoul(color, &end, 16);
1916 if (errno == ERANGE)
1917 break;
1918 switch (end - color)
1920 case 1:
1921 value = value * 0x10 + value;
1922 break;
1923 case 2:
1924 break;
1925 case 3:
1926 value /= 0x10;
1927 break;
1928 case 4:
1929 value /= 0x100;
1930 break;
1931 default:
1932 value = ULONG_MAX;
1934 if (value == ULONG_MAX)
1935 break;
1936 colorval |= (value << pos);
1937 pos += 0x8;
1938 if (i == 2)
1940 if (*end != '\0')
1941 break;
1942 UNBLOCK_INPUT;
1943 return (colorval);
1945 if (*end != '/')
1946 break;
1947 color = end + 1;
1950 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1952 /* This is an RGB Intensity specification. */
1953 char *color;
1954 unsigned long colorval;
1955 int i, pos;
1956 pos = 0;
1958 colorval = 0;
1959 color = colorname + 5;
1960 for (i = 0; i < 3; i++)
1962 char *end;
1963 double value;
1964 unsigned long val;
1966 value = strtod(color, &end);
1967 if (errno == ERANGE)
1968 break;
1969 if (value < 0.0 || value > 1.0)
1970 break;
1971 val = (unsigned long)(0x100 * value);
1972 /* We used 0x100 instead of 0xFF to give an continuous
1973 range between 0.0 and 1.0 inclusive. The next statement
1974 fixes the 1.0 case. */
1975 if (val == 0x100)
1976 val = 0xFF;
1977 colorval |= (val << pos);
1978 pos += 0x8;
1979 if (i == 2)
1981 if (*end != '\0')
1982 break;
1983 UNBLOCK_INPUT;
1984 return (colorval);
1986 if (*end != '/')
1987 break;
1988 color = end + 1;
1992 ret = mac_color_map_lookup (colorname);
1994 UNBLOCK_INPUT;
1995 return ret;
1998 /* Gamma-correct COLOR on frame F. */
2000 void
2001 gamma_correct (f, color)
2002 struct frame *f;
2003 unsigned long *color;
2005 if (f->gamma)
2007 unsigned long red, green, blue;
2009 red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2010 green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2011 blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2012 *color = RGB_TO_ULONG (red, green, blue);
2016 /* Decide if color named COLOR is valid for the display associated
2017 with the selected frame; if so, return the rgb values in COLOR_DEF.
2018 If ALLOC is nonzero, allocate a new colormap cell. */
2021 mac_defined_color (f, color, color_def, alloc)
2022 FRAME_PTR f;
2023 char *color;
2024 XColor *color_def;
2025 int alloc;
2027 register Lisp_Object tem;
2028 unsigned long mac_color_ref;
2030 tem = x_to_mac_color (color);
2032 if (!NILP (tem))
2034 if (f)
2036 /* Apply gamma correction. */
2037 mac_color_ref = XUINT (tem);
2038 gamma_correct (f, &mac_color_ref);
2039 XSETINT (tem, mac_color_ref);
2042 color_def->pixel = mac_color_ref;
2043 color_def->red = RED_FROM_ULONG (mac_color_ref);
2044 color_def->green = GREEN_FROM_ULONG (mac_color_ref);
2045 color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
2047 return 1;
2049 else
2051 return 0;
2055 /* Given a string ARG naming a color, compute a pixel value from it
2056 suitable for screen F.
2057 If F is not a color screen, return DEF (default) regardless of what
2058 ARG says. */
2061 x_decode_color (f, arg, def)
2062 FRAME_PTR f;
2063 Lisp_Object arg;
2064 int def;
2066 XColor cdef;
2068 CHECK_STRING (arg);
2070 if (strcmp (SDATA (arg), "black") == 0)
2071 return BLACK_PIX_DEFAULT (f);
2072 else if (strcmp (SDATA (arg), "white") == 0)
2073 return WHITE_PIX_DEFAULT (f);
2075 #if 0
2076 if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
2077 * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
2078 return def;
2079 #endif
2081 if (mac_defined_color (f, SDATA (arg), &cdef, 1))
2082 return cdef.pixel;
2084 /* defined_color failed; return an ultimate default. */
2085 return def;
2088 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
2089 the previous value of that parameter, NEW_VALUE is the new value. */
2091 static void
2092 x_set_line_spacing (f, new_value, old_value)
2093 struct frame *f;
2094 Lisp_Object new_value, old_value;
2096 if (NILP (new_value))
2097 f->extra_line_spacing = 0;
2098 else if (NATNUMP (new_value))
2099 f->extra_line_spacing = XFASTINT (new_value);
2100 else
2101 Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
2102 Fcons (new_value, Qnil)));
2103 if (FRAME_VISIBLE_P (f))
2104 redraw_frame (f);
2108 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
2109 the previous value of that parameter, NEW_VALUE is the new value. */
2111 static void
2112 x_set_screen_gamma (f, new_value, old_value)
2113 struct frame *f;
2114 Lisp_Object new_value, old_value;
2116 if (NILP (new_value))
2117 f->gamma = 0;
2118 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
2119 /* The value 0.4545 is the normal viewing gamma. */
2120 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
2121 else
2122 Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
2123 Fcons (new_value, Qnil)));
2125 clear_face_cache (0);
2129 /* Functions called only from `x_set_frame_param'
2130 to set individual parameters.
2132 If FRAME_MAC_WINDOW (f) is 0,
2133 the frame is being created and its window does not exist yet.
2134 In that case, just record the parameter's new value
2135 in the standard place; do not attempt to change the window. */
2137 void
2138 x_set_foreground_color (f, arg, oldval)
2139 struct frame *f;
2140 Lisp_Object arg, oldval;
2142 FRAME_FOREGROUND_PIXEL (f)
2143 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2145 if (FRAME_MAC_WINDOW (f) != 0)
2147 update_face_from_frame_parameter (f, Qforeground_color, arg);
2148 if (FRAME_VISIBLE_P (f))
2149 redraw_frame (f);
2153 void
2154 x_set_background_color (f, arg, oldval)
2155 struct frame *f;
2156 Lisp_Object arg, oldval;
2158 FRAME_BACKGROUND_PIXEL (f)
2159 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
2161 if (FRAME_MAC_WINDOW (f) != 0)
2163 update_face_from_frame_parameter (f, Qbackground_color, arg);
2165 if (FRAME_VISIBLE_P (f))
2166 redraw_frame (f);
2170 void
2171 x_set_mouse_color (f, arg, oldval)
2172 struct frame *f;
2173 Lisp_Object arg, oldval;
2175 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
2176 int count;
2177 int mask_color;
2179 if (!EQ (Qnil, arg))
2180 f->output_data.mac->mouse_pixel
2181 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2182 mask_color = FRAME_BACKGROUND_PIXEL (f);
2184 /* Don't let pointers be invisible. */
2185 if (mask_color == f->output_data.mac->mouse_pixel
2186 && mask_color == FRAME_BACKGROUND_PIXEL (f))
2187 f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
2189 #if 0 /* MAC_TODO : cursor changes */
2190 BLOCK_INPUT;
2192 /* It's not okay to crash if the user selects a screwy cursor. */
2193 count = x_catch_errors (FRAME_W32_DISPLAY (f));
2195 if (!EQ (Qnil, Vx_pointer_shape))
2197 CHECK_NUMBER (Vx_pointer_shape);
2198 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
2200 else
2201 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2202 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
2204 if (!EQ (Qnil, Vx_nontext_pointer_shape))
2206 CHECK_NUMBER (Vx_nontext_pointer_shape);
2207 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2208 XINT (Vx_nontext_pointer_shape));
2210 else
2211 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
2212 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2214 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
2216 CHECK_NUMBER (Vx_hourglass_pointer_shape);
2217 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2218 XINT (Vx_hourglass_pointer_shape));
2220 else
2221 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
2222 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
2224 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2225 if (!EQ (Qnil, Vx_mode_pointer_shape))
2227 CHECK_NUMBER (Vx_mode_pointer_shape);
2228 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2229 XINT (Vx_mode_pointer_shape));
2231 else
2232 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2233 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
2235 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
2237 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
2238 cross_cursor
2239 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2240 XINT (Vx_sensitive_text_pointer_shape));
2242 else
2243 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
2245 if (!NILP (Vx_window_horizontal_drag_shape))
2247 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
2248 horizontal_drag_cursor
2249 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2250 XINT (Vx_window_horizontal_drag_shape));
2252 else
2253 horizontal_drag_cursor
2254 = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
2256 /* Check and report errors with the above calls. */
2257 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
2258 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
2261 XColor fore_color, back_color;
2263 fore_color.pixel = f->output_data.w32->mouse_pixel;
2264 back_color.pixel = mask_color;
2265 XQueryColor (FRAME_W32_DISPLAY (f),
2266 DefaultColormap (FRAME_W32_DISPLAY (f),
2267 DefaultScreen (FRAME_W32_DISPLAY (f))),
2268 &fore_color);
2269 XQueryColor (FRAME_W32_DISPLAY (f),
2270 DefaultColormap (FRAME_W32_DISPLAY (f),
2271 DefaultScreen (FRAME_W32_DISPLAY (f))),
2272 &back_color);
2273 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
2274 &fore_color, &back_color);
2275 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
2276 &fore_color, &back_color);
2277 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
2278 &fore_color, &back_color);
2279 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
2280 &fore_color, &back_color);
2281 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
2282 &fore_color, &back_color);
2285 if (FRAME_W32_WINDOW (f) != 0)
2286 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
2288 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
2289 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
2290 f->output_data.w32->text_cursor = cursor;
2292 if (nontext_cursor != f->output_data.w32->nontext_cursor
2293 && f->output_data.w32->nontext_cursor != 0)
2294 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
2295 f->output_data.w32->nontext_cursor = nontext_cursor;
2297 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
2298 && f->output_data.w32->hourglass_cursor != 0)
2299 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
2300 f->output_data.w32->hourglass_cursor = hourglass_cursor;
2302 if (mode_cursor != f->output_data.w32->modeline_cursor
2303 && f->output_data.w32->modeline_cursor != 0)
2304 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
2305 f->output_data.w32->modeline_cursor = mode_cursor;
2307 if (cross_cursor != f->output_data.w32->cross_cursor
2308 && f->output_data.w32->cross_cursor != 0)
2309 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
2310 f->output_data.w32->cross_cursor = cross_cursor;
2312 XFlush (FRAME_W32_DISPLAY (f));
2313 UNBLOCK_INPUT;
2315 update_face_from_frame_parameter (f, Qmouse_color, arg);
2316 #endif /* MAC_TODO */
2319 void
2320 x_set_cursor_color (f, arg, oldval)
2321 struct frame *f;
2322 Lisp_Object arg, oldval;
2324 unsigned long fore_pixel;
2326 if (!NILP (Vx_cursor_fore_pixel))
2327 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
2328 WHITE_PIX_DEFAULT (f));
2329 else
2330 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2331 f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2333 /* Make sure that the cursor color differs from the background color. */
2334 if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
2336 f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
2337 if (f->output_data.mac->cursor_pixel == fore_pixel)
2338 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2340 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
2342 #if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
2343 if (FRAME_MAC_WINDOW (f) != 0)
2345 if (FRAME_VISIBLE_P (f))
2347 x_display_cursor (f, 0);
2348 x_display_cursor (f, 1);
2351 #endif
2353 update_face_from_frame_parameter (f, Qcursor_color, arg);
2356 /* Set the border-color of frame F to pixel value PIX.
2357 Note that this does not fully take effect if done before
2358 F has an window. */
2359 void
2360 x_set_border_pixel (f, pix)
2361 struct frame *f;
2362 int pix;
2364 f->output_data.mac->border_pixel = pix;
2366 if (FRAME_MAC_WINDOW (f) != 0 && f->output_data.mac->border_width > 0)
2368 if (FRAME_VISIBLE_P (f))
2369 redraw_frame (f);
2373 /* Set the border-color of frame F to value described by ARG.
2374 ARG can be a string naming a color.
2375 The border-color is used for the border that is drawn by the server.
2376 Note that this does not fully take effect if done before
2377 F has a window; it must be redone when the window is created. */
2379 void
2380 x_set_border_color (f, arg, oldval)
2381 struct frame *f;
2382 Lisp_Object arg, oldval;
2384 int pix;
2386 CHECK_STRING (arg);
2387 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2388 x_set_border_pixel (f, pix);
2389 update_face_from_frame_parameter (f, Qborder_color, arg);
2392 void
2393 x_set_cursor_type (f, arg, oldval)
2394 FRAME_PTR f;
2395 Lisp_Object arg, oldval;
2397 set_frame_cursor_types (f, arg);
2399 /* Make sure the cursor gets redrawn. This is overkill, but how
2400 often do people change cursor types? */
2401 update_mode_lines++;
2404 #if 0 /* MAC_TODO: really no icon for Mac */
2405 void
2406 x_set_icon_type (f, arg, oldval)
2407 struct frame *f;
2408 Lisp_Object arg, oldval;
2410 int result;
2412 if (NILP (arg) && NILP (oldval))
2413 return;
2415 if (STRINGP (arg) && STRINGP (oldval)
2416 && EQ (Fstring_equal (oldval, arg), Qt))
2417 return;
2419 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2420 return;
2422 BLOCK_INPUT;
2424 result = x_bitmap_icon (f, arg);
2425 if (result)
2427 UNBLOCK_INPUT;
2428 error ("No icon window available");
2431 UNBLOCK_INPUT;
2433 #endif /* MAC_TODO */
2435 /* Return non-nil if frame F wants a bitmap icon. */
2437 Lisp_Object
2438 x_icon_type (f)
2439 FRAME_PTR f;
2441 Lisp_Object tem;
2443 tem = assq_no_quit (Qicon_type, f->param_alist);
2444 if (CONSP (tem))
2445 return XCDR (tem);
2446 else
2447 return Qnil;
2450 void
2451 x_set_icon_name (f, arg, oldval)
2452 struct frame *f;
2453 Lisp_Object arg, oldval;
2455 int result;
2457 if (STRINGP (arg))
2459 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2460 return;
2462 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2463 return;
2465 f->icon_name = arg;
2467 #if 0 /* MAC_TODO */
2468 if (f->output_data.w32->icon_bitmap != 0)
2469 return;
2471 BLOCK_INPUT;
2473 result = x_text_icon (f,
2474 (char *) SDATA ((!NILP (f->icon_name)
2475 ? f->icon_name
2476 : !NILP (f->title)
2477 ? f->title
2478 : f->name)));
2480 if (result)
2482 UNBLOCK_INPUT;
2483 error ("No icon window available");
2486 /* If the window was unmapped (and its icon was mapped),
2487 the new icon is not mapped, so map the window in its stead. */
2488 if (FRAME_VISIBLE_P (f))
2490 #ifdef USE_X_TOOLKIT
2491 XtPopup (f->output_data.w32->widget, XtGrabNone);
2492 #endif
2493 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2496 XFlush (FRAME_W32_DISPLAY (f));
2497 UNBLOCK_INPUT;
2498 #endif /* MAC_TODO */
2501 extern Lisp_Object x_new_font ();
2502 extern Lisp_Object x_new_fontset();
2504 void
2505 x_set_font (f, arg, oldval)
2506 struct frame *f;
2507 Lisp_Object arg, oldval;
2509 Lisp_Object result;
2510 Lisp_Object fontset_name;
2511 Lisp_Object frame;
2512 int old_fontset = FRAME_FONTSET(f);
2514 CHECK_STRING (arg);
2516 fontset_name = Fquery_fontset (arg, Qnil);
2518 BLOCK_INPUT;
2519 result = (STRINGP (fontset_name)
2520 ? x_new_fontset (f, SDATA (fontset_name))
2521 : x_new_font (f, SDATA (arg)));
2522 UNBLOCK_INPUT;
2524 if (EQ (result, Qnil))
2525 error ("Font `%s' is not defined", SDATA (arg));
2526 else if (EQ (result, Qt))
2527 error ("The characters of the given font have varying widths");
2528 else if (STRINGP (result))
2530 if (STRINGP (fontset_name))
2532 /* Fontset names are built from ASCII font names, so the
2533 names may be equal despite there was a change. */
2534 if (old_fontset == FRAME_FONTSET (f))
2535 return;
2537 else if (!NILP (Fequal (result, oldval)))
2538 return;
2540 store_frame_param (f, Qfont, result);
2541 recompute_basic_faces (f);
2543 else
2544 abort ();
2546 do_pending_window_change (0);
2548 /* Don't call `face-set-after-frame-default' when faces haven't been
2549 initialized yet. This is the case when called from
2550 Fx_create_frame. In that case, the X widget or window doesn't
2551 exist either, and we can end up in x_report_frame_params with a
2552 null widget which gives a segfault. */
2553 if (FRAME_FACE_CACHE (f))
2555 XSETFRAME (frame, f);
2556 call1 (Qface_set_after_frame_default, frame);
2560 void
2561 x_set_border_width (f, arg, oldval)
2562 struct frame *f;
2563 Lisp_Object arg, oldval;
2565 CHECK_NUMBER (arg);
2567 if (XINT (arg) == f->output_data.mac->border_width)
2568 return;
2570 #if 0 /* MAC_TODO */
2571 if (FRAME_MAC_WINDOW (f) != 0)
2572 error ("Cannot change the border width of a window");
2573 #endif
2575 f->output_data.mac->border_width = XINT (arg);
2578 void
2579 x_set_internal_border_width (f, arg, oldval)
2580 struct frame *f;
2581 Lisp_Object arg, oldval;
2583 int old = f->output_data.mac->internal_border_width;
2585 CHECK_NUMBER (arg);
2586 f->output_data.mac->internal_border_width = XINT (arg);
2587 if (f->output_data.mac->internal_border_width < 0)
2588 f->output_data.mac->internal_border_width = 0;
2590 if (f->output_data.mac->internal_border_width == old)
2591 return;
2593 if (FRAME_MAC_WINDOW (f) != 0)
2595 x_set_window_size (f, 0, f->width, f->height);
2596 SET_FRAME_GARBAGED (f);
2597 do_pending_window_change (0);
2599 else
2600 SET_FRAME_GARBAGED (f);
2603 void
2604 x_set_visibility (f, value, oldval)
2605 struct frame *f;
2606 Lisp_Object value, oldval;
2608 Lisp_Object frame;
2609 XSETFRAME (frame, f);
2611 if (NILP (value))
2612 Fmake_frame_invisible (frame, Qt);
2613 else if (EQ (value, Qicon))
2614 Ficonify_frame (frame);
2615 else
2616 Fmake_frame_visible (frame);
2620 /* Change window heights in windows rooted in WINDOW by N lines. */
2622 static void
2623 x_change_window_heights (window, n)
2624 Lisp_Object window;
2625 int n;
2627 struct window *w = XWINDOW (window);
2629 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2630 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2632 if (INTEGERP (w->orig_top))
2633 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2634 if (INTEGERP (w->orig_height))
2635 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2637 /* Handle just the top child in a vertical split. */
2638 if (!NILP (w->vchild))
2639 x_change_window_heights (w->vchild, n);
2641 /* Adjust all children in a horizontal split. */
2642 for (window = w->hchild; !NILP (window); window = w->next)
2644 w = XWINDOW (window);
2645 x_change_window_heights (window, n);
2649 void
2650 x_set_menu_bar_lines (f, value, oldval)
2651 struct frame *f;
2652 Lisp_Object value, oldval;
2654 int nlines;
2655 int olines = FRAME_MENU_BAR_LINES (f);
2657 /* Right now, menu bars don't work properly in minibuf-only frames;
2658 most of the commands try to apply themselves to the minibuffer
2659 frame itself, and get an error because you can't switch buffers
2660 in or split the minibuffer window. */
2661 if (FRAME_MINIBUF_ONLY_P (f))
2662 return;
2664 if (INTEGERP (value))
2665 nlines = XINT (value);
2666 else
2667 nlines = 0;
2669 FRAME_MENU_BAR_LINES (f) = 0;
2670 if (nlines)
2671 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2672 else
2674 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2675 free_frame_menubar (f);
2676 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2678 /* Adjust the frame size so that the client (text) dimensions
2679 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2680 set correctly. */
2681 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2682 do_pending_window_change (0);
2684 adjust_glyphs (f);
2688 /* Set the number of lines used for the tool bar of frame F to VALUE.
2689 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2690 is the old number of tool bar lines. This function changes the
2691 height of all windows on frame F to match the new tool bar height.
2692 The frame's height doesn't change. */
2694 void
2695 x_set_tool_bar_lines (f, value, oldval)
2696 struct frame *f;
2697 Lisp_Object value, oldval;
2699 int delta, nlines, root_height;
2700 Lisp_Object root_window;
2702 /* Treat tool bars like menu bars. */
2703 if (FRAME_MINIBUF_ONLY_P (f))
2704 return;
2706 /* Use VALUE only if an integer >= 0. */
2707 if (INTEGERP (value) && XINT (value) >= 0)
2708 nlines = XFASTINT (value);
2709 else
2710 nlines = 0;
2712 /* Make sure we redisplay all windows in this frame. */
2713 ++windows_or_buffers_changed;
2715 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2717 /* Don't resize the tool-bar to more than we have room for. */
2718 root_window = FRAME_ROOT_WINDOW (f);
2719 root_height = XINT (XWINDOW (root_window)->height);
2720 if (root_height - delta < 1)
2722 delta = root_height - 1;
2723 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2726 FRAME_TOOL_BAR_LINES (f) = nlines;
2727 x_change_window_heights (root_window, delta);
2728 adjust_glyphs (f);
2730 /* We also have to make sure that the internal border at the top of
2731 the frame, below the menu bar or tool bar, is redrawn when the
2732 tool bar disappears. This is so because the internal border is
2733 below the tool bar if one is displayed, but is below the menu bar
2734 if there isn't a tool bar. The tool bar draws into the area
2735 below the menu bar. */
2736 if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2738 updating_frame = f;
2739 clear_frame ();
2740 clear_current_matrices (f);
2741 updating_frame = NULL;
2744 /* If the tool bar gets smaller, the internal border below it
2745 has to be cleared. It was formerly part of the display
2746 of the larger tool bar, and updating windows won't clear it. */
2747 if (delta < 0)
2749 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2750 int width = PIXEL_WIDTH (f);
2751 int y = nlines * CANON_Y_UNIT (f);
2753 BLOCK_INPUT;
2754 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2755 0, y, width, height, 0);
2756 UNBLOCK_INPUT;
2758 if (WINDOWP (f->tool_bar_window))
2759 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2764 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2765 w32_id_name.
2767 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2768 name; if NAME is a string, set F's name to NAME and set
2769 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2771 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2772 suggesting a new name, which lisp code should override; if
2773 F->explicit_name is set, ignore the new name; otherwise, set it. */
2775 void
2776 x_set_name (f, name, explicit)
2777 struct frame *f;
2778 Lisp_Object name;
2779 int explicit;
2781 /* Make sure that requests from lisp code override requests from
2782 Emacs redisplay code. */
2783 if (explicit)
2785 /* If we're switching from explicit to implicit, we had better
2786 update the mode lines and thereby update the title. */
2787 if (f->explicit_name && NILP (name))
2788 update_mode_lines = 1;
2790 f->explicit_name = ! NILP (name);
2792 else if (f->explicit_name)
2793 return;
2795 /* If NAME is nil, set the name to the w32_id_name. */
2796 if (NILP (name))
2798 /* Check for no change needed in this very common case
2799 before we do any consing. */
2800 if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
2801 SDATA (f->name)))
2802 return;
2803 name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
2805 else
2806 CHECK_STRING (name);
2808 /* Don't change the name if it's already NAME. */
2809 if (! NILP (Fstring_equal (name, f->name)))
2810 return;
2812 f->name = name;
2814 /* For setting the frame title, the title parameter should override
2815 the name parameter. */
2816 if (! NILP (f->title))
2817 name = f->title;
2819 if (FRAME_MAC_WINDOW (f))
2821 if (STRING_MULTIBYTE (name))
2822 #if 0 /* MAC_TODO: encoding title string */
2823 name = ENCODE_SYSTEM (name);
2824 #else
2825 return;
2826 #endif
2828 BLOCK_INPUT;
2831 Str255 windowTitle;
2832 if (strlen (SDATA (name)) < 255)
2834 strcpy (windowTitle, SDATA (name));
2835 c2pstr (windowTitle);
2836 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2840 UNBLOCK_INPUT;
2844 /* This function should be called when the user's lisp code has
2845 specified a name for the frame; the name will override any set by the
2846 redisplay code. */
2847 void
2848 x_explicitly_set_name (f, arg, oldval)
2849 FRAME_PTR f;
2850 Lisp_Object arg, oldval;
2852 x_set_name (f, arg, 1);
2855 /* This function should be called by Emacs redisplay code to set the
2856 name; names set this way will never override names set by the user's
2857 lisp code. */
2858 void
2859 x_implicitly_set_name (f, arg, oldval)
2860 FRAME_PTR f;
2861 Lisp_Object arg, oldval;
2863 x_set_name (f, arg, 0);
2866 /* Change the title of frame F to NAME.
2867 If NAME is nil, use the frame name as the title.
2869 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2870 name; if NAME is a string, set F's name to NAME and set
2871 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2873 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2874 suggesting a new name, which lisp code should override; if
2875 F->explicit_name is set, ignore the new name; otherwise, set it. */
2877 void
2878 x_set_title (f, name, old_name)
2879 struct frame *f;
2880 Lisp_Object name, old_name;
2882 /* Don't change the title if it's already NAME. */
2883 if (EQ (name, f->title))
2884 return;
2886 update_mode_lines = 1;
2888 f->title = name;
2890 if (NILP (name))
2891 name = f->name;
2893 if (FRAME_MAC_WINDOW (f))
2895 if (STRING_MULTIBYTE (name))
2896 #if 0 /* MAC_TODO: encoding title string */
2897 name = ENCODE_SYSTEM (name);
2898 #else
2899 return;
2900 #endif
2902 BLOCK_INPUT;
2905 Str255 windowTitle;
2906 if (strlen (SDATA (name)) < 255)
2908 strcpy (windowTitle, SDATA (name));
2909 c2pstr (windowTitle);
2910 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2914 UNBLOCK_INPUT;
2918 void
2919 x_set_autoraise (f, arg, oldval)
2920 struct frame *f;
2921 Lisp_Object arg, oldval;
2923 f->auto_raise = !EQ (Qnil, arg);
2926 void
2927 x_set_autolower (f, arg, oldval)
2928 struct frame *f;
2929 Lisp_Object arg, oldval;
2931 f->auto_lower = !EQ (Qnil, arg);
2934 void
2935 x_set_unsplittable (f, arg, oldval)
2936 struct frame *f;
2937 Lisp_Object arg, oldval;
2939 f->no_split = !NILP (arg);
2942 void
2943 x_set_vertical_scroll_bars (f, arg, oldval)
2944 struct frame *f;
2945 Lisp_Object arg, oldval;
2947 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2948 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2949 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2950 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2952 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2953 = (NILP (arg)
2954 ? vertical_scroll_bar_none
2955 : EQ (Qright, arg)
2956 ? vertical_scroll_bar_right
2957 : vertical_scroll_bar_left);
2959 /* We set this parameter before creating the window for the
2960 frame, so we can get the geometry right from the start.
2961 However, if the window hasn't been created yet, we shouldn't
2962 call x_set_window_size. */
2963 if (FRAME_MAC_WINDOW (f))
2964 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2965 do_pending_window_change (0);
2969 void
2970 x_set_scroll_bar_width (f, arg, oldval)
2971 struct frame *f;
2972 Lisp_Object arg, oldval;
2974 /* Imitate X without X Toolkit */
2976 int wid = FONT_WIDTH (f->output_data.mac->font);
2978 if (NILP (arg))
2980 #ifdef MAC_OSX
2981 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 16; /* Aqua scroll bars. */
2982 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
2983 wid - 1) / wid;
2984 #else /* not MAC_OSX */
2985 /* Make the actual width at least 14 pixels and a multiple of a
2986 character width. */
2987 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2989 /* Use all of that space (aside from required margins) for the
2990 scroll bar. */
2991 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2992 #endif /* not MAC_OSX */
2993 if (FRAME_MAC_WINDOW (f))
2994 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2995 do_pending_window_change (0);
2997 else if (INTEGERP (arg) && XINT (arg) > 0
2998 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
3000 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3001 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3003 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
3004 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
3005 if (FRAME_MAC_WINDOW (f))
3006 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
3007 do_pending_window_change (0);
3009 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
3010 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3011 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3014 /* Subroutines of creating an frame. */
3016 /* Make sure that Vx_resource_name is set to a reasonable value.
3017 Fix it up, or set it to `emacs' if it is too hopeless. */
3019 static void
3020 validate_x_resource_name ()
3022 int len = 0;
3023 /* Number of valid characters in the resource name. */
3024 int good_count = 0;
3025 /* Number of invalid characters in the resource name. */
3026 int bad_count = 0;
3027 Lisp_Object new;
3028 int i;
3030 if (STRINGP (Vx_resource_name))
3032 unsigned char *p = SDATA (Vx_resource_name);
3033 int i;
3035 len = SBYTES (Vx_resource_name);
3037 /* Only letters, digits, - and _ are valid in resource names.
3038 Count the valid characters and count the invalid ones. */
3039 for (i = 0; i < len; i++)
3041 int c = p[i];
3042 if (! ((c >= 'a' && c <= 'z')
3043 || (c >= 'A' && c <= 'Z')
3044 || (c >= '0' && c <= '9')
3045 || c == '-' || c == '_'))
3046 bad_count++;
3047 else
3048 good_count++;
3051 else
3052 /* Not a string => completely invalid. */
3053 bad_count = 5, good_count = 0;
3055 /* If name is valid already, return. */
3056 if (bad_count == 0)
3057 return;
3059 /* If name is entirely invalid, or nearly so, use `emacs'. */
3060 if (good_count == 0
3061 || (good_count == 1 && bad_count > 0))
3063 Vx_resource_name = build_string ("emacs");
3064 return;
3067 /* Name is partly valid. Copy it and replace the invalid characters
3068 with underscores. */
3070 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3072 for (i = 0; i < len; i++)
3074 int c = SREF (new, i);
3075 if (! ((c >= 'a' && c <= 'z')
3076 || (c >= 'A' && c <= 'Z')
3077 || (c >= '0' && c <= '9')
3078 || c == '-' || c == '_'))
3079 SSET (new, i, '_');
3084 #if 0 /* MAC_TODO: implement resource strings */
3085 extern char *x_get_string_resource ();
3087 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3088 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3089 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3090 class, where INSTANCE is the name under which Emacs was invoked, or
3091 the name specified by the `-name' or `-rn' command-line arguments.
3093 The optional arguments COMPONENT and SUBCLASS add to the key and the
3094 class, respectively. You must specify both of them or neither.
3095 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3096 and the class is `Emacs.CLASS.SUBCLASS'. */)
3097 (attribute, class, component, subclass)
3098 Lisp_Object attribute, class, component, subclass;
3100 register char *value;
3101 char *name_key;
3102 char *class_key;
3104 CHECK_STRING (attribute);
3105 CHECK_STRING (class);
3107 if (!NILP (component))
3108 CHECK_STRING (component);
3109 if (!NILP (subclass))
3110 CHECK_STRING (subclass);
3111 if (NILP (component) != NILP (subclass))
3112 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3114 validate_x_resource_name ();
3116 /* Allocate space for the components, the dots which separate them,
3117 and the final '\0'. Make them big enough for the worst case. */
3118 name_key = (char *) alloca (SBYTES (Vx_resource_name)
3119 + (STRINGP (component)
3120 ? SBYTES (component) : 0)
3121 + SBYTES (attribute)
3122 + 3);
3124 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3125 + SBYTES (class)
3126 + (STRINGP (subclass)
3127 ? SBYTES (subclass) : 0)
3128 + 3);
3130 /* Start with emacs.FRAMENAME for the name (the specific one)
3131 and with `Emacs' for the class key (the general one). */
3132 strcpy (name_key, SDATA (Vx_resource_name));
3133 strcpy (class_key, EMACS_CLASS);
3135 strcat (class_key, ".");
3136 strcat (class_key, SDATA (class));
3138 if (!NILP (component))
3140 strcat (class_key, ".");
3141 strcat (class_key, SDATA (subclass));
3143 strcat (name_key, ".");
3144 strcat (name_key, SDATA (component));
3147 strcat (name_key, ".");
3148 strcat (name_key, SDATA (attribute));
3150 value = x_get_string_resource (Qnil,
3151 name_key, class_key);
3153 if (value != (char *) 0)
3154 return build_string (value);
3155 else
3156 return Qnil;
3159 /* Used when C code wants a resource value. */
3161 char *
3162 x_get_resource_string (attribute, class)
3163 char *attribute, *class;
3165 char *name_key;
3166 char *class_key;
3167 struct frame *sf = SELECTED_FRAME ();
3169 /* Allocate space for the components, the dots which separate them,
3170 and the final '\0'. */
3171 name_key = (char *) alloca (SBYTES (Vinvocation_name)
3172 + strlen (attribute) + 2);
3173 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3174 + strlen (class) + 2);
3176 sprintf (name_key, "%s.%s",
3177 SDATA (Vinvocation_name),
3178 attribute);
3179 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3181 return x_get_string_resource (sf, name_key, class_key);
3183 #endif /* MAC_TODO */
3185 /* Types we might convert a resource string into. */
3186 enum resource_types
3188 RES_TYPE_NUMBER,
3189 RES_TYPE_FLOAT,
3190 RES_TYPE_BOOLEAN,
3191 RES_TYPE_STRING,
3192 RES_TYPE_SYMBOL
3195 /* Return the value of parameter PARAM.
3197 First search ALIST, then Vdefault_frame_alist, then the X defaults
3198 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3200 Convert the resource to the type specified by desired_type.
3202 If no default is specified, return Qunbound. If you call
3203 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3204 and don't let it get stored in any Lisp-visible variables! */
3206 static Lisp_Object
3207 mac_get_arg (alist, param, attribute, class, type)
3208 Lisp_Object alist, param;
3209 char *attribute;
3210 char *class;
3211 enum resource_types type;
3213 register Lisp_Object tem;
3215 tem = Fassq (param, alist);
3216 if (EQ (tem, Qnil))
3217 tem = Fassq (param, Vdefault_frame_alist);
3218 if (EQ (tem, Qnil))
3221 #if 0 /* MAC_TODO: search resource also */
3222 if (attribute)
3224 tem = Fx_get_resource (build_string (attribute),
3225 build_string (class),
3226 Qnil, Qnil);
3228 if (NILP (tem))
3229 return Qunbound;
3231 switch (type)
3233 case RES_TYPE_NUMBER:
3234 return make_number (atoi (SDATA (tem)));
3236 case RES_TYPE_FLOAT:
3237 return make_float (atof (SDATA (tem)));
3239 case RES_TYPE_BOOLEAN:
3240 tem = Fdowncase (tem);
3241 if (!strcmp (SDATA (tem), "on")
3242 || !strcmp (SDATA (tem), "true"))
3243 return Qt;
3244 else
3245 return Qnil;
3247 case RES_TYPE_STRING:
3248 return tem;
3250 case RES_TYPE_SYMBOL:
3251 /* As a special case, we map the values `true' and `on'
3252 to Qt, and `false' and `off' to Qnil. */
3254 Lisp_Object lower;
3255 lower = Fdowncase (tem);
3256 if (!strcmp (SDATA (lower), "on")
3257 || !strcmp (SDATA (lower), "true"))
3258 return Qt;
3259 else if (!strcmp (SDATA (lower), "off")
3260 || !strcmp (SDATA (lower), "false"))
3261 return Qnil;
3262 else
3263 return Fintern (tem, Qnil);
3266 default:
3267 abort ();
3270 else
3271 #endif /* MAC_TODO */
3272 return Qunbound;
3274 return Fcdr (tem);
3277 /* Record in frame F the specified or default value according to ALIST
3278 of the parameter named PROP (a Lisp symbol).
3279 If no value is specified for PROP, look for an X default for XPROP
3280 on the frame named NAME.
3281 If that is not found either, use the value DEFLT. */
3283 static Lisp_Object
3284 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3285 struct frame *f;
3286 Lisp_Object alist;
3287 Lisp_Object prop;
3288 Lisp_Object deflt;
3289 char *xprop;
3290 char *xclass;
3291 enum resource_types type;
3293 Lisp_Object tem;
3295 tem = mac_get_arg (alist, prop, xprop, xclass, type);
3296 if (EQ (tem, Qunbound))
3297 tem = deflt;
3298 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3299 return tem;
3302 /* XParseGeometry copied from w32xfns.c */
3305 * XParseGeometry parses strings of the form
3306 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
3307 * width, height, xoffset, and yoffset are unsigned integers.
3308 * Example: "=80x24+300-49"
3309 * The equal sign is optional.
3310 * It returns a bitmask that indicates which of the four values
3311 * were actually found in the string. For each value found,
3312 * the corresponding argument is updated; for each value
3313 * not found, the corresponding argument is left unchanged.
3316 static int
3317 read_integer (string, NextString)
3318 register char *string;
3319 char **NextString;
3321 register int Result = 0;
3322 int Sign = 1;
3324 if (*string == '+')
3325 string++;
3326 else if (*string == '-')
3328 string++;
3329 Sign = -1;
3331 for (; (*string >= '0') && (*string <= '9'); string++)
3333 Result = (Result * 10) + (*string - '0');
3335 *NextString = string;
3336 if (Sign >= 0)
3337 return (Result);
3338 else
3339 return (-Result);
3343 XParseGeometry (string, x, y, width, height)
3344 char *string;
3345 int *x, *y;
3346 unsigned int *width, *height; /* RETURN */
3348 int mask = NoValue;
3349 register char *strind;
3350 unsigned int tempWidth, tempHeight;
3351 int tempX, tempY;
3352 char *nextCharacter;
3354 if ((string == NULL) || (*string == '\0')) return (mask);
3355 if (*string == '=')
3356 string++; /* ignore possible '=' at beg of geometry spec */
3358 strind = (char *)string;
3359 if (*strind != '+' && *strind != '-' && *strind != 'x')
3361 tempWidth = read_integer (strind, &nextCharacter);
3362 if (strind == nextCharacter)
3363 return (0);
3364 strind = nextCharacter;
3365 mask |= WidthValue;
3368 if (*strind == 'x' || *strind == 'X')
3370 strind++;
3371 tempHeight = read_integer (strind, &nextCharacter);
3372 if (strind == nextCharacter)
3373 return (0);
3374 strind = nextCharacter;
3375 mask |= HeightValue;
3378 if ((*strind == '+') || (*strind == '-'))
3380 if (*strind == '-')
3382 strind++;
3383 tempX = -read_integer (strind, &nextCharacter);
3384 if (strind == nextCharacter)
3385 return (0);
3386 strind = nextCharacter;
3387 mask |= XNegative;
3390 else
3392 strind++;
3393 tempX = read_integer (strind, &nextCharacter);
3394 if (strind == nextCharacter)
3395 return (0);
3396 strind = nextCharacter;
3398 mask |= XValue;
3399 if ((*strind == '+') || (*strind == '-'))
3401 if (*strind == '-')
3403 strind++;
3404 tempY = -read_integer (strind, &nextCharacter);
3405 if (strind == nextCharacter)
3406 return (0);
3407 strind = nextCharacter;
3408 mask |= YNegative;
3411 else
3413 strind++;
3414 tempY = read_integer (strind, &nextCharacter);
3415 if (strind == nextCharacter)
3416 return (0);
3417 strind = nextCharacter;
3419 mask |= YValue;
3423 /* If strind isn't at the end of the string the it's an invalid
3424 geometry specification. */
3426 if (*strind != '\0') return (0);
3428 if (mask & XValue)
3429 *x = tempX;
3430 if (mask & YValue)
3431 *y = tempY;
3432 if (mask & WidthValue)
3433 *width = tempWidth;
3434 if (mask & HeightValue)
3435 *height = tempHeight;
3436 return (mask);
3439 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3440 doc: /* Parse an X-style geometry string STRING.
3441 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3442 The properties returned may include `top', `left', `height', and `width'.
3443 The value of `left' or `top' may be an integer,
3444 or a list (+ N) meaning N pixels relative to top/left corner,
3445 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3446 (string)
3447 Lisp_Object string;
3449 int geometry, x, y;
3450 unsigned int width, height;
3451 Lisp_Object result;
3453 CHECK_STRING (string);
3455 geometry = XParseGeometry ((char *) SDATA (string),
3456 &x, &y, &width, &height);
3458 result = Qnil;
3459 if (geometry & XValue)
3461 Lisp_Object element;
3463 if (x >= 0 && (geometry & XNegative))
3464 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3465 else if (x < 0 && ! (geometry & XNegative))
3466 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3467 else
3468 element = Fcons (Qleft, make_number (x));
3469 result = Fcons (element, result);
3472 if (geometry & YValue)
3474 Lisp_Object element;
3476 if (y >= 0 && (geometry & YNegative))
3477 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3478 else if (y < 0 && ! (geometry & YNegative))
3479 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3480 else
3481 element = Fcons (Qtop, make_number (y));
3482 result = Fcons (element, result);
3485 if (geometry & WidthValue)
3486 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3487 if (geometry & HeightValue)
3488 result = Fcons (Fcons (Qheight, make_number (height)), result);
3490 return result;
3493 /* Calculate the desired size and position of this window,
3494 and return the flags saying which aspects were specified.
3496 This function does not make the coordinates positive. */
3498 #define DEFAULT_ROWS 40
3499 #define DEFAULT_COLS 80
3501 static int
3502 x_figure_window_size (f, parms)
3503 struct frame *f;
3504 Lisp_Object parms;
3506 register Lisp_Object tem0, tem1, tem2;
3507 long window_prompting = 0;
3509 /* Default values if we fall through.
3510 Actually, if that happens we should get
3511 window manager prompting. */
3512 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3513 f->height = DEFAULT_ROWS;
3514 /* Window managers expect that if program-specified
3515 positions are not (0,0), they're intentional, not defaults. */
3516 f->output_data.mac->top_pos = 0;
3517 f->output_data.mac->left_pos = 0;
3519 tem0 = mac_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3520 tem1 = mac_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3521 tem2 = mac_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3522 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3524 if (!EQ (tem0, Qunbound))
3526 CHECK_NUMBER (tem0);
3527 f->height = XINT (tem0);
3529 if (!EQ (tem1, Qunbound))
3531 CHECK_NUMBER (tem1);
3532 SET_FRAME_WIDTH (f, XINT (tem1));
3534 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3535 window_prompting |= USSize;
3536 else
3537 window_prompting |= PSize;
3540 f->output_data.mac->vertical_scroll_bar_extra
3541 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3543 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3544 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3545 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
3547 x_compute_fringe_widths (f, 0);
3549 f->output_data.mac->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3550 f->output_data.mac->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3552 tem0 = mac_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3553 tem1 = mac_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3554 tem2 = mac_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3555 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3557 if (EQ (tem0, Qminus))
3559 f->output_data.mac->top_pos = 0;
3560 window_prompting |= YNegative;
3562 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3563 && CONSP (XCDR (tem0))
3564 && INTEGERP (XCAR (XCDR (tem0))))
3566 f->output_data.mac->top_pos = - XINT (XCAR (XCDR (tem0)));
3567 window_prompting |= YNegative;
3569 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3570 && CONSP (XCDR (tem0))
3571 && INTEGERP (XCAR (XCDR (tem0))))
3573 f->output_data.mac->top_pos = XINT (XCAR (XCDR (tem0)));
3575 else if (EQ (tem0, Qunbound))
3576 f->output_data.mac->top_pos = 0;
3577 else
3579 CHECK_NUMBER (tem0);
3580 f->output_data.mac->top_pos = XINT (tem0);
3581 if (f->output_data.mac->top_pos < 0)
3582 window_prompting |= YNegative;
3585 if (EQ (tem1, Qminus))
3587 f->output_data.mac->left_pos = 0;
3588 window_prompting |= XNegative;
3590 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3591 && CONSP (XCDR (tem1))
3592 && INTEGERP (XCAR (XCDR (tem1))))
3594 f->output_data.mac->left_pos = - XINT (XCAR (XCDR (tem1)));
3595 window_prompting |= XNegative;
3597 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3598 && CONSP (XCDR (tem1))
3599 && INTEGERP (XCAR (XCDR (tem1))))
3601 f->output_data.mac->left_pos = XINT (XCAR (XCDR (tem1)));
3603 else if (EQ (tem1, Qunbound))
3604 f->output_data.mac->left_pos = 0;
3605 else
3607 CHECK_NUMBER (tem1);
3608 f->output_data.mac->left_pos = XINT (tem1);
3609 if (f->output_data.mac->left_pos < 0)
3610 window_prompting |= XNegative;
3613 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3614 window_prompting |= USPosition;
3615 else
3616 window_prompting |= PPosition;
3619 return window_prompting;
3623 #if 0 /* MAC_TODO */
3624 /* Create and set up the Mac window for frame F. */
3626 static void
3627 mac_window (f, window_prompting, minibuffer_only)
3628 struct frame *f;
3629 long window_prompting;
3630 int minibuffer_only;
3632 Rect r;
3634 BLOCK_INPUT;
3636 /* Use the resource name as the top-level window name
3637 for looking up resources. Make a non-Lisp copy
3638 for the window manager, so GC relocation won't bother it.
3640 Elsewhere we specify the window name for the window manager. */
3643 char *str = (char *) SDATA (Vx_resource_name);
3644 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3645 strcpy (f->namebuf, str);
3648 SetRect (&r, f->output_data.mac->left_pos, f->output_data.mac->top_pos,
3649 f->output_data.mac->left_pos + PIXEL_WIDTH (f),
3650 f->output_data.mac->top_pos + PIXEL_HEIGHT (f));
3651 FRAME_MAC_WINDOW (f)
3652 = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
3654 validate_x_resource_name ();
3656 /* x_set_name normally ignores requests to set the name if the
3657 requested name is the same as the current name. This is the one
3658 place where that assumption isn't correct; f->name is set, but
3659 the server hasn't been told. */
3661 Lisp_Object name;
3662 int explicit = f->explicit_name;
3664 f->explicit_name = 0;
3665 name = f->name;
3666 f->name = Qnil;
3667 x_set_name (f, name, explicit);
3670 ShowWindow (FRAME_MAC_WINDOW (f));
3672 UNBLOCK_INPUT;
3674 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3675 initialize_frame_menubar (f);
3677 if (FRAME_MAC_WINDOW (f) == 0)
3678 error ("Unable to create window");
3680 #endif /* MAC_TODO */
3682 /* Handle the icon stuff for this window. Perhaps later we might
3683 want an x_set_icon_position which can be called interactively as
3684 well. */
3686 static void
3687 x_icon (f, parms)
3688 struct frame *f;
3689 Lisp_Object parms;
3691 Lisp_Object icon_x, icon_y;
3693 /* Set the position of the icon. Note that Windows 95 groups all
3694 icons in the tray. */
3695 icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3696 icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3697 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3699 CHECK_NUMBER (icon_x);
3700 CHECK_NUMBER (icon_y);
3702 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3703 error ("Both left and top icon corners of icon must be specified");
3705 BLOCK_INPUT;
3707 if (! EQ (icon_x, Qunbound))
3708 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3710 #if 0 /* TODO */
3711 /* Start up iconic or window? */
3712 x_wm_set_window_state
3713 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
3714 ? IconicState
3715 : NormalState));
3717 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
3718 ? f->icon_name
3719 : f->name)));
3720 #endif
3722 UNBLOCK_INPUT;
3726 void
3727 x_make_gc (f)
3728 struct frame *f;
3730 XGCValues gc_values;
3732 BLOCK_INPUT;
3734 /* Create the GC's of this frame.
3735 Note that many default values are used. */
3737 /* Normal video */
3738 gc_values.font = f->output_data.mac->font;
3739 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3740 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3741 f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3742 FRAME_MAC_WINDOW (f),
3743 GCFont | GCForeground | GCBackground,
3744 &gc_values);
3746 /* Reverse video style. */
3747 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3748 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3749 f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3750 FRAME_MAC_WINDOW (f),
3751 GCFont | GCForeground | GCBackground,
3752 &gc_values);
3754 /* Cursor has cursor-color background, background-color foreground. */
3755 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3756 gc_values.background = f->output_data.mac->cursor_pixel;
3757 f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3758 FRAME_MAC_WINDOW (f),
3759 GCFont | GCForeground | GCBackground,
3760 &gc_values);
3762 /* Reliefs. */
3763 f->output_data.mac->white_relief.gc = 0;
3764 f->output_data.mac->black_relief.gc = 0;
3766 UNBLOCK_INPUT;
3770 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3771 1, 1, 0,
3772 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
3773 Returns an Emacs frame object.
3774 ALIST is an alist of frame parameters.
3775 If the parameters specify that the frame should not have a minibuffer,
3776 and do not specify a specific minibuffer window to use,
3777 then `default-minibuffer-frame' must be a frame whose minibuffer can
3778 be shared by the new frame.
3780 This function is an internal primitive--use `make-frame' instead. */)
3781 (parms)
3782 Lisp_Object parms;
3784 struct frame *f;
3785 Lisp_Object frame, tem;
3786 Lisp_Object name;
3787 int minibuffer_only = 0;
3788 long window_prompting = 0;
3789 int width, height;
3790 int count = SPECPDL_INDEX ();
3791 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3792 Lisp_Object display;
3793 struct mac_display_info *dpyinfo = NULL;
3794 Lisp_Object parent;
3795 struct kboard *kb;
3796 char x_frame_name[10];
3797 static int x_frame_count = 2; /* begins at 2 because terminal frame is F1 */
3799 check_mac ();
3801 /* Use this general default value to start with
3802 until we know if this frame has a specified name. */
3803 Vx_resource_name = Vinvocation_name;
3805 display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3806 if (EQ (display, Qunbound))
3807 display = Qnil;
3808 dpyinfo = check_x_display_info (display);
3809 #ifdef MULTI_KBOARD
3810 kb = dpyinfo->kboard;
3811 #else
3812 kb = &the_only_kboard;
3813 #endif
3815 name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
3816 if (!STRINGP (name)
3817 && ! EQ (name, Qunbound)
3818 && ! NILP (name))
3819 error ("Invalid frame name--not a string or nil");
3821 if (STRINGP (name))
3822 Vx_resource_name = name;
3824 /* See if parent window is specified. */
3825 parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3826 if (EQ (parent, Qunbound))
3827 parent = Qnil;
3828 if (! NILP (parent))
3829 CHECK_NUMBER (parent);
3831 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3832 /* No need to protect DISPLAY because that's not used after passing
3833 it to make_frame_without_minibuffer. */
3834 frame = Qnil;
3835 GCPRO4 (parms, parent, name, frame);
3836 tem = mac_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
3837 RES_TYPE_SYMBOL);
3838 if (EQ (tem, Qnone) || NILP (tem))
3839 f = make_frame_without_minibuffer (Qnil, kb, display);
3840 else if (EQ (tem, Qonly))
3842 f = make_minibuffer_frame ();
3843 minibuffer_only = 1;
3845 else if (WINDOWP (tem))
3846 f = make_frame_without_minibuffer (tem, kb, display);
3847 else
3848 f = make_frame (1);
3850 if (EQ (name, Qunbound) || NILP (name))
3852 sprintf (x_frame_name, "F%d", x_frame_count++);
3853 f->name = build_string (x_frame_name);
3854 f->explicit_name = 0;
3856 else
3858 f->name = name;
3859 f->explicit_name = 1;
3862 XSETFRAME (frame, f);
3864 /* Note that X Windows does support scroll bars. */
3865 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3867 f->output_method = output_mac;
3868 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
3869 bzero (f->output_data.mac, sizeof (struct mac_output));
3870 FRAME_FONTSET (f) = -1;
3871 f->output_data.mac->scroll_bar_foreground_pixel = -1;
3872 f->output_data.mac->scroll_bar_background_pixel = -1;
3874 #if 0
3875 FRAME_FONTSET (f) = -1;
3876 #endif
3878 f->icon_name
3879 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
3880 if (! STRINGP (f->icon_name))
3881 f->icon_name = Qnil;
3883 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
3884 #ifdef MULTI_KBOARD
3885 FRAME_KBOARD (f) = kb;
3886 #endif
3888 /* Specify the parent under which to make this window. */
3890 if (!NILP (parent))
3892 f->output_data.mac->parent_desc = (Window) parent;
3893 f->output_data.mac->explicit_parent = 1;
3895 else
3897 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
3898 f->output_data.mac->explicit_parent = 0;
3901 /* Set the name; the functions to which we pass f expect the name to
3902 be set. */
3903 if (EQ (name, Qunbound) || NILP (name))
3905 f->name = build_string (dpyinfo->mac_id_name);
3906 f->explicit_name = 0;
3908 else
3910 f->name = name;
3911 f->explicit_name = 1;
3912 /* use the frame's title when getting resources for this frame. */
3913 specbind (Qx_resource_name, name);
3916 /* Extract the window parameters from the supplied values
3917 that are needed to determine window geometry. */
3919 Lisp_Object font;
3921 font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
3923 BLOCK_INPUT;
3924 /* First, try whatever font the caller has specified. */
3925 if (STRINGP (font))
3927 tem = Fquery_fontset (font, Qnil);
3928 if (STRINGP (tem))
3929 font = x_new_fontset (f, SDATA (tem));
3930 else
3931 font = x_new_font (f, SDATA (font));
3933 /* Try out a font which we hope has bold and italic variations. */
3934 if (! STRINGP (font))
3935 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
3936 /* If those didn't work, look for something which will at least work. */
3937 if (!STRINGP (font))
3938 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
3939 if (! STRINGP (font))
3940 font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
3941 if (! STRINGP (font))
3942 error ("Cannot find any usable font");
3943 UNBLOCK_INPUT;
3945 x_default_parameter (f, parms, Qfont, font,
3946 "font", "Font", RES_TYPE_STRING);
3949 x_default_parameter (f, parms, Qborder_width, make_number (0),
3950 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
3951 /* This defaults to 2 in order to match xterm. We recognize either
3952 internalBorderWidth or internalBorder (which is what xterm calls
3953 it). */
3954 if (NILP (Fassq (Qinternal_border_width, parms)))
3956 Lisp_Object value;
3958 value = mac_get_arg (parms, Qinternal_border_width,
3959 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
3960 if (! EQ (value, Qunbound))
3961 parms = Fcons (Fcons (Qinternal_border_width, value),
3962 parms);
3964 /* Default internalBorderWidth to 0 on Windows to match other programs. */
3965 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
3966 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
3967 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
3968 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
3970 /* Also do the stuff which must be set before the window exists. */
3971 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3972 "foreground", "Foreground", RES_TYPE_STRING);
3973 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3974 "background", "Background", RES_TYPE_STRING);
3975 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3976 "pointerColor", "Foreground", RES_TYPE_STRING);
3977 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3978 "cursorColor", "Foreground", RES_TYPE_STRING);
3979 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3980 "borderColor", "BorderColor", RES_TYPE_STRING);
3981 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3982 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3983 x_default_parameter (f, parms, Qline_spacing, Qnil,
3984 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3985 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3986 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3987 x_default_parameter (f, parms, Qright_fringe, Qnil,
3988 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3991 /* Init faces before x_default_parameter is called for scroll-bar
3992 parameters because that function calls x_set_scroll_bar_width,
3993 which calls change_frame_size, which calls Fset_window_buffer,
3994 which runs hooks, which call Fvertical_motion. At the end, we
3995 end up in init_iterator with a null face cache, which should not
3996 happen. */
3997 init_frame_faces (f);
3999 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4000 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4001 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
4002 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4003 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4004 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
4005 x_default_parameter (f, parms, Qtitle, Qnil,
4006 "title", "Title", RES_TYPE_STRING);
4008 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
4009 window_prompting = x_figure_window_size (f, parms);
4011 if (window_prompting & XNegative)
4013 if (window_prompting & YNegative)
4014 f->output_data.mac->win_gravity = SouthEastGravity;
4015 else
4016 f->output_data.mac->win_gravity = NorthEastGravity;
4018 else
4020 if (window_prompting & YNegative)
4021 f->output_data.mac->win_gravity = SouthWestGravity;
4022 else
4023 f->output_data.mac->win_gravity = NorthWestGravity;
4026 f->output_data.mac->size_hint_flags = window_prompting;
4028 tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4029 f->no_split = minibuffer_only || EQ (tem, Qt);
4031 /* Create the window. Add the tool-bar height to the initial frame
4032 height so that the user gets a text display area of the size he
4033 specified with -g or via the registry. Later changes of the
4034 tool-bar height don't change the frame size. This is done so that
4035 users can create tall Emacs frames without having to guess how
4036 tall the tool-bar will get. */
4037 f->height += FRAME_TOOL_BAR_LINES (f);
4039 /* mac_window (f, window_prompting, minibuffer_only); */
4040 make_mac_frame (f);
4042 x_icon (f, parms);
4044 x_make_gc (f);
4046 /* Now consider the frame official. */
4047 FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
4048 Vframe_list = Fcons (frame, Vframe_list);
4050 /* We need to do this after creating the window, so that the
4051 icon-creation functions can say whose icon they're describing. */
4052 x_default_parameter (f, parms, Qicon_type, Qnil,
4053 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4055 x_default_parameter (f, parms, Qauto_raise, Qnil,
4056 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4057 x_default_parameter (f, parms, Qauto_lower, Qnil,
4058 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4059 x_default_parameter (f, parms, Qcursor_type, Qbox,
4060 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4061 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4062 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
4064 /* Dimensions, especially f->height, must be done via change_frame_size.
4065 Change will not be effected unless different from the current
4066 f->height. */
4067 width = f->width;
4068 height = f->height;
4070 f->height = 0;
4071 SET_FRAME_WIDTH (f, 0);
4072 change_frame_size (f, height, width, 1, 0, 0);
4074 /* Set up faces after all frame parameters are known. */
4075 call1 (Qface_set_after_frame_default, frame);
4077 #if 0 /* MAC_TODO: when we have window manager hints */
4078 /* Tell the server what size and position, etc, we want, and how
4079 badly we want them. This should be done after we have the menu
4080 bar so that its size can be taken into account. */
4081 BLOCK_INPUT;
4082 x_wm_set_size_hint (f, window_prompting, 0);
4083 UNBLOCK_INPUT;
4084 #endif
4086 /* Make the window appear on the frame and enable display, unless
4087 the caller says not to. However, with explicit parent, Emacs
4088 cannot control visibility, so don't try. */
4089 if (! f->output_data.mac->explicit_parent)
4091 Lisp_Object visibility;
4093 visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
4094 if (EQ (visibility, Qunbound))
4095 visibility = Qt;
4097 #if 0 /* MAC_TODO: really no iconify on Mac */
4098 if (EQ (visibility, Qicon))
4099 x_iconify_frame (f);
4100 else
4101 #endif
4102 if (! NILP (visibility))
4103 x_make_frame_visible (f);
4104 else
4105 /* Must have been Qnil. */
4108 UNGCPRO;
4110 /* Make sure windows on this frame appear in calls to next-window
4111 and similar functions. */
4112 Vwindow_list = Qnil;
4114 return unbind_to (count, frame);
4117 /* FRAME is used only to get a handle on the X display. We don't pass the
4118 display info directly because we're called from frame.c, which doesn't
4119 know about that structure. */
4120 Lisp_Object
4121 x_get_focus_frame (frame)
4122 struct frame *frame;
4124 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4125 Lisp_Object xfocus;
4126 if (! dpyinfo->x_focus_frame)
4127 return Qnil;
4129 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4130 return xfocus;
4133 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4134 doc: /* Internal function called by `color-defined-p', which see. */)
4135 (color, frame)
4136 Lisp_Object color, frame;
4138 XColor foo;
4139 FRAME_PTR f = check_x_frame (frame);
4141 CHECK_STRING (color);
4143 if (mac_defined_color (f, SDATA (color), &foo, 0))
4144 return Qt;
4145 else
4146 return Qnil;
4149 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4150 doc: /* Internal function called by `color-values', which see. */)
4151 (color, frame)
4152 Lisp_Object color, frame;
4154 XColor foo;
4155 FRAME_PTR f = check_x_frame (frame);
4157 CHECK_STRING (color);
4159 if (mac_defined_color (f, SDATA (color), &foo, 0))
4161 Lisp_Object rgb[3];
4163 rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
4164 | RED_FROM_ULONG (foo.pixel));
4165 rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
4166 | GREEN_FROM_ULONG (foo.pixel));
4167 rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
4168 | BLUE_FROM_ULONG (foo.pixel));
4169 return Flist (3, rgb);
4171 else
4172 return Qnil;
4175 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4176 doc: /* Internal function called by `display-color-p', which see. */)
4177 (display)
4178 Lisp_Object display;
4180 struct mac_display_info *dpyinfo = check_x_display_info (display);
4182 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
4183 return Qnil;
4185 return Qt;
4188 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4189 0, 1, 0,
4190 doc: /* Return t if the X display supports shades of gray.
4191 Note that color displays do support shades of gray.
4192 The optional argument DISPLAY specifies which display to ask about.
4193 DISPLAY should be either a frame or a display name (a string).
4194 If omitted or nil, that stands for the selected frame's display. */)
4195 (display)
4196 Lisp_Object display;
4198 struct mac_display_info *dpyinfo = check_x_display_info (display);
4200 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
4201 return Qnil;
4203 return Qt;
4206 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4207 0, 1, 0,
4208 doc: /* Returns the width in pixels of the X display DISPLAY.
4209 The optional argument DISPLAY specifies which display to ask about.
4210 DISPLAY should be either a frame or a display name (a string).
4211 If omitted or nil, that stands for the selected frame's display. */)
4212 (display)
4213 Lisp_Object display;
4215 struct mac_display_info *dpyinfo = check_x_display_info (display);
4217 return make_number (dpyinfo->width);
4220 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4221 Sx_display_pixel_height, 0, 1, 0,
4222 doc: /* Returns the height in pixels of the X display DISPLAY.
4223 The optional argument DISPLAY specifies which display to ask about.
4224 DISPLAY should be either a frame or a display name (a string).
4225 If omitted or nil, that stands for the selected frame's display. */)
4226 (display)
4227 Lisp_Object display;
4229 struct mac_display_info *dpyinfo = check_x_display_info (display);
4231 return make_number (dpyinfo->height);
4234 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4235 0, 1, 0,
4236 doc: /* Returns the number of bitplanes of the display DISPLAY.
4237 The optional argument DISPLAY specifies which display to ask about.
4238 DISPLAY should be either a frame or a display name (a string).
4239 If omitted or nil, that stands for the selected frame's display. */)
4240 (display)
4241 Lisp_Object display;
4243 struct mac_display_info *dpyinfo = check_x_display_info (display);
4245 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
4248 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4249 0, 1, 0,
4250 doc: /* Returns the number of color cells of the display DISPLAY.
4251 The optional argument DISPLAY specifies which display to ask about.
4252 DISPLAY should be either a frame or a display name (a string).
4253 If omitted or nil, that stands for the selected frame's display. */)
4254 (display)
4255 Lisp_Object display;
4257 struct mac_display_info *dpyinfo = check_x_display_info (display);
4259 /* MAC_TODO: check whether this is right */
4260 return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
4263 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4264 Sx_server_max_request_size,
4265 0, 1, 0,
4266 doc: /* Returns the maximum request size of the server of display DISPLAY.
4267 The optional argument DISPLAY specifies which display to ask about.
4268 DISPLAY should be either a frame or a display name (a string).
4269 If omitted or nil, that stands for the selected frame's display. */)
4270 (display)
4271 Lisp_Object display;
4273 struct mac_display_info *dpyinfo = check_x_display_info (display);
4275 return make_number (1);
4278 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4279 doc: /* Returns the vendor ID string of the Mac OS system (Apple).
4280 The optional argument DISPLAY specifies which display to ask about.
4281 DISPLAY should be either a frame or a display name (a string).
4282 If omitted or nil, that stands for the selected frame's display. */)
4283 (display)
4284 Lisp_Object display;
4286 return build_string ("Apple Computers");
4289 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4290 doc: /* Returns the version numbers of the server of display DISPLAY.
4291 The value is a list of three integers: the major and minor
4292 version numbers, and the vendor-specific release
4293 number. See also the function `x-server-vendor'.
4295 The optional argument DISPLAY specifies which display to ask about.
4296 DISPLAY should be either a frame or a display name (a string).
4297 If omitted or nil, that stands for the selected frame's display. */)
4298 (display)
4299 Lisp_Object display;
4301 int mac_major_version, mac_minor_version;
4302 SInt32 response;
4304 if (Gestalt (gestaltSystemVersion, &response) != noErr)
4305 error ("Cannot get Mac OS version");
4307 mac_major_version = (response >> 8) & 0xf;
4308 mac_minor_version = (response >> 4) & 0xf;
4310 return Fcons (make_number (mac_major_version),
4311 Fcons (make_number (mac_minor_version), Qnil));
4314 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4315 doc: /* Return the number of screens on the server of display DISPLAY.
4316 The optional argument DISPLAY specifies which display to ask about.
4317 DISPLAY should be either a frame or a display name (a string).
4318 If omitted or nil, that stands for the selected frame's display. */)
4319 (display)
4320 Lisp_Object display;
4322 return make_number (1);
4325 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4326 doc: /* Return the height in millimeters of the X display DISPLAY.
4327 The optional argument DISPLAY specifies which display to ask about.
4328 DISPLAY should be either a frame or a display name (a string).
4329 If omitted or nil, that stands for the selected frame's display. */)
4330 (display)
4331 Lisp_Object display;
4333 /* MAC_TODO: this is an approximation, and only of the main display */
4335 struct mac_display_info *dpyinfo = check_x_display_info (display);
4336 short h, v;
4338 ScreenRes (&h, &v);
4340 return make_number ((int) (v / 72.0 * 25.4));
4343 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4344 doc: /* Return the width in millimeters of the X display DISPLAY.
4345 The optional argument DISPLAY specifies which display to ask about.
4346 DISPLAY should be either a frame or a display name (a string).
4347 If omitted or nil, that stands for the selected frame's display. */)
4348 (display)
4349 Lisp_Object display;
4351 /* MAC_TODO: this is an approximation, and only of the main display */
4353 struct mac_display_info *dpyinfo = check_x_display_info (display);
4354 short h, v;
4356 ScreenRes (&h, &v);
4358 return make_number ((int) (h / 72.0 * 25.4));
4361 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4362 Sx_display_backing_store, 0, 1, 0,
4363 doc: /* Returns an indication of whether display DISPLAY does backing store.
4364 The value may be `always', `when-mapped', or `not-useful'.
4365 The optional argument DISPLAY specifies which display to ask about.
4366 DISPLAY should be either a frame or a display name (a string).
4367 If omitted or nil, that stands for the selected frame's display. */)
4368 (display)
4369 Lisp_Object display;
4371 return intern ("not-useful");
4374 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4375 Sx_display_visual_class, 0, 1, 0,
4376 doc: /* Returns the visual class of the display DISPLAY.
4377 The value is one of the symbols `static-gray', `gray-scale',
4378 `static-color', `pseudo-color', `true-color', or `direct-color'.
4380 The optional argument DISPLAY specifies which display to ask about.
4381 DISPLAY should be either a frame or a display name (a string).
4382 If omitted or nil, that stands for the selected frame's display. */)
4383 (display)
4384 Lisp_Object display;
4386 struct mac_display_info *dpyinfo = check_x_display_info (display);
4388 #if 0
4389 switch (dpyinfo->visual->class)
4391 case StaticGray: return (intern ("static-gray"));
4392 case GrayScale: return (intern ("gray-scale"));
4393 case StaticColor: return (intern ("static-color"));
4394 case PseudoColor: return (intern ("pseudo-color"));
4395 case TrueColor: return (intern ("true-color"));
4396 case DirectColor: return (intern ("direct-color"));
4397 default:
4398 error ("Display has an unknown visual class");
4400 #endif /* 0 */
4402 return (intern ("true-color"));
4405 DEFUN ("x-display-save-under", Fx_display_save_under,
4406 Sx_display_save_under, 0, 1, 0,
4407 doc: /* Returns t if the display DISPLAY supports the save-under feature.
4408 The optional argument DISPLAY specifies which display to ask about.
4409 DISPLAY should be either a frame or a display name (a string).
4410 If omitted or nil, that stands for the selected frame's display. */)
4411 (display)
4412 Lisp_Object display;
4414 return Qnil;
4418 x_pixel_width (f)
4419 register struct frame *f;
4421 return PIXEL_WIDTH (f);
4425 x_pixel_height (f)
4426 register struct frame *f;
4428 return PIXEL_HEIGHT (f);
4432 x_char_width (f)
4433 register struct frame *f;
4435 return FONT_WIDTH (f->output_data.mac->font);
4439 x_char_height (f)
4440 register struct frame *f;
4442 return f->output_data.mac->line_height;
4446 x_screen_planes (f)
4447 register struct frame *f;
4449 return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
4452 /* Return the display structure for the display named NAME.
4453 Open a new connection if necessary. */
4455 struct mac_display_info *
4456 x_display_info_for_name (name)
4457 Lisp_Object name;
4459 Lisp_Object names;
4460 struct mac_display_info *dpyinfo;
4462 CHECK_STRING (name);
4464 for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
4465 dpyinfo;
4466 dpyinfo = dpyinfo->next, names = XCDR (names))
4468 Lisp_Object tem;
4469 tem = Fstring_equal (XCAR (XCAR (names)), name);
4470 if (!NILP (tem))
4471 return dpyinfo;
4474 /* Use this general default value to start with. */
4475 Vx_resource_name = Vinvocation_name;
4477 validate_x_resource_name ();
4479 dpyinfo = mac_term_init (name, (unsigned char *) 0,
4480 (char *) SDATA (Vx_resource_name));
4482 if (dpyinfo == 0)
4483 error ("Cannot connect to server %s", SDATA (name));
4485 mac_in_use = 1;
4486 XSETFASTINT (Vwindow_system_version, 3);
4488 return dpyinfo;
4491 #if 0 /* MAC_TODO: implement network support */
4492 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4493 1, 3, 0,
4494 doc: /* Open a connection to a server.
4495 DISPLAY is the name of the display to connect to.
4496 Optional second arg XRM-STRING is a string of resources in xrdb format.
4497 If the optional third arg MUST-SUCCEED is non-nil,
4498 terminate Emacs if we can't open the connection. */)
4499 (display, xrm_string, must_succeed)
4500 Lisp_Object display, xrm_string, must_succeed;
4502 unsigned char *xrm_option;
4503 struct mac_display_info *dpyinfo;
4505 CHECK_STRING (display);
4506 if (! NILP (xrm_string))
4507 CHECK_STRING (xrm_string);
4509 if (! EQ (Vwindow_system, intern ("mac")))
4510 error ("Not using Mac OS");
4512 if (! NILP (xrm_string))
4513 xrm_option = (unsigned char *) SDATA (xrm_string);
4514 else
4515 xrm_option = (unsigned char *) 0;
4517 validate_x_resource_name ();
4519 /* This is what opens the connection and sets x_current_display.
4520 This also initializes many symbols, such as those used for input. */
4521 dpyinfo = mac_term_init (display, xrm_option,
4522 (char *) SDATA (Vx_resource_name));
4524 if (dpyinfo == 0)
4526 if (!NILP (must_succeed))
4527 fatal ("Cannot connect to server %s.\n",
4528 SDATA (display));
4529 else
4530 error ("Cannot connect to server %s", SDATA (display));
4533 mac_in_use = 1;
4535 XSETFASTINT (Vwindow_system_version, 3);
4536 return Qnil;
4539 DEFUN ("x-close-connection", Fx_close_connection,
4540 Sx_close_connection, 1, 1, 0,
4541 doc: /* Close the connection to DISPLAY's server.
4542 For DISPLAY, specify either a frame or a display name (a string).
4543 If DISPLAY is nil, that stands for the selected frame's display. */)
4544 (display)
4545 Lisp_Object display;
4547 struct mac_display_info *dpyinfo = check_x_display_info (display);
4548 int i;
4550 if (dpyinfo->reference_count > 0)
4551 error ("Display still has frames on it");
4553 BLOCK_INPUT;
4554 /* Free the fonts in the font table. */
4555 for (i = 0; i < dpyinfo->n_fonts; i++)
4556 if (dpyinfo->font_table[i].name)
4558 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4559 xfree (dpyinfo->font_table[i].full_name);
4560 xfree (dpyinfo->font_table[i].name);
4561 x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
4563 x_destroy_all_bitmaps (dpyinfo);
4565 x_delete_display (dpyinfo);
4566 UNBLOCK_INPUT;
4568 return Qnil;
4570 #endif /* 0 */
4572 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4573 doc: /* Return the list of display names that Emacs has connections to. */)
4576 Lisp_Object tail, result;
4578 result = Qnil;
4579 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4580 result = Fcons (XCAR (XCAR (tail)), result);
4582 return result;
4585 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4586 doc: /* If ON is non-nil, report errors as soon as the erring request is made.
4587 If ON is nil, allow buffering of requests.
4588 This is a noop on Mac OS systems.
4589 The optional second argument DISPLAY specifies which display to act on.
4590 DISPLAY should be either a frame or a display name (a string).
4591 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4592 (on, display)
4593 Lisp_Object display, on;
4595 return Qnil;
4599 /***********************************************************************
4600 Image types
4601 ***********************************************************************/
4603 /* Value is the number of elements of vector VECTOR. */
4605 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4607 /* List of supported image types. Use define_image_type to add new
4608 types. Use lookup_image_type to find a type for a given symbol. */
4610 static struct image_type *image_types;
4612 /* The symbol `image' which is the car of the lists used to represent
4613 images in Lisp. */
4615 extern Lisp_Object Qimage;
4617 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4619 Lisp_Object Qxbm;
4621 /* Keywords. */
4623 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
4624 extern Lisp_Object QCdata, QCtype;
4625 Lisp_Object QCascent, QCmargin, QCrelief;
4626 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
4627 Lisp_Object QCindex;
4629 /* Other symbols. */
4631 Lisp_Object Qlaplace;
4633 /* Time in seconds after which images should be removed from the cache
4634 if not displayed. */
4636 Lisp_Object Vimage_cache_eviction_delay;
4638 /* Function prototypes. */
4640 static void define_image_type P_ ((struct image_type *type));
4641 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
4642 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
4643 static void x_laplace P_ ((struct frame *, struct image *));
4644 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
4645 Lisp_Object));
4648 /* Define a new image type from TYPE. This adds a copy of TYPE to
4649 image_types and adds the symbol *TYPE->type to Vimage_types. */
4651 static void
4652 define_image_type (type)
4653 struct image_type *type;
4655 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4656 The initialized data segment is read-only. */
4657 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
4658 bcopy (type, p, sizeof *p);
4659 p->next = image_types;
4660 image_types = p;
4661 Vimage_types = Fcons (*p->type, Vimage_types);
4665 /* Look up image type SYMBOL, and return a pointer to its image_type
4666 structure. Value is null if SYMBOL is not a known image type. */
4668 static INLINE struct image_type *
4669 lookup_image_type (symbol)
4670 Lisp_Object symbol;
4672 struct image_type *type;
4674 for (type = image_types; type; type = type->next)
4675 if (EQ (symbol, *type->type))
4676 break;
4678 return type;
4682 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4683 valid image specification is a list whose car is the symbol
4684 `image', and whose rest is a property list. The property list must
4685 contain a value for key `:type'. That value must be the name of a
4686 supported image type. The rest of the property list depends on the
4687 image type. */
4690 valid_image_p (object)
4691 Lisp_Object object;
4693 int valid_p = 0;
4695 if (CONSP (object) && EQ (XCAR (object), Qimage))
4697 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
4698 struct image_type *type = lookup_image_type (symbol);
4700 if (type)
4701 valid_p = type->valid_p (object);
4704 return valid_p;
4708 /* Log error message with format string FORMAT and argument ARG.
4709 Signaling an error, e.g. when an image cannot be loaded, is not a
4710 good idea because this would interrupt redisplay, and the error
4711 message display would lead to another redisplay. This function
4712 therefore simply displays a message. */
4714 static void
4715 image_error (format, arg1, arg2)
4716 char *format;
4717 Lisp_Object arg1, arg2;
4719 add_to_log (format, arg1, arg2);
4724 /***********************************************************************
4725 Image specifications
4726 ***********************************************************************/
4728 enum image_value_type
4730 IMAGE_DONT_CHECK_VALUE_TYPE,
4731 IMAGE_STRING_VALUE,
4732 IMAGE_SYMBOL_VALUE,
4733 IMAGE_POSITIVE_INTEGER_VALUE,
4734 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
4735 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
4736 IMAGE_ASCENT_VALUE,
4737 IMAGE_INTEGER_VALUE,
4738 IMAGE_FUNCTION_VALUE,
4739 IMAGE_NUMBER_VALUE,
4740 IMAGE_BOOL_VALUE
4743 /* Structure used when parsing image specifications. */
4745 struct image_keyword
4747 /* Name of keyword. */
4748 char *name;
4750 /* The type of value allowed. */
4751 enum image_value_type type;
4753 /* Non-zero means key must be present. */
4754 int mandatory_p;
4756 /* Used to recognize duplicate keywords in a property list. */
4757 int count;
4759 /* The value that was found. */
4760 Lisp_Object value;
4764 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
4765 int, Lisp_Object));
4766 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
4769 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
4770 has the format (image KEYWORD VALUE ...). One of the keyword/
4771 value pairs must be `:type TYPE'. KEYWORDS is a vector of
4772 image_keywords structures of size NKEYWORDS describing other
4773 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
4775 static int
4776 parse_image_spec (spec, keywords, nkeywords, type)
4777 Lisp_Object spec;
4778 struct image_keyword *keywords;
4779 int nkeywords;
4780 Lisp_Object type;
4782 int i;
4783 Lisp_Object plist;
4785 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
4786 return 0;
4788 plist = XCDR (spec);
4789 while (CONSP (plist))
4791 Lisp_Object key, value;
4793 /* First element of a pair must be a symbol. */
4794 key = XCAR (plist);
4795 plist = XCDR (plist);
4796 if (!SYMBOLP (key))
4797 return 0;
4799 /* There must follow a value. */
4800 if (!CONSP (plist))
4801 return 0;
4802 value = XCAR (plist);
4803 plist = XCDR (plist);
4805 /* Find key in KEYWORDS. Error if not found. */
4806 for (i = 0; i < nkeywords; ++i)
4807 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
4808 break;
4810 if (i == nkeywords)
4811 continue;
4813 /* Record that we recognized the keyword. If a keywords
4814 was found more than once, it's an error. */
4815 keywords[i].value = value;
4816 ++keywords[i].count;
4818 if (keywords[i].count > 1)
4819 return 0;
4821 /* Check type of value against allowed type. */
4822 switch (keywords[i].type)
4824 case IMAGE_STRING_VALUE:
4825 if (!STRINGP (value))
4826 return 0;
4827 break;
4829 case IMAGE_SYMBOL_VALUE:
4830 if (!SYMBOLP (value))
4831 return 0;
4832 break;
4834 case IMAGE_POSITIVE_INTEGER_VALUE:
4835 if (!INTEGERP (value) || XINT (value) <= 0)
4836 return 0;
4837 break;
4839 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
4840 if (INTEGERP (value) && XINT (value) >= 0)
4841 break;
4842 if (CONSP (value)
4843 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
4844 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
4845 break;
4846 return 0;
4848 case IMAGE_ASCENT_VALUE:
4849 if (SYMBOLP (value) && EQ (value, Qcenter))
4850 break;
4851 else if (INTEGERP (value)
4852 && XINT (value) >= 0
4853 && XINT (value) <= 100)
4854 break;
4855 return 0;
4857 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
4858 if (!INTEGERP (value) || XINT (value) < 0)
4859 return 0;
4860 break;
4862 case IMAGE_DONT_CHECK_VALUE_TYPE:
4863 break;
4865 case IMAGE_FUNCTION_VALUE:
4866 value = indirect_function (value);
4867 if (SUBRP (value)
4868 || COMPILEDP (value)
4869 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
4870 break;
4871 return 0;
4873 case IMAGE_NUMBER_VALUE:
4874 if (!INTEGERP (value) && !FLOATP (value))
4875 return 0;
4876 break;
4878 case IMAGE_INTEGER_VALUE:
4879 if (!INTEGERP (value))
4880 return 0;
4881 break;
4883 case IMAGE_BOOL_VALUE:
4884 if (!NILP (value) && !EQ (value, Qt))
4885 return 0;
4886 break;
4888 default:
4889 abort ();
4890 break;
4893 if (EQ (key, QCtype) && !EQ (type, value))
4894 return 0;
4897 /* Check that all mandatory fields are present. */
4898 for (i = 0; i < nkeywords; ++i)
4899 if (keywords[i].mandatory_p && keywords[i].count == 0)
4900 return 0;
4902 return NILP (plist);
4906 /* Return the value of KEY in image specification SPEC. Value is nil
4907 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
4908 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
4910 static Lisp_Object
4911 image_spec_value (spec, key, found)
4912 Lisp_Object spec, key;
4913 int *found;
4915 Lisp_Object tail;
4917 xassert (valid_image_p (spec));
4919 for (tail = XCDR (spec);
4920 CONSP (tail) && CONSP (XCDR (tail));
4921 tail = XCDR (XCDR (tail)))
4923 if (EQ (XCAR (tail), key))
4925 if (found)
4926 *found = 1;
4927 return XCAR (XCDR (tail));
4931 if (found)
4932 *found = 0;
4933 return Qnil;
4939 /***********************************************************************
4940 Image type independent image structures
4941 ***********************************************************************/
4943 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
4944 static void free_image P_ ((struct frame *f, struct image *img));
4947 /* Allocate and return a new image structure for image specification
4948 SPEC. SPEC has a hash value of HASH. */
4950 static struct image *
4951 make_image (spec, hash)
4952 Lisp_Object spec;
4953 unsigned hash;
4955 struct image *img = (struct image *) xmalloc (sizeof *img);
4957 xassert (valid_image_p (spec));
4958 bzero (img, sizeof *img);
4959 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
4960 xassert (img->type != NULL);
4961 img->spec = spec;
4962 img->data.lisp_val = Qnil;
4963 img->ascent = DEFAULT_IMAGE_ASCENT;
4964 img->hash = hash;
4965 return img;
4969 /* Free image IMG which was used on frame F, including its resources. */
4971 static void
4972 free_image (f, img)
4973 struct frame *f;
4974 struct image *img;
4976 if (img)
4978 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4980 /* Remove IMG from the hash table of its cache. */
4981 if (img->prev)
4982 img->prev->next = img->next;
4983 else
4984 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
4986 if (img->next)
4987 img->next->prev = img->prev;
4989 c->images[img->id] = NULL;
4991 /* Free resources, then free IMG. */
4992 img->type->free (f, img);
4993 xfree (img);
4998 /* Prepare image IMG for display on frame F. Must be called before
4999 drawing an image. */
5001 void
5002 prepare_image_for_display (f, img)
5003 struct frame *f;
5004 struct image *img;
5006 EMACS_TIME t;
5008 /* We're about to display IMG, so set its timestamp to `now'. */
5009 EMACS_GET_TIME (t);
5010 img->timestamp = EMACS_SECS (t);
5012 /* If IMG doesn't have a pixmap yet, load it now, using the image
5013 type dependent loader function. */
5014 if (img->pixmap == 0 && !img->load_failed_p)
5015 img->load_failed_p = img->type->load (f, img) == 0;
5019 /* Value is the number of pixels for the ascent of image IMG when
5020 drawn in face FACE. */
5023 image_ascent (img, face)
5024 struct image *img;
5025 struct face *face;
5027 int height = img->height + img->vmargin;
5028 int ascent;
5030 if (img->ascent == CENTERED_IMAGE_ASCENT)
5032 if (face->font)
5033 ascent = height / 2 - (FONT_DESCENT(face->font)
5034 - FONT_BASE(face->font)) / 2;
5035 else
5036 ascent = height / 2;
5038 else
5039 ascent = height * img->ascent / 100.0;
5041 return ascent;
5046 /***********************************************************************
5047 Helper functions for X image types
5048 ***********************************************************************/
5050 static void x_clear_image P_ ((struct frame *f, struct image *img));
5051 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5052 struct image *img,
5053 Lisp_Object color_name,
5054 unsigned long dflt));
5056 /* Free X resources of image IMG which is used on frame F. */
5058 static void
5059 x_clear_image (f, img)
5060 struct frame *f;
5061 struct image *img;
5063 #if 0 /* MAC_TODO: W32 image support */
5065 if (img->pixmap)
5067 BLOCK_INPUT;
5068 XFreePixmap (NULL, img->pixmap);
5069 img->pixmap = 0;
5070 UNBLOCK_INPUT;
5073 if (img->ncolors)
5075 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
5077 /* If display has an immutable color map, freeing colors is not
5078 necessary and some servers don't allow it. So don't do it. */
5079 if (class != StaticColor
5080 && class != StaticGray
5081 && class != TrueColor)
5083 Colormap cmap;
5084 BLOCK_INPUT;
5085 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
5086 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
5087 img->ncolors, 0);
5088 UNBLOCK_INPUT;
5091 xfree (img->colors);
5092 img->colors = NULL;
5093 img->ncolors = 0;
5095 #endif /* MAC_TODO */
5099 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5100 cannot be allocated, use DFLT. Add a newly allocated color to
5101 IMG->colors, so that it can be freed again. Value is the pixel
5102 color. */
5104 static unsigned long
5105 x_alloc_image_color (f, img, color_name, dflt)
5106 struct frame *f;
5107 struct image *img;
5108 Lisp_Object color_name;
5109 unsigned long dflt;
5111 #if 0 /* MAC_TODO: allocing colors. */
5112 XColor color;
5113 unsigned long result;
5115 xassert (STRINGP (color_name));
5117 if (w32_defined_color (f, SDATA (color_name), &color, 1))
5119 /* This isn't called frequently so we get away with simply
5120 reallocating the color vector to the needed size, here. */
5121 ++img->ncolors;
5122 img->colors =
5123 (unsigned long *) xrealloc (img->colors,
5124 img->ncolors * sizeof *img->colors);
5125 img->colors[img->ncolors - 1] = color.pixel;
5126 result = color.pixel;
5128 else
5129 result = dflt;
5130 return result;
5131 #endif /* MAC_TODO */
5132 return 0;
5137 /***********************************************************************
5138 Image Cache
5139 ***********************************************************************/
5141 static void cache_image P_ ((struct frame *f, struct image *img));
5144 /* Return a new, initialized image cache that is allocated from the
5145 heap. Call free_image_cache to free an image cache. */
5147 struct image_cache *
5148 make_image_cache ()
5150 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5151 int size;
5153 bzero (c, sizeof *c);
5154 c->size = 50;
5155 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5156 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5157 c->buckets = (struct image **) xmalloc (size);
5158 bzero (c->buckets, size);
5159 return c;
5163 /* Free image cache of frame F. Be aware that X frames share images
5164 caches. */
5166 void
5167 free_image_cache (f)
5168 struct frame *f;
5170 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5171 if (c)
5173 int i;
5175 /* Cache should not be referenced by any frame when freed. */
5176 xassert (c->refcount == 0);
5178 for (i = 0; i < c->used; ++i)
5179 free_image (f, c->images[i]);
5180 xfree (c->images);
5181 xfree (c->buckets);
5182 xfree (c);
5183 FRAME_X_IMAGE_CACHE (f) = NULL;
5188 /* Clear image cache of frame F. FORCE_P non-zero means free all
5189 images. FORCE_P zero means clear only images that haven't been
5190 displayed for some time. Should be called from time to time to
5191 reduce the number of loaded images. If image-eviction-seconds is
5192 non-nil, this frees images in the cache which weren't displayed for
5193 at least that many seconds. */
5195 void
5196 clear_image_cache (f, force_p)
5197 struct frame *f;
5198 int force_p;
5200 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5202 if (c && INTEGERP (Vimage_cache_eviction_delay))
5204 EMACS_TIME t;
5205 unsigned long old;
5206 int i, any_freed_p = 0;
5208 EMACS_GET_TIME (t);
5209 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5211 for (i = 0; i < c->used; ++i)
5213 struct image *img = c->images[i];
5214 if (img != NULL
5215 && (force_p
5216 || (img->timestamp > old)))
5218 free_image (f, img);
5219 any_freed_p = 1;
5223 /* We may be clearing the image cache because, for example,
5224 Emacs was iconified for a longer period of time. In that
5225 case, current matrices may still contain references to
5226 images freed above. So, clear these matrices. */
5227 if (any_freed_p)
5229 clear_current_matrices (f);
5230 ++windows_or_buffers_changed;
5236 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5237 0, 1, 0,
5238 doc: /* Clear the image cache of FRAME.
5239 FRAME nil or omitted means use the selected frame.
5240 FRAME t means clear the image caches of all frames. */)
5241 (frame)
5242 Lisp_Object frame;
5244 if (EQ (frame, Qt))
5246 Lisp_Object tail;
5248 FOR_EACH_FRAME (tail, frame)
5249 if (FRAME_MAC_P (XFRAME (frame)))
5250 clear_image_cache (XFRAME (frame), 1);
5252 else
5253 clear_image_cache (check_x_frame (frame), 1);
5255 return Qnil;
5259 /* Return the id of image with Lisp specification SPEC on frame F.
5260 SPEC must be a valid Lisp image specification (see valid_image_p). */
5263 lookup_image (f, spec)
5264 struct frame *f;
5265 Lisp_Object spec;
5267 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5268 struct image *img;
5269 int i;
5270 unsigned hash;
5271 struct gcpro gcpro1;
5272 EMACS_TIME now;
5274 /* F must be a window-system frame, and SPEC must be a valid image
5275 specification. */
5276 xassert (FRAME_WINDOW_P (f));
5277 xassert (valid_image_p (spec));
5279 GCPRO1 (spec);
5281 /* Look up SPEC in the hash table of the image cache. */
5282 hash = sxhash (spec, 0);
5283 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5285 for (img = c->buckets[i]; img; img = img->next)
5286 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5287 break;
5289 /* If not found, create a new image and cache it. */
5290 if (img == NULL)
5292 BLOCK_INPUT;
5293 img = make_image (spec, hash);
5294 cache_image (f, img);
5295 img->load_failed_p = img->type->load (f, img) == 0;
5296 xassert (!interrupt_input_blocked);
5298 /* If we can't load the image, and we don't have a width and
5299 height, use some arbitrary width and height so that we can
5300 draw a rectangle for it. */
5301 if (img->load_failed_p)
5303 Lisp_Object value;
5305 value = image_spec_value (spec, QCwidth, NULL);
5306 img->width = (INTEGERP (value)
5307 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5308 value = image_spec_value (spec, QCheight, NULL);
5309 img->height = (INTEGERP (value)
5310 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5312 else
5314 /* Handle image type independent image attributes
5315 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
5316 Lisp_Object ascent, margin, relief;
5318 ascent = image_spec_value (spec, QCascent, NULL);
5319 if (INTEGERP (ascent))
5320 img->ascent = XFASTINT (ascent);
5321 else if (EQ (ascent, Qcenter))
5322 img->ascent = CENTERED_IMAGE_ASCENT;
5324 margin = image_spec_value (spec, QCmargin, NULL);
5325 if (INTEGERP (margin) && XINT (margin) >= 0)
5326 img->vmargin = img->hmargin = XFASTINT (margin);
5327 else if (CONSP (margin) && INTEGERP (XCAR (margin))
5328 && INTEGERP (XCDR (margin)))
5330 if (XINT (XCAR (margin)) > 0)
5331 img->hmargin = XFASTINT (XCAR (margin));
5332 if (XINT (XCDR (margin)) > 0)
5333 img->vmargin = XFASTINT (XCDR (margin));
5336 relief = image_spec_value (spec, QCrelief, NULL);
5337 if (INTEGERP (relief))
5339 img->relief = XINT (relief);
5340 img->hmargin += abs (img->relief);
5341 img->vmargin += abs (img->relief);
5346 /* We're using IMG, so set its timestamp to `now'. */
5347 EMACS_GET_TIME (now);
5348 img->timestamp = EMACS_SECS (now);
5350 UNGCPRO;
5352 /* Value is the image id. */
5353 return img->id;
5357 /* Cache image IMG in the image cache of frame F. */
5359 static void
5360 cache_image (f, img)
5361 struct frame *f;
5362 struct image *img;
5364 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5365 int i;
5367 /* Find a free slot in c->images. */
5368 for (i = 0; i < c->used; ++i)
5369 if (c->images[i] == NULL)
5370 break;
5372 /* If no free slot found, maybe enlarge c->images. */
5373 if (i == c->used && c->used == c->size)
5375 c->size *= 2;
5376 c->images = (struct image **) xrealloc (c->images,
5377 c->size * sizeof *c->images);
5380 /* Add IMG to c->images, and assign IMG an id. */
5381 c->images[i] = img;
5382 img->id = i;
5383 if (i == c->used)
5384 ++c->used;
5386 /* Add IMG to the cache's hash table. */
5387 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5388 img->next = c->buckets[i];
5389 if (img->next)
5390 img->next->prev = img;
5391 img->prev = NULL;
5392 c->buckets[i] = img;
5396 /* Call FN on every image in the image cache of frame F. Used to mark
5397 Lisp Objects in the image cache. */
5399 void
5400 forall_images_in_image_cache (f, fn)
5401 struct frame *f;
5402 void (*fn) P_ ((struct image *img));
5404 if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
5406 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5407 if (c)
5409 int i;
5410 for (i = 0; i < c->used; ++i)
5411 if (c->images[i])
5412 fn (c->images[i]);
5419 /***********************************************************************
5420 Mac support code
5421 ***********************************************************************/
5423 #if 0 /* MAC_TODO: Mac specific image code. */
5425 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5426 XImage **, Pixmap *));
5427 static void x_destroy_x_image P_ ((XImage *));
5428 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5431 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5432 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5433 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5434 via xmalloc. Print error messages via image_error if an error
5435 occurs. Value is non-zero if successful. */
5437 static int
5438 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5439 struct frame *f;
5440 int width, height, depth;
5441 XImage **ximg;
5442 Pixmap *pixmap;
5444 #if 0 /* MAC_TODO: Image support for Mac */
5445 Display *display = FRAME_W32_DISPLAY (f);
5446 Screen *screen = FRAME_X_SCREEN (f);
5447 Window window = FRAME_W32_WINDOW (f);
5449 xassert (interrupt_input_blocked);
5451 if (depth <= 0)
5452 depth = DefaultDepthOfScreen (screen);
5453 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5454 depth, ZPixmap, 0, NULL, width, height,
5455 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5456 if (*ximg == NULL)
5458 image_error ("Unable to allocate X image", Qnil, Qnil);
5459 return 0;
5462 /* Allocate image raster. */
5463 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5465 /* Allocate a pixmap of the same size. */
5466 *pixmap = XCreatePixmap (display, window, width, height, depth);
5467 if (*pixmap == 0)
5469 x_destroy_x_image (*ximg);
5470 *ximg = NULL;
5471 image_error ("Unable to create X pixmap", Qnil, Qnil);
5472 return 0;
5474 #endif /* MAC_TODO */
5475 return 1;
5479 /* Destroy XImage XIMG. Free XIMG->data. */
5481 static void
5482 x_destroy_x_image (ximg)
5483 XImage *ximg;
5485 xassert (interrupt_input_blocked);
5486 if (ximg)
5488 xfree (ximg->data);
5489 ximg->data = NULL;
5490 XDestroyImage (ximg);
5495 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5496 are width and height of both the image and pixmap. */
5498 static void
5499 x_put_x_image (f, ximg, pixmap, width, height)
5500 struct frame *f;
5501 XImage *ximg;
5502 Pixmap pixmap;
5504 GC gc;
5506 xassert (interrupt_input_blocked);
5507 gc = XCreateGC (NULL, pixmap, 0, NULL);
5508 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5509 XFreeGC (NULL, gc);
5512 #endif /* MAC_TODO */
5515 /***********************************************************************
5516 Searching files
5517 ***********************************************************************/
5519 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5521 /* Find image file FILE. Look in data-directory, then
5522 x-bitmap-file-path. Value is the full name of the file found, or
5523 nil if not found. */
5525 static Lisp_Object
5526 x_find_image_file (file)
5527 Lisp_Object file;
5529 Lisp_Object file_found, search_path;
5530 struct gcpro gcpro1, gcpro2;
5531 int fd;
5533 file_found = Qnil;
5534 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5535 GCPRO2 (file_found, search_path);
5537 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5538 fd = openp (search_path, file, Qnil, &file_found, Qnil);
5540 if (fd < 0)
5541 file_found = Qnil;
5542 else
5543 close (fd);
5545 UNGCPRO;
5546 return file_found;
5550 /***********************************************************************
5551 XBM images
5552 ***********************************************************************/
5554 static int xbm_load P_ ((struct frame *f, struct image *img));
5555 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
5556 Lisp_Object file));
5557 static int xbm_image_p P_ ((Lisp_Object object));
5558 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
5559 unsigned char **));
5562 /* Indices of image specification fields in xbm_format, below. */
5564 enum xbm_keyword_index
5566 XBM_TYPE,
5567 XBM_FILE,
5568 XBM_WIDTH,
5569 XBM_HEIGHT,
5570 XBM_DATA,
5571 XBM_FOREGROUND,
5572 XBM_BACKGROUND,
5573 XBM_ASCENT,
5574 XBM_MARGIN,
5575 XBM_RELIEF,
5576 XBM_ALGORITHM,
5577 XBM_HEURISTIC_MASK,
5578 XBM_LAST
5581 /* Vector of image_keyword structures describing the format
5582 of valid XBM image specifications. */
5584 static struct image_keyword xbm_format[XBM_LAST] =
5586 {":type", IMAGE_SYMBOL_VALUE, 1},
5587 {":file", IMAGE_STRING_VALUE, 0},
5588 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5589 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5590 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5591 {":foreground", IMAGE_STRING_VALUE, 0},
5592 {":background", IMAGE_STRING_VALUE, 0},
5593 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
5594 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5595 {":relief", IMAGE_INTEGER_VALUE, 0},
5596 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5597 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5600 /* Structure describing the image type XBM. */
5602 static struct image_type xbm_type =
5604 &Qxbm,
5605 xbm_image_p,
5606 xbm_load,
5607 x_clear_image,
5608 NULL
5611 /* Tokens returned from xbm_scan. */
5613 enum xbm_token
5615 XBM_TK_IDENT = 256,
5616 XBM_TK_NUMBER
5620 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5621 A valid specification is a list starting with the symbol `image'
5622 The rest of the list is a property list which must contain an
5623 entry `:type xbm..
5625 If the specification specifies a file to load, it must contain
5626 an entry `:file FILENAME' where FILENAME is a string.
5628 If the specification is for a bitmap loaded from memory it must
5629 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5630 WIDTH and HEIGHT are integers > 0. DATA may be:
5632 1. a string large enough to hold the bitmap data, i.e. it must
5633 have a size >= (WIDTH + 7) / 8 * HEIGHT
5635 2. a bool-vector of size >= WIDTH * HEIGHT
5637 3. a vector of strings or bool-vectors, one for each line of the
5638 bitmap.
5640 Both the file and data forms may contain the additional entries
5641 `:background COLOR' and `:foreground COLOR'. If not present,
5642 foreground and background of the frame on which the image is
5643 displayed, is used. */
5645 static int
5646 xbm_image_p (object)
5647 Lisp_Object object;
5649 struct image_keyword kw[XBM_LAST];
5651 bcopy (xbm_format, kw, sizeof kw);
5652 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5653 return 0;
5655 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5657 if (kw[XBM_FILE].count)
5659 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5660 return 0;
5662 else
5664 Lisp_Object data;
5665 int width, height;
5667 /* Entries for `:width', `:height' and `:data' must be present. */
5668 if (!kw[XBM_WIDTH].count
5669 || !kw[XBM_HEIGHT].count
5670 || !kw[XBM_DATA].count)
5671 return 0;
5673 data = kw[XBM_DATA].value;
5674 width = XFASTINT (kw[XBM_WIDTH].value);
5675 height = XFASTINT (kw[XBM_HEIGHT].value);
5677 /* Check type of data, and width and height against contents of
5678 data. */
5679 if (VECTORP (data))
5681 int i;
5683 /* Number of elements of the vector must be >= height. */
5684 if (XVECTOR (data)->size < height)
5685 return 0;
5687 /* Each string or bool-vector in data must be large enough
5688 for one line of the image. */
5689 for (i = 0; i < height; ++i)
5691 Lisp_Object elt = XVECTOR (data)->contents[i];
5693 if (STRINGP (elt))
5695 if (SCHARS (elt)
5696 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
5697 return 0;
5699 else if (BOOL_VECTOR_P (elt))
5701 if (XBOOL_VECTOR (elt)->size < width)
5702 return 0;
5704 else
5705 return 0;
5708 else if (STRINGP (data))
5710 if (SCHARS (data)
5711 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
5712 return 0;
5714 else if (BOOL_VECTOR_P (data))
5716 if (XBOOL_VECTOR (data)->size < width * height)
5717 return 0;
5719 else
5720 return 0;
5723 /* Baseline must be a value between 0 and 100 (a percentage). */
5724 if (kw[XBM_ASCENT].count
5725 && XFASTINT (kw[XBM_ASCENT].value) > 100)
5726 return 0;
5728 return 1;
5732 /* Scan a bitmap file. FP is the stream to read from. Value is
5733 either an enumerator from enum xbm_token, or a character for a
5734 single-character token, or 0 at end of file. If scanning an
5735 identifier, store the lexeme of the identifier in SVAL. If
5736 scanning a number, store its value in *IVAL. */
5738 static int
5739 xbm_scan (fp, sval, ival)
5740 FILE *fp;
5741 char *sval;
5742 int *ival;
5744 int c;
5746 /* Skip white space. */
5747 while ((c = fgetc (fp)) != EOF && isspace (c))
5750 if (c == EOF)
5751 c = 0;
5752 else if (isdigit (c))
5754 int value = 0, digit;
5756 if (c == '0')
5758 c = fgetc (fp);
5759 if (c == 'x' || c == 'X')
5761 while ((c = fgetc (fp)) != EOF)
5763 if (isdigit (c))
5764 digit = c - '0';
5765 else if (c >= 'a' && c <= 'f')
5766 digit = c - 'a' + 10;
5767 else if (c >= 'A' && c <= 'F')
5768 digit = c - 'A' + 10;
5769 else
5770 break;
5771 value = 16 * value + digit;
5774 else if (isdigit (c))
5776 value = c - '0';
5777 while ((c = fgetc (fp)) != EOF
5778 && isdigit (c))
5779 value = 8 * value + c - '0';
5782 else
5784 value = c - '0';
5785 while ((c = fgetc (fp)) != EOF
5786 && isdigit (c))
5787 value = 10 * value + c - '0';
5790 if (c != EOF)
5791 ungetc (c, fp);
5792 *ival = value;
5793 c = XBM_TK_NUMBER;
5795 else if (isalpha (c) || c == '_')
5797 *sval++ = c;
5798 while ((c = fgetc (fp)) != EOF
5799 && (isalnum (c) || c == '_'))
5800 *sval++ = c;
5801 *sval = 0;
5802 if (c != EOF)
5803 ungetc (c, fp);
5804 c = XBM_TK_IDENT;
5807 return c;
5811 /* Replacement for XReadBitmapFileData which isn't available under old
5812 X versions. FILE is the name of the bitmap file to read. Set
5813 *WIDTH and *HEIGHT to the width and height of the image. Return in
5814 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
5815 successful. */
5817 static int
5818 xbm_read_bitmap_file_data (file, width, height, data)
5819 char *file;
5820 int *width, *height;
5821 unsigned char **data;
5823 FILE *fp;
5824 char buffer[BUFSIZ];
5825 int padding_p = 0;
5826 int v10 = 0;
5827 int bytes_per_line, i, nbytes;
5828 unsigned char *p;
5829 int value;
5830 int LA1;
5832 #define match() \
5833 LA1 = xbm_scan (fp, buffer, &value)
5835 #define expect(TOKEN) \
5836 if (LA1 != (TOKEN)) \
5837 goto failure; \
5838 else \
5839 match ()
5841 #define expect_ident(IDENT) \
5842 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5843 match (); \
5844 else \
5845 goto failure
5847 fp = fopen (file, "r");
5848 if (fp == NULL)
5849 return 0;
5851 *width = *height = -1;
5852 *data = NULL;
5853 LA1 = xbm_scan (fp, buffer, &value);
5855 /* Parse defines for width, height and hot-spots. */
5856 while (LA1 == '#')
5858 match ();
5859 expect_ident ("define");
5860 expect (XBM_TK_IDENT);
5862 if (LA1 == XBM_TK_NUMBER);
5864 char *p = strrchr (buffer, '_');
5865 p = p ? p + 1 : buffer;
5866 if (strcmp (p, "width") == 0)
5867 *width = value;
5868 else if (strcmp (p, "height") == 0)
5869 *height = value;
5871 expect (XBM_TK_NUMBER);
5874 if (*width < 0 || *height < 0)
5875 goto failure;
5877 /* Parse bits. Must start with `static'. */
5878 expect_ident ("static");
5879 if (LA1 == XBM_TK_IDENT)
5881 if (strcmp (buffer, "unsigned") == 0)
5883 match ();
5884 expect_ident ("char");
5886 else if (strcmp (buffer, "short") == 0)
5888 match ();
5889 v10 = 1;
5890 if (*width % 16 && *width % 16 < 9)
5891 padding_p = 1;
5893 else if (strcmp (buffer, "char") == 0)
5894 match ();
5895 else
5896 goto failure;
5898 else
5899 goto failure;
5901 expect (XBM_TK_IDENT);
5902 expect ('[');
5903 expect (']');
5904 expect ('=');
5905 expect ('{');
5907 bytes_per_line = (*width + 7) / 8 + padding_p;
5908 nbytes = bytes_per_line * *height;
5909 p = *data = (char *) xmalloc (nbytes);
5911 if (v10)
5914 for (i = 0; i < nbytes; i += 2)
5916 int val = value;
5917 expect (XBM_TK_NUMBER);
5919 *p++ = val;
5920 if (!padding_p || ((i + 2) % bytes_per_line))
5921 *p++ = value >> 8;
5923 if (LA1 == ',' || LA1 == '}')
5924 match ();
5925 else
5926 goto failure;
5929 else
5931 for (i = 0; i < nbytes; ++i)
5933 int val = value;
5934 expect (XBM_TK_NUMBER);
5936 *p++ = val;
5938 if (LA1 == ',' || LA1 == '}')
5939 match ();
5940 else
5941 goto failure;
5945 fclose (fp);
5946 return 1;
5948 failure:
5950 fclose (fp);
5951 if (*data)
5953 xfree (*data);
5954 *data = NULL;
5956 return 0;
5958 #undef match
5959 #undef expect
5960 #undef expect_ident
5964 /* Load XBM image IMG which will be displayed on frame F from file
5965 SPECIFIED_FILE. Value is non-zero if successful. */
5967 static int
5968 xbm_load_image_from_file (f, img, specified_file)
5969 struct frame *f;
5970 struct image *img;
5971 Lisp_Object specified_file;
5973 int rc;
5974 unsigned char *data;
5975 int success_p = 0;
5976 Lisp_Object file;
5977 struct gcpro gcpro1;
5979 xassert (STRINGP (specified_file));
5980 file = Qnil;
5981 GCPRO1 (file);
5983 file = x_find_image_file (specified_file);
5984 if (!STRINGP (file))
5986 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5987 UNGCPRO;
5988 return 0;
5991 rc = xbm_read_bitmap_file_data (SDATA (file), &img->width,
5992 &img->height, &data);
5993 if (rc)
5995 int depth = one_mac_display_info.n_cbits;
5996 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5997 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5998 Lisp_Object value;
6000 xassert (img->width > 0 && img->height > 0);
6002 /* Get foreground and background colors, maybe allocate colors. */
6003 value = image_spec_value (img->spec, QCforeground, NULL);
6004 if (!NILP (value))
6005 foreground = x_alloc_image_color (f, img, value, foreground);
6007 value = image_spec_value (img->spec, QCbackground, NULL);
6008 if (!NILP (value))
6009 background = x_alloc_image_color (f, img, value, background);
6011 #if 0 /* MAC_TODO : Port image display to Mac */
6012 BLOCK_INPUT;
6013 img->pixmap
6014 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
6015 FRAME_W32_WINDOW (f),
6016 data,
6017 img->width, img->height,
6018 foreground, background,
6019 depth);
6020 xfree (data);
6022 if (img->pixmap == 0)
6024 x_clear_image (f, img);
6025 image_error ("Unable to create X pixmap for `%s'", file, Qnil);
6027 else
6028 success_p = 1;
6030 UNBLOCK_INPUT;
6031 #endif /* MAC_TODO */
6033 else
6034 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6036 UNGCPRO;
6037 return success_p;
6041 /* Fill image IMG which is used on frame F with pixmap data. Value is
6042 non-zero if successful. */
6044 static int
6045 xbm_load (f, img)
6046 struct frame *f;
6047 struct image *img;
6049 int success_p = 0;
6050 Lisp_Object file_name;
6052 xassert (xbm_image_p (img->spec));
6054 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6055 file_name = image_spec_value (img->spec, QCfile, NULL);
6056 if (STRINGP (file_name))
6057 success_p = xbm_load_image_from_file (f, img, file_name);
6058 else
6060 struct image_keyword fmt[XBM_LAST];
6061 Lisp_Object data;
6062 int depth;
6063 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6064 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6065 char *bits;
6066 int parsed_p;
6068 /* Parse the list specification. */
6069 bcopy (xbm_format, fmt, sizeof fmt);
6070 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6071 xassert (parsed_p);
6073 /* Get specified width, and height. */
6074 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6075 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6076 xassert (img->width > 0 && img->height > 0);
6078 BLOCK_INPUT;
6080 if (fmt[XBM_ASCENT].count)
6081 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
6083 /* Get foreground and background colors, maybe allocate colors. */
6084 if (fmt[XBM_FOREGROUND].count)
6085 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6086 foreground);
6087 if (fmt[XBM_BACKGROUND].count)
6088 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6089 background);
6091 /* Set bits to the bitmap image data. */
6092 data = fmt[XBM_DATA].value;
6093 if (VECTORP (data))
6095 int i;
6096 char *p;
6097 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6099 p = bits = (char *) alloca (nbytes * img->height);
6100 for (i = 0; i < img->height; ++i, p += nbytes)
6102 Lisp_Object line = XVECTOR (data)->contents[i];
6103 if (STRINGP (line))
6104 bcopy (SDATA (line), p, nbytes);
6105 else
6106 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6109 else if (STRINGP (data))
6110 bits = SDATA (data);
6111 else
6112 bits = XBOOL_VECTOR (data)->data;
6114 #if 0 /* MAC_TODO : port Mac display code */
6115 /* Create the pixmap. */
6116 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6117 img->pixmap
6118 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
6119 FRAME_W32_WINDOW (f),
6120 bits,
6121 img->width, img->height,
6122 foreground, background,
6123 depth);
6124 #endif /* MAC_TODO */
6126 if (img->pixmap)
6127 success_p = 1;
6128 else
6130 image_error ("Unable to create pixmap for XBM image `%s'",
6131 img->spec, Qnil);
6132 x_clear_image (f, img);
6135 UNBLOCK_INPUT;
6138 return success_p;
6143 /***********************************************************************
6144 XPM images
6145 ***********************************************************************/
6147 #if HAVE_XPM
6149 static int xpm_image_p P_ ((Lisp_Object object));
6150 static int xpm_load P_ ((struct frame *f, struct image *img));
6151 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6153 #include "X11/xpm.h"
6155 /* The symbol `xpm' identifying XPM-format images. */
6157 Lisp_Object Qxpm;
6159 /* Indices of image specification fields in xpm_format, below. */
6161 enum xpm_keyword_index
6163 XPM_TYPE,
6164 XPM_FILE,
6165 XPM_DATA,
6166 XPM_ASCENT,
6167 XPM_MARGIN,
6168 XPM_RELIEF,
6169 XPM_ALGORITHM,
6170 XPM_HEURISTIC_MASK,
6171 XPM_COLOR_SYMBOLS,
6172 XPM_LAST
6175 /* Vector of image_keyword structures describing the format
6176 of valid XPM image specifications. */
6178 static struct image_keyword xpm_format[XPM_LAST] =
6180 {":type", IMAGE_SYMBOL_VALUE, 1},
6181 {":file", IMAGE_STRING_VALUE, 0},
6182 {":data", IMAGE_STRING_VALUE, 0},
6183 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6184 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6185 {":relief", IMAGE_INTEGER_VALUE, 0},
6186 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6187 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6188 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6191 /* Structure describing the image type XBM. */
6193 static struct image_type xpm_type =
6195 &Qxpm,
6196 xpm_image_p,
6197 xpm_load,
6198 x_clear_image,
6199 NULL
6203 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6204 for XPM images. Such a list must consist of conses whose car and
6205 cdr are strings. */
6207 static int
6208 xpm_valid_color_symbols_p (color_symbols)
6209 Lisp_Object color_symbols;
6211 while (CONSP (color_symbols))
6213 Lisp_Object sym = XCAR (color_symbols);
6214 if (!CONSP (sym)
6215 || !STRINGP (XCAR (sym))
6216 || !STRINGP (XCDR (sym)))
6217 break;
6218 color_symbols = XCDR (color_symbols);
6221 return NILP (color_symbols);
6225 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6227 static int
6228 xpm_image_p (object)
6229 Lisp_Object object;
6231 struct image_keyword fmt[XPM_LAST];
6232 bcopy (xpm_format, fmt, sizeof fmt);
6233 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6234 /* Either `:file' or `:data' must be present. */
6235 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6236 /* Either no `:color-symbols' or it's a list of conses
6237 whose car and cdr are strings. */
6238 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6239 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
6240 && (fmt[XPM_ASCENT].count == 0
6241 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
6245 /* Load image IMG which will be displayed on frame F. Value is
6246 non-zero if successful. */
6248 static int
6249 xpm_load (f, img)
6250 struct frame *f;
6251 struct image *img;
6253 int rc, i;
6254 XpmAttributes attrs;
6255 Lisp_Object specified_file, color_symbols;
6257 /* Configure the XPM lib. Use the visual of frame F. Allocate
6258 close colors. Return colors allocated. */
6259 bzero (&attrs, sizeof attrs);
6260 attrs.visual = FRAME_X_VISUAL (f);
6261 attrs.colormap = FRAME_X_COLORMAP (f);
6262 attrs.valuemask |= XpmVisual;
6263 attrs.valuemask |= XpmColormap;
6264 attrs.valuemask |= XpmReturnAllocPixels;
6265 #ifdef XpmAllocCloseColors
6266 attrs.alloc_close_colors = 1;
6267 attrs.valuemask |= XpmAllocCloseColors;
6268 #else
6269 attrs.closeness = 600;
6270 attrs.valuemask |= XpmCloseness;
6271 #endif
6273 /* If image specification contains symbolic color definitions, add
6274 these to `attrs'. */
6275 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6276 if (CONSP (color_symbols))
6278 Lisp_Object tail;
6279 XpmColorSymbol *xpm_syms;
6280 int i, size;
6282 attrs.valuemask |= XpmColorSymbols;
6284 /* Count number of symbols. */
6285 attrs.numsymbols = 0;
6286 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6287 ++attrs.numsymbols;
6289 /* Allocate an XpmColorSymbol array. */
6290 size = attrs.numsymbols * sizeof *xpm_syms;
6291 xpm_syms = (XpmColorSymbol *) alloca (size);
6292 bzero (xpm_syms, size);
6293 attrs.colorsymbols = xpm_syms;
6295 /* Fill the color symbol array. */
6296 for (tail = color_symbols, i = 0;
6297 CONSP (tail);
6298 ++i, tail = XCDR (tail))
6300 Lisp_Object name = XCAR (XCAR (tail));
6301 Lisp_Object color = XCDR (XCAR (tail));
6302 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
6303 strcpy (xpm_syms[i].name, SDATA (name));
6304 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
6305 strcpy (xpm_syms[i].value, SDATA (color));
6309 /* Create a pixmap for the image, either from a file, or from a
6310 string buffer containing data in the same format as an XPM file. */
6311 BLOCK_INPUT;
6312 specified_file = image_spec_value (img->spec, QCfile, NULL);
6313 if (STRINGP (specified_file))
6315 Lisp_Object file = x_find_image_file (specified_file);
6316 if (!STRINGP (file))
6318 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6319 UNBLOCK_INPUT;
6320 return 0;
6323 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
6324 SDATA (file), &img->pixmap, &img->mask,
6325 &attrs);
6327 else
6329 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6330 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
6331 SDATA (buffer),
6332 &img->pixmap, &img->mask,
6333 &attrs);
6335 UNBLOCK_INPUT;
6337 if (rc == XpmSuccess)
6339 /* Remember allocated colors. */
6340 img->ncolors = attrs.nalloc_pixels;
6341 img->colors = (unsigned long *) xmalloc (img->ncolors
6342 * sizeof *img->colors);
6343 for (i = 0; i < attrs.nalloc_pixels; ++i)
6344 img->colors[i] = attrs.alloc_pixels[i];
6346 img->width = attrs.width;
6347 img->height = attrs.height;
6348 xassert (img->width > 0 && img->height > 0);
6350 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6351 BLOCK_INPUT;
6352 XpmFreeAttributes (&attrs);
6353 UNBLOCK_INPUT;
6355 else
6357 switch (rc)
6359 case XpmOpenFailed:
6360 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6361 break;
6363 case XpmFileInvalid:
6364 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6365 break;
6367 case XpmNoMemory:
6368 image_error ("Out of memory (%s)", img->spec, Qnil);
6369 break;
6371 case XpmColorFailed:
6372 image_error ("Color allocation error (%s)", img->spec, Qnil);
6373 break;
6375 default:
6376 image_error ("Unknown error (%s)", img->spec, Qnil);
6377 break;
6381 return rc == XpmSuccess;
6384 #endif /* HAVE_XPM != 0 */
6387 #if 0 /* MAC_TODO : Color tables on Mac. */
6388 /***********************************************************************
6389 Color table
6390 ***********************************************************************/
6392 /* An entry in the color table mapping an RGB color to a pixel color. */
6394 struct ct_color
6396 int r, g, b;
6397 unsigned long pixel;
6399 /* Next in color table collision list. */
6400 struct ct_color *next;
6403 /* The bucket vector size to use. Must be prime. */
6405 #define CT_SIZE 101
6407 /* Value is a hash of the RGB color given by R, G, and B. */
6409 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6411 /* The color hash table. */
6413 struct ct_color **ct_table;
6415 /* Number of entries in the color table. */
6417 int ct_colors_allocated;
6419 /* Function prototypes. */
6421 static void init_color_table P_ ((void));
6422 static void free_color_table P_ ((void));
6423 static unsigned long *colors_in_color_table P_ ((int *n));
6424 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
6425 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
6428 /* Initialize the color table. */
6430 static void
6431 init_color_table ()
6433 int size = CT_SIZE * sizeof (*ct_table);
6434 ct_table = (struct ct_color **) xmalloc (size);
6435 bzero (ct_table, size);
6436 ct_colors_allocated = 0;
6440 /* Free memory associated with the color table. */
6442 static void
6443 free_color_table ()
6445 int i;
6446 struct ct_color *p, *next;
6448 for (i = 0; i < CT_SIZE; ++i)
6449 for (p = ct_table[i]; p; p = next)
6451 next = p->next;
6452 xfree (p);
6455 xfree (ct_table);
6456 ct_table = NULL;
6460 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6461 entry for that color already is in the color table, return the
6462 pixel color of that entry. Otherwise, allocate a new color for R,
6463 G, B, and make an entry in the color table. */
6465 static unsigned long
6466 lookup_rgb_color (f, r, g, b)
6467 struct frame *f;
6468 int r, g, b;
6470 unsigned hash = CT_HASH_RGB (r, g, b);
6471 int i = hash % CT_SIZE;
6472 struct ct_color *p;
6474 for (p = ct_table[i]; p; p = p->next)
6475 if (p->r == r && p->g == g && p->b == b)
6476 break;
6478 if (p == NULL)
6480 COLORREF color;
6481 Colormap cmap;
6482 int rc;
6484 color = RGB_TO_ULONG (r, g, b);
6486 ++ct_colors_allocated;
6488 p = (struct ct_color *) xmalloc (sizeof *p);
6489 p->r = r;
6490 p->g = g;
6491 p->b = b;
6492 p->pixel = color;
6493 p->next = ct_table[i];
6494 ct_table[i] = p;
6497 return p->pixel;
6501 /* Look up pixel color PIXEL which is used on frame F in the color
6502 table. If not already present, allocate it. Value is PIXEL. */
6504 static unsigned long
6505 lookup_pixel_color (f, pixel)
6506 struct frame *f;
6507 unsigned long pixel;
6509 int i = pixel % CT_SIZE;
6510 struct ct_color *p;
6512 for (p = ct_table[i]; p; p = p->next)
6513 if (p->pixel == pixel)
6514 break;
6516 if (p == NULL)
6518 XColor color;
6519 Colormap cmap;
6520 int rc;
6522 BLOCK_INPUT;
6524 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6525 color.pixel = pixel;
6526 XQueryColor (NULL, cmap, &color);
6527 rc = x_alloc_nearest_color (f, cmap, &color);
6528 UNBLOCK_INPUT;
6530 if (rc)
6532 ++ct_colors_allocated;
6534 p = (struct ct_color *) xmalloc (sizeof *p);
6535 p->r = color.red;
6536 p->g = color.green;
6537 p->b = color.blue;
6538 p->pixel = pixel;
6539 p->next = ct_table[i];
6540 ct_table[i] = p;
6542 else
6543 return FRAME_FOREGROUND_PIXEL (f);
6545 return p->pixel;
6549 /* Value is a vector of all pixel colors contained in the color table,
6550 allocated via xmalloc. Set *N to the number of colors. */
6552 static unsigned long *
6553 colors_in_color_table (n)
6554 int *n;
6556 int i, j;
6557 struct ct_color *p;
6558 unsigned long *colors;
6560 if (ct_colors_allocated == 0)
6562 *n = 0;
6563 colors = NULL;
6565 else
6567 colors = (unsigned long *) xmalloc (ct_colors_allocated
6568 * sizeof *colors);
6569 *n = ct_colors_allocated;
6571 for (i = j = 0; i < CT_SIZE; ++i)
6572 for (p = ct_table[i]; p; p = p->next)
6573 colors[j++] = p->pixel;
6576 return colors;
6579 #endif /* MAC_TODO */
6582 /***********************************************************************
6583 Algorithms
6584 ***********************************************************************/
6586 #if 0 /* MAC_TODO : Mac versions of low level algorithms */
6587 static void x_laplace_write_row P_ ((struct frame *, long *,
6588 int, XImage *, int));
6589 static void x_laplace_read_row P_ ((struct frame *, Colormap,
6590 XColor *, int, XImage *, int));
6593 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
6594 frame we operate on, CMAP is the color-map in effect, and WIDTH is
6595 the width of one row in the image. */
6597 static void
6598 x_laplace_read_row (f, cmap, colors, width, ximg, y)
6599 struct frame *f;
6600 Colormap cmap;
6601 XColor *colors;
6602 int width;
6603 XImage *ximg;
6604 int y;
6606 int x;
6608 for (x = 0; x < width; ++x)
6609 colors[x].pixel = XGetPixel (ximg, x, y);
6611 XQueryColors (NULL, cmap, colors, width);
6615 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
6616 containing the pixel colors to write. F is the frame we are
6617 working on. */
6619 static void
6620 x_laplace_write_row (f, pixels, width, ximg, y)
6621 struct frame *f;
6622 long *pixels;
6623 int width;
6624 XImage *ximg;
6625 int y;
6627 int x;
6629 for (x = 0; x < width; ++x)
6630 XPutPixel (ximg, x, y, pixels[x]);
6632 #endif /* MAC_TODO */
6634 /* Transform image IMG which is used on frame F with a Laplace
6635 edge-detection algorithm. The result is an image that can be used
6636 to draw disabled buttons, for example. */
6638 static void
6639 x_laplace (f, img)
6640 struct frame *f;
6641 struct image *img;
6643 #if 0 /* MAC_TODO : Mac version */
6644 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6645 XImage *ximg, *oimg;
6646 XColor *in[3];
6647 long *out;
6648 Pixmap pixmap;
6649 int x, y, i;
6650 long pixel;
6651 int in_y, out_y, rc;
6652 int mv2 = 45000;
6654 BLOCK_INPUT;
6656 /* Get the X image IMG->pixmap. */
6657 ximg = XGetImage (NULL, img->pixmap,
6658 0, 0, img->width, img->height, ~0, ZPixmap);
6660 /* Allocate 3 input rows, and one output row of colors. */
6661 for (i = 0; i < 3; ++i)
6662 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
6663 out = (long *) alloca (img->width * sizeof (long));
6665 /* Create an X image for output. */
6666 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
6667 &oimg, &pixmap);
6669 /* Fill first two rows. */
6670 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
6671 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
6672 in_y = 2;
6674 /* Write first row, all zeros. */
6675 init_color_table ();
6676 pixel = lookup_rgb_color (f, 0, 0, 0);
6677 for (x = 0; x < img->width; ++x)
6678 out[x] = pixel;
6679 x_laplace_write_row (f, out, img->width, oimg, 0);
6680 out_y = 1;
6682 for (y = 2; y < img->height; ++y)
6684 int rowa = y % 3;
6685 int rowb = (y + 2) % 3;
6687 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
6689 for (x = 0; x < img->width - 2; ++x)
6691 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
6692 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
6693 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
6695 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
6696 b & 0xffff);
6699 x_laplace_write_row (f, out, img->width, oimg, out_y++);
6702 /* Write last line, all zeros. */
6703 for (x = 0; x < img->width; ++x)
6704 out[x] = pixel;
6705 x_laplace_write_row (f, out, img->width, oimg, out_y);
6707 /* Free the input image, and free resources of IMG. */
6708 XDestroyImage (ximg);
6709 x_clear_image (f, img);
6711 /* Put the output image into pixmap, and destroy it. */
6712 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6713 x_destroy_x_image (oimg);
6715 /* Remember new pixmap and colors in IMG. */
6716 img->pixmap = pixmap;
6717 img->colors = colors_in_color_table (&img->ncolors);
6718 free_color_table ();
6720 UNBLOCK_INPUT;
6721 #endif /* MAC_TODO */
6725 /* Build a mask for image IMG which is used on frame F. FILE is the
6726 name of an image file, for error messages. HOW determines how to
6727 determine the background color of IMG. If it is a list '(R G B)',
6728 with R, G, and B being integers >= 0, take that as the color of the
6729 background. Otherwise, determine the background color of IMG
6730 heuristically. Value is non-zero if successful. */
6732 static int
6733 x_build_heuristic_mask (f, img, how)
6734 struct frame *f;
6735 struct image *img;
6736 Lisp_Object how;
6738 #if 0 /* MAC_TODO : Mac version */
6739 Display *dpy = FRAME_W32_DISPLAY (f);
6740 XImage *ximg, *mask_img;
6741 int x, y, rc, look_at_corners_p;
6742 unsigned long bg;
6744 BLOCK_INPUT;
6746 /* Create an image and pixmap serving as mask. */
6747 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
6748 &mask_img, &img->mask);
6749 if (!rc)
6751 UNBLOCK_INPUT;
6752 return 0;
6755 /* Get the X image of IMG->pixmap. */
6756 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
6757 ~0, ZPixmap);
6759 /* Determine the background color of ximg. If HOW is `(R G B)'
6760 take that as color. Otherwise, try to determine the color
6761 heuristically. */
6762 look_at_corners_p = 1;
6764 if (CONSP (how))
6766 int rgb[3], i = 0;
6768 while (i < 3
6769 && CONSP (how)
6770 && NATNUMP (XCAR (how)))
6772 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
6773 how = XCDR (how);
6776 if (i == 3 && NILP (how))
6778 char color_name[30];
6779 XColor exact, color;
6780 Colormap cmap;
6782 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
6784 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6785 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
6787 bg = color.pixel;
6788 look_at_corners_p = 0;
6793 if (look_at_corners_p)
6795 unsigned long corners[4];
6796 int i, best_count;
6798 /* Get the colors at the corners of ximg. */
6799 corners[0] = XGetPixel (ximg, 0, 0);
6800 corners[1] = XGetPixel (ximg, img->width - 1, 0);
6801 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
6802 corners[3] = XGetPixel (ximg, 0, img->height - 1);
6804 /* Choose the most frequently found color as background. */
6805 for (i = best_count = 0; i < 4; ++i)
6807 int j, n;
6809 for (j = n = 0; j < 4; ++j)
6810 if (corners[i] == corners[j])
6811 ++n;
6813 if (n > best_count)
6814 bg = corners[i], best_count = n;
6818 /* Set all bits in mask_img to 1 whose color in ximg is different
6819 from the background color bg. */
6820 for (y = 0; y < img->height; ++y)
6821 for (x = 0; x < img->width; ++x)
6822 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
6824 /* Put mask_img into img->mask. */
6825 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6826 x_destroy_x_image (mask_img);
6827 XDestroyImage (ximg);
6829 UNBLOCK_INPUT;
6830 #endif /* MAC_TODO */
6832 return 1;
6837 /***********************************************************************
6838 PBM (mono, gray, color)
6839 ***********************************************************************/
6840 #ifdef HAVE_PBM
6842 static int pbm_image_p P_ ((Lisp_Object object));
6843 static int pbm_load P_ ((struct frame *f, struct image *img));
6844 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
6846 /* The symbol `pbm' identifying images of this type. */
6848 Lisp_Object Qpbm;
6850 /* Indices of image specification fields in gs_format, below. */
6852 enum pbm_keyword_index
6854 PBM_TYPE,
6855 PBM_FILE,
6856 PBM_DATA,
6857 PBM_ASCENT,
6858 PBM_MARGIN,
6859 PBM_RELIEF,
6860 PBM_ALGORITHM,
6861 PBM_HEURISTIC_MASK,
6862 PBM_LAST
6865 /* Vector of image_keyword structures describing the format
6866 of valid user-defined image specifications. */
6868 static struct image_keyword pbm_format[PBM_LAST] =
6870 {":type", IMAGE_SYMBOL_VALUE, 1},
6871 {":file", IMAGE_STRING_VALUE, 0},
6872 {":data", IMAGE_STRING_VALUE, 0},
6873 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6874 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6875 {":relief", IMAGE_INTEGER_VALUE, 0},
6876 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6877 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6880 /* Structure describing the image type `pbm'. */
6882 static struct image_type pbm_type =
6884 &Qpbm,
6885 pbm_image_p,
6886 pbm_load,
6887 x_clear_image,
6888 NULL
6892 /* Return non-zero if OBJECT is a valid PBM image specification. */
6894 static int
6895 pbm_image_p (object)
6896 Lisp_Object object;
6898 struct image_keyword fmt[PBM_LAST];
6900 bcopy (pbm_format, fmt, sizeof fmt);
6902 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
6903 || (fmt[PBM_ASCENT].count
6904 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
6905 return 0;
6907 /* Must specify either :data or :file. */
6908 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
6912 /* Scan a decimal number from *S and return it. Advance *S while
6913 reading the number. END is the end of the string. Value is -1 at
6914 end of input. */
6916 static int
6917 pbm_scan_number (s, end)
6918 unsigned char **s, *end;
6920 int c, val = -1;
6922 while (*s < end)
6924 /* Skip white-space. */
6925 while (*s < end && (c = *(*s)++, isspace (c)))
6928 if (c == '#')
6930 /* Skip comment to end of line. */
6931 while (*s < end && (c = *(*s)++, c != '\n'))
6934 else if (isdigit (c))
6936 /* Read decimal number. */
6937 val = c - '0';
6938 while (*s < end && (c = *(*s)++, isdigit (c)))
6939 val = 10 * val + c - '0';
6940 break;
6942 else
6943 break;
6946 return val;
6950 /* Read FILE into memory. Value is a pointer to a buffer allocated
6951 with xmalloc holding FILE's contents. Value is null if an error
6952 occurred. *SIZE is set to the size of the file. */
6954 static char *
6955 pbm_read_file (file, size)
6956 Lisp_Object file;
6957 int *size;
6959 FILE *fp = NULL;
6960 char *buf = NULL;
6961 struct stat st;
6963 if (stat (SDATA (file), &st) == 0
6964 && (fp = fopen (SDATA (file), "r")) != NULL
6965 && (buf = (char *) xmalloc (st.st_size),
6966 fread (buf, 1, st.st_size, fp) == st.st_size))
6968 *size = st.st_size;
6969 fclose (fp);
6971 else
6973 if (fp)
6974 fclose (fp);
6975 if (buf)
6977 xfree (buf);
6978 buf = NULL;
6982 return buf;
6986 /* Load PBM image IMG for use on frame F. */
6988 static int
6989 pbm_load (f, img)
6990 struct frame *f;
6991 struct image *img;
6993 int raw_p, x, y;
6994 int width, height, max_color_idx = 0;
6995 XImage *ximg;
6996 Lisp_Object file, specified_file;
6997 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
6998 struct gcpro gcpro1;
6999 unsigned char *contents = NULL;
7000 unsigned char *end, *p;
7001 int size;
7003 specified_file = image_spec_value (img->spec, QCfile, NULL);
7004 file = Qnil;
7005 GCPRO1 (file);
7007 if (STRINGP (specified_file))
7009 file = x_find_image_file (specified_file);
7010 if (!STRINGP (file))
7012 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7013 UNGCPRO;
7014 return 0;
7017 contents = pbm_read_file (file, &size);
7018 if (contents == NULL)
7020 image_error ("Error reading `%s'", file, Qnil);
7021 UNGCPRO;
7022 return 0;
7025 p = contents;
7026 end = contents + size;
7028 else
7030 Lisp_Object data;
7031 data = image_spec_value (img->spec, QCdata, NULL);
7032 p = SDATA (data);
7033 end = p + SBYTES (data);
7036 /* Check magic number. */
7037 if (end - p < 2 || *p++ != 'P')
7039 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7040 error:
7041 xfree (contents);
7042 UNGCPRO;
7043 return 0;
7046 switch (*p++)
7048 case '1':
7049 raw_p = 0, type = PBM_MONO;
7050 break;
7052 case '2':
7053 raw_p = 0, type = PBM_GRAY;
7054 break;
7056 case '3':
7057 raw_p = 0, type = PBM_COLOR;
7058 break;
7060 case '4':
7061 raw_p = 1, type = PBM_MONO;
7062 break;
7064 case '5':
7065 raw_p = 1, type = PBM_GRAY;
7066 break;
7068 case '6':
7069 raw_p = 1, type = PBM_COLOR;
7070 break;
7072 default:
7073 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7074 goto error;
7077 /* Read width, height, maximum color-component. Characters
7078 starting with `#' up to the end of a line are ignored. */
7079 width = pbm_scan_number (&p, end);
7080 height = pbm_scan_number (&p, end);
7082 if (type != PBM_MONO)
7084 max_color_idx = pbm_scan_number (&p, end);
7085 if (raw_p && max_color_idx > 255)
7086 max_color_idx = 255;
7089 if (width < 0
7090 || height < 0
7091 || (type != PBM_MONO && max_color_idx < 0))
7092 goto error;
7094 BLOCK_INPUT;
7095 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7096 &ximg, &img->pixmap))
7098 UNBLOCK_INPUT;
7099 goto error;
7102 /* Initialize the color hash table. */
7103 init_color_table ();
7105 if (type == PBM_MONO)
7107 int c = 0, g;
7109 for (y = 0; y < height; ++y)
7110 for (x = 0; x < width; ++x)
7112 if (raw_p)
7114 if ((x & 7) == 0)
7115 c = *p++;
7116 g = c & 0x80;
7117 c <<= 1;
7119 else
7120 g = pbm_scan_number (&p, end);
7122 XPutPixel (ximg, x, y, (g
7123 ? FRAME_FOREGROUND_PIXEL (f)
7124 : FRAME_BACKGROUND_PIXEL (f)));
7127 else
7129 for (y = 0; y < height; ++y)
7130 for (x = 0; x < width; ++x)
7132 int r, g, b;
7134 if (type == PBM_GRAY)
7135 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7136 else if (raw_p)
7138 r = *p++;
7139 g = *p++;
7140 b = *p++;
7142 else
7144 r = pbm_scan_number (&p, end);
7145 g = pbm_scan_number (&p, end);
7146 b = pbm_scan_number (&p, end);
7149 if (r < 0 || g < 0 || b < 0)
7151 xfree (ximg->data);
7152 ximg->data = NULL;
7153 XDestroyImage (ximg);
7154 UNBLOCK_INPUT;
7155 image_error ("Invalid pixel value in image `%s'",
7156 img->spec, Qnil);
7157 goto error;
7160 /* RGB values are now in the range 0..max_color_idx.
7161 Scale this to the range 0..0xffff supported by X. */
7162 r = (double) r * 65535 / max_color_idx;
7163 g = (double) g * 65535 / max_color_idx;
7164 b = (double) b * 65535 / max_color_idx;
7165 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7169 /* Store in IMG->colors the colors allocated for the image, and
7170 free the color table. */
7171 img->colors = colors_in_color_table (&img->ncolors);
7172 free_color_table ();
7174 /* Put the image into a pixmap. */
7175 x_put_x_image (f, ximg, img->pixmap, width, height);
7176 x_destroy_x_image (ximg);
7177 UNBLOCK_INPUT;
7179 img->width = width;
7180 img->height = height;
7182 UNGCPRO;
7183 xfree (contents);
7184 return 1;
7186 #endif /* HAVE_PBM */
7189 /***********************************************************************
7191 ***********************************************************************/
7193 #if HAVE_PNG
7195 #include <png.h>
7197 /* Function prototypes. */
7199 static int png_image_p P_ ((Lisp_Object object));
7200 static int png_load P_ ((struct frame *f, struct image *img));
7202 /* The symbol `png' identifying images of this type. */
7204 Lisp_Object Qpng;
7206 /* Indices of image specification fields in png_format, below. */
7208 enum png_keyword_index
7210 PNG_TYPE,
7211 PNG_DATA,
7212 PNG_FILE,
7213 PNG_ASCENT,
7214 PNG_MARGIN,
7215 PNG_RELIEF,
7216 PNG_ALGORITHM,
7217 PNG_HEURISTIC_MASK,
7218 PNG_LAST
7221 /* Vector of image_keyword structures describing the format
7222 of valid user-defined image specifications. */
7224 static struct image_keyword png_format[PNG_LAST] =
7226 {":type", IMAGE_SYMBOL_VALUE, 1},
7227 {":data", IMAGE_STRING_VALUE, 0},
7228 {":file", IMAGE_STRING_VALUE, 0},
7229 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7230 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7231 {":relief", IMAGE_INTEGER_VALUE, 0},
7232 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7233 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7236 /* Structure describing the image type `png'. */
7238 static struct image_type png_type =
7240 &Qpng,
7241 png_image_p,
7242 png_load,
7243 x_clear_image,
7244 NULL
7248 /* Return non-zero if OBJECT is a valid PNG image specification. */
7250 static int
7251 png_image_p (object)
7252 Lisp_Object object;
7254 struct image_keyword fmt[PNG_LAST];
7255 bcopy (png_format, fmt, sizeof fmt);
7257 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
7258 || (fmt[PNG_ASCENT].count
7259 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
7260 return 0;
7262 /* Must specify either the :data or :file keyword. */
7263 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7267 /* Error and warning handlers installed when the PNG library
7268 is initialized. */
7270 static void
7271 my_png_error (png_ptr, msg)
7272 png_struct *png_ptr;
7273 char *msg;
7275 xassert (png_ptr != NULL);
7276 image_error ("PNG error: %s", build_string (msg), Qnil);
7277 longjmp (png_ptr->jmpbuf, 1);
7281 static void
7282 my_png_warning (png_ptr, msg)
7283 png_struct *png_ptr;
7284 char *msg;
7286 xassert (png_ptr != NULL);
7287 image_error ("PNG warning: %s", build_string (msg), Qnil);
7290 /* Memory source for PNG decoding. */
7292 struct png_memory_storage
7294 unsigned char *bytes; /* The data */
7295 size_t len; /* How big is it? */
7296 int index; /* Where are we? */
7300 /* Function set as reader function when reading PNG image from memory.
7301 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7302 bytes from the input to DATA. */
7304 static void
7305 png_read_from_memory (png_ptr, data, length)
7306 png_structp png_ptr;
7307 png_bytep data;
7308 png_size_t length;
7310 struct png_memory_storage *tbr
7311 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7313 if (length > tbr->len - tbr->index)
7314 png_error (png_ptr, "Read error");
7316 bcopy (tbr->bytes + tbr->index, data, length);
7317 tbr->index = tbr->index + length;
7320 /* Load PNG image IMG for use on frame F. Value is non-zero if
7321 successful. */
7323 static int
7324 png_load (f, img)
7325 struct frame *f;
7326 struct image *img;
7328 Lisp_Object file, specified_file;
7329 Lisp_Object specified_data;
7330 int x, y, i;
7331 XImage *ximg, *mask_img = NULL;
7332 struct gcpro gcpro1;
7333 png_struct *png_ptr = NULL;
7334 png_info *info_ptr = NULL, *end_info = NULL;
7335 FILE *fp = NULL;
7336 png_byte sig[8];
7337 png_byte *pixels = NULL;
7338 png_byte **rows = NULL;
7339 png_uint_32 width, height;
7340 int bit_depth, color_type, interlace_type;
7341 png_byte channels;
7342 png_uint_32 row_bytes;
7343 int transparent_p;
7344 char *gamma_str;
7345 double screen_gamma, image_gamma;
7346 int intent;
7347 struct png_memory_storage tbr; /* Data to be read */
7349 /* Find out what file to load. */
7350 specified_file = image_spec_value (img->spec, QCfile, NULL);
7351 specified_data = image_spec_value (img->spec, QCdata, NULL);
7352 file = Qnil;
7353 GCPRO1 (file);
7355 if (NILP (specified_data))
7357 file = x_find_image_file (specified_file);
7358 if (!STRINGP (file))
7360 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7361 UNGCPRO;
7362 return 0;
7365 /* Open the image file. */
7366 fp = fopen (SDATA (file), "rb");
7367 if (!fp)
7369 image_error ("Cannot open image file `%s'", file, Qnil);
7370 UNGCPRO;
7371 fclose (fp);
7372 return 0;
7375 /* Check PNG signature. */
7376 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7377 || !png_check_sig (sig, sizeof sig))
7379 image_error ("Not a PNG file:` %s'", file, Qnil);
7380 UNGCPRO;
7381 fclose (fp);
7382 return 0;
7385 else
7387 /* Read from memory. */
7388 tbr.bytes = SDATA (specified_data);
7389 tbr.len = SBYTES (specified_data);
7390 tbr.index = 0;
7392 /* Check PNG signature. */
7393 if (tbr.len < sizeof sig
7394 || !png_check_sig (tbr.bytes, sizeof sig))
7396 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7397 UNGCPRO;
7398 return 0;
7401 /* Need to skip past the signature. */
7402 tbr.bytes += sizeof (sig);
7405 /* Initialize read and info structs for PNG lib. */
7406 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7407 my_png_error, my_png_warning);
7408 if (!png_ptr)
7410 if (fp) fclose (fp);
7411 UNGCPRO;
7412 return 0;
7415 info_ptr = png_create_info_struct (png_ptr);
7416 if (!info_ptr)
7418 png_destroy_read_struct (&png_ptr, NULL, NULL);
7419 if (fp) fclose (fp);
7420 UNGCPRO;
7421 return 0;
7424 end_info = png_create_info_struct (png_ptr);
7425 if (!end_info)
7427 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7428 if (fp) fclose (fp);
7429 UNGCPRO;
7430 return 0;
7433 /* Set error jump-back. We come back here when the PNG library
7434 detects an error. */
7435 if (setjmp (png_ptr->jmpbuf))
7437 error:
7438 if (png_ptr)
7439 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7440 xfree (pixels);
7441 xfree (rows);
7442 if (fp) fclose (fp);
7443 UNGCPRO;
7444 return 0;
7447 /* Read image info. */
7448 if (!NILP (specified_data))
7449 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7450 else
7451 png_init_io (png_ptr, fp);
7453 png_set_sig_bytes (png_ptr, sizeof sig);
7454 png_read_info (png_ptr, info_ptr);
7455 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7456 &interlace_type, NULL, NULL);
7458 /* If image contains simply transparency data, we prefer to
7459 construct a clipping mask. */
7460 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7461 transparent_p = 1;
7462 else
7463 transparent_p = 0;
7465 /* This function is easier to write if we only have to handle
7466 one data format: RGB or RGBA with 8 bits per channel. Let's
7467 transform other formats into that format. */
7469 /* Strip more than 8 bits per channel. */
7470 if (bit_depth == 16)
7471 png_set_strip_16 (png_ptr);
7473 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7474 if available. */
7475 png_set_expand (png_ptr);
7477 /* Convert grayscale images to RGB. */
7478 if (color_type == PNG_COLOR_TYPE_GRAY
7479 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7480 png_set_gray_to_rgb (png_ptr);
7482 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7483 gamma_str = getenv ("SCREEN_GAMMA");
7484 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
7486 /* Tell the PNG lib to handle gamma correction for us. */
7488 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7489 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7490 /* There is a special chunk in the image specifying the gamma. */
7491 png_set_sRGB (png_ptr, info_ptr, intent);
7492 else
7493 #endif
7494 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7495 /* Image contains gamma information. */
7496 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7497 else
7498 /* Use a default of 0.5 for the image gamma. */
7499 png_set_gamma (png_ptr, screen_gamma, 0.5);
7501 /* Handle alpha channel by combining the image with a background
7502 color. Do this only if a real alpha channel is supplied. For
7503 simple transparency, we prefer a clipping mask. */
7504 if (!transparent_p)
7506 png_color_16 *image_background;
7508 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
7509 /* Image contains a background color with which to
7510 combine the image. */
7511 png_set_background (png_ptr, image_background,
7512 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7513 else
7515 /* Image does not contain a background color with which
7516 to combine the image data via an alpha channel. Use
7517 the frame's background instead. */
7518 XColor color;
7519 Colormap cmap;
7520 png_color_16 frame_background;
7522 BLOCK_INPUT;
7523 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7524 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7525 XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
7526 UNBLOCK_INPUT;
7528 bzero (&frame_background, sizeof frame_background);
7529 frame_background.red = color.red;
7530 frame_background.green = color.green;
7531 frame_background.blue = color.blue;
7533 png_set_background (png_ptr, &frame_background,
7534 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7538 /* Update info structure. */
7539 png_read_update_info (png_ptr, info_ptr);
7541 /* Get number of channels. Valid values are 1 for grayscale images
7542 and images with a palette, 2 for grayscale images with transparency
7543 information (alpha channel), 3 for RGB images, and 4 for RGB
7544 images with alpha channel, i.e. RGBA. If conversions above were
7545 sufficient we should only have 3 or 4 channels here. */
7546 channels = png_get_channels (png_ptr, info_ptr);
7547 xassert (channels == 3 || channels == 4);
7549 /* Number of bytes needed for one row of the image. */
7550 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7552 /* Allocate memory for the image. */
7553 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7554 rows = (png_byte **) xmalloc (height * sizeof *rows);
7555 for (i = 0; i < height; ++i)
7556 rows[i] = pixels + i * row_bytes;
7558 /* Read the entire image. */
7559 png_read_image (png_ptr, rows);
7560 png_read_end (png_ptr, info_ptr);
7561 if (fp)
7563 fclose (fp);
7564 fp = NULL;
7567 BLOCK_INPUT;
7569 /* Create the X image and pixmap. */
7570 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7571 &img->pixmap))
7573 UNBLOCK_INPUT;
7574 goto error;
7577 /* Create an image and pixmap serving as mask if the PNG image
7578 contains an alpha channel. */
7579 if (channels == 4
7580 && !transparent_p
7581 && !x_create_x_image_and_pixmap (f, width, height, 1,
7582 &mask_img, &img->mask))
7584 x_destroy_x_image (ximg);
7585 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
7586 img->pixmap = 0;
7587 UNBLOCK_INPUT;
7588 goto error;
7591 /* Fill the X image and mask from PNG data. */
7592 init_color_table ();
7594 for (y = 0; y < height; ++y)
7596 png_byte *p = rows[y];
7598 for (x = 0; x < width; ++x)
7600 unsigned r, g, b;
7602 r = *p++ << 8;
7603 g = *p++ << 8;
7604 b = *p++ << 8;
7605 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7607 /* An alpha channel, aka mask channel, associates variable
7608 transparency with an image. Where other image formats
7609 support binary transparency---fully transparent or fully
7610 opaque---PNG allows up to 254 levels of partial transparency.
7611 The PNG library implements partial transparency by combining
7612 the image with a specified background color.
7614 I'm not sure how to handle this here nicely: because the
7615 background on which the image is displayed may change, for
7616 real alpha channel support, it would be necessary to create
7617 a new image for each possible background.
7619 What I'm doing now is that a mask is created if we have
7620 boolean transparency information. Otherwise I'm using
7621 the frame's background color to combine the image with. */
7623 if (channels == 4)
7625 if (mask_img)
7626 XPutPixel (mask_img, x, y, *p > 0);
7627 ++p;
7632 /* Remember colors allocated for this image. */
7633 img->colors = colors_in_color_table (&img->ncolors);
7634 free_color_table ();
7636 /* Clean up. */
7637 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7638 xfree (rows);
7639 xfree (pixels);
7641 img->width = width;
7642 img->height = height;
7644 /* Put the image into the pixmap, then free the X image and its buffer. */
7645 x_put_x_image (f, ximg, img->pixmap, width, height);
7646 x_destroy_x_image (ximg);
7648 /* Same for the mask. */
7649 if (mask_img)
7651 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7652 x_destroy_x_image (mask_img);
7655 UNBLOCK_INPUT;
7656 UNGCPRO;
7657 return 1;
7660 #endif /* HAVE_PNG != 0 */
7664 /***********************************************************************
7665 JPEG
7666 ***********************************************************************/
7668 #if HAVE_JPEG
7670 /* Work around a warning about HAVE_STDLIB_H being redefined in
7671 jconfig.h. */
7672 #ifdef HAVE_STDLIB_H
7673 #define HAVE_STDLIB_H_1
7674 #undef HAVE_STDLIB_H
7675 #endif /* HAVE_STLIB_H */
7677 #include <jpeglib.h>
7678 #include <jerror.h>
7679 #include <setjmp.h>
7681 #ifdef HAVE_STLIB_H_1
7682 #define HAVE_STDLIB_H 1
7683 #endif
7685 static int jpeg_image_p P_ ((Lisp_Object object));
7686 static int jpeg_load P_ ((struct frame *f, struct image *img));
7688 /* The symbol `jpeg' identifying images of this type. */
7690 Lisp_Object Qjpeg;
7692 /* Indices of image specification fields in gs_format, below. */
7694 enum jpeg_keyword_index
7696 JPEG_TYPE,
7697 JPEG_DATA,
7698 JPEG_FILE,
7699 JPEG_ASCENT,
7700 JPEG_MARGIN,
7701 JPEG_RELIEF,
7702 JPEG_ALGORITHM,
7703 JPEG_HEURISTIC_MASK,
7704 JPEG_LAST
7707 /* Vector of image_keyword structures describing the format
7708 of valid user-defined image specifications. */
7710 static struct image_keyword jpeg_format[JPEG_LAST] =
7712 {":type", IMAGE_SYMBOL_VALUE, 1},
7713 {":data", IMAGE_STRING_VALUE, 0},
7714 {":file", IMAGE_STRING_VALUE, 0},
7715 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7716 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7717 {":relief", IMAGE_INTEGER_VALUE, 0},
7718 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7719 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7722 /* Structure describing the image type `jpeg'. */
7724 static struct image_type jpeg_type =
7726 &Qjpeg,
7727 jpeg_image_p,
7728 jpeg_load,
7729 x_clear_image,
7730 NULL
7734 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7736 static int
7737 jpeg_image_p (object)
7738 Lisp_Object object;
7740 struct image_keyword fmt[JPEG_LAST];
7742 bcopy (jpeg_format, fmt, sizeof fmt);
7744 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
7745 || (fmt[JPEG_ASCENT].count
7746 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
7747 return 0;
7749 /* Must specify either the :data or :file keyword. */
7750 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
7754 struct my_jpeg_error_mgr
7756 struct jpeg_error_mgr pub;
7757 jmp_buf setjmp_buffer;
7760 static void
7761 my_error_exit (cinfo)
7762 j_common_ptr cinfo;
7764 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7765 longjmp (mgr->setjmp_buffer, 1);
7768 /* Init source method for JPEG data source manager. Called by
7769 jpeg_read_header() before any data is actually read. See
7770 libjpeg.doc from the JPEG lib distribution. */
7772 static void
7773 our_init_source (cinfo)
7774 j_decompress_ptr cinfo;
7779 /* Fill input buffer method for JPEG data source manager. Called
7780 whenever more data is needed. We read the whole image in one step,
7781 so this only adds a fake end of input marker at the end. */
7783 static boolean
7784 our_fill_input_buffer (cinfo)
7785 j_decompress_ptr cinfo;
7787 /* Insert a fake EOI marker. */
7788 struct jpeg_source_mgr *src = cinfo->src;
7789 static JOCTET buffer[2];
7791 buffer[0] = (JOCTET) 0xFF;
7792 buffer[1] = (JOCTET) JPEG_EOI;
7794 src->next_input_byte = buffer;
7795 src->bytes_in_buffer = 2;
7796 return TRUE;
7800 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7801 is the JPEG data source manager. */
7803 static void
7804 our_skip_input_data (cinfo, num_bytes)
7805 j_decompress_ptr cinfo;
7806 long num_bytes;
7808 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7810 if (src)
7812 if (num_bytes > src->bytes_in_buffer)
7813 ERREXIT (cinfo, JERR_INPUT_EOF);
7815 src->bytes_in_buffer -= num_bytes;
7816 src->next_input_byte += num_bytes;
7821 /* Method to terminate data source. Called by
7822 jpeg_finish_decompress() after all data has been processed. */
7824 static void
7825 our_term_source (cinfo)
7826 j_decompress_ptr cinfo;
7831 /* Set up the JPEG lib for reading an image from DATA which contains
7832 LEN bytes. CINFO is the decompression info structure created for
7833 reading the image. */
7835 static void
7836 jpeg_memory_src (cinfo, data, len)
7837 j_decompress_ptr cinfo;
7838 JOCTET *data;
7839 unsigned int len;
7841 struct jpeg_source_mgr *src;
7843 if (cinfo->src == NULL)
7845 /* First time for this JPEG object? */
7846 cinfo->src = (struct jpeg_source_mgr *)
7847 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7848 sizeof (struct jpeg_source_mgr));
7849 src = (struct jpeg_source_mgr *) cinfo->src;
7850 src->next_input_byte = data;
7853 src = (struct jpeg_source_mgr *) cinfo->src;
7854 src->init_source = our_init_source;
7855 src->fill_input_buffer = our_fill_input_buffer;
7856 src->skip_input_data = our_skip_input_data;
7857 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
7858 src->term_source = our_term_source;
7859 src->bytes_in_buffer = len;
7860 src->next_input_byte = data;
7864 /* Load image IMG for use on frame F. Patterned after example.c
7865 from the JPEG lib. */
7867 static int
7868 jpeg_load (f, img)
7869 struct frame *f;
7870 struct image *img;
7872 struct jpeg_decompress_struct cinfo;
7873 struct my_jpeg_error_mgr mgr;
7874 Lisp_Object file, specified_file;
7875 Lisp_Object specified_data;
7876 FILE *fp = NULL;
7877 JSAMPARRAY buffer;
7878 int row_stride, x, y;
7879 XImage *ximg = NULL;
7880 int rc;
7881 unsigned long *colors;
7882 int width, height;
7883 struct gcpro gcpro1;
7885 /* Open the JPEG file. */
7886 specified_file = image_spec_value (img->spec, QCfile, NULL);
7887 specified_data = image_spec_value (img->spec, QCdata, NULL);
7888 file = Qnil;
7889 GCPRO1 (file);
7891 if (NILP (specified_data))
7893 file = x_find_image_file (specified_file);
7894 if (!STRINGP (file))
7896 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7897 UNGCPRO;
7898 return 0;
7901 fp = fopen (SDATA (file), "r");
7902 if (fp == NULL)
7904 image_error ("Cannot open `%s'", file, Qnil);
7905 UNGCPRO;
7906 return 0;
7910 /* Customize libjpeg's error handling to call my_error_exit when an
7911 error is detected. This function will perform a longjmp. */
7912 mgr.pub.error_exit = my_error_exit;
7913 cinfo.err = jpeg_std_error (&mgr.pub);
7915 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7917 if (rc == 1)
7919 /* Called from my_error_exit. Display a JPEG error. */
7920 char buffer[JMSG_LENGTH_MAX];
7921 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7922 image_error ("Error reading JPEG image `%s': %s", img->spec,
7923 build_string (buffer));
7926 /* Close the input file and destroy the JPEG object. */
7927 if (fp)
7928 fclose (fp);
7929 jpeg_destroy_decompress (&cinfo);
7931 BLOCK_INPUT;
7933 /* If we already have an XImage, free that. */
7934 x_destroy_x_image (ximg);
7936 /* Free pixmap and colors. */
7937 x_clear_image (f, img);
7939 UNBLOCK_INPUT;
7940 UNGCPRO;
7941 return 0;
7944 /* Create the JPEG decompression object. Let it read from fp.
7945 Read the JPEG image header. */
7946 jpeg_create_decompress (&cinfo);
7948 if (NILP (specified_data))
7949 jpeg_stdio_src (&cinfo, fp);
7950 else
7951 jpeg_memory_src (&cinfo, SDATA (specified_data),
7952 SBYTES (specified_data));
7954 jpeg_read_header (&cinfo, TRUE);
7956 /* Customize decompression so that color quantization will be used.
7957 Start decompression. */
7958 cinfo.quantize_colors = TRUE;
7959 jpeg_start_decompress (&cinfo);
7960 width = img->width = cinfo.output_width;
7961 height = img->height = cinfo.output_height;
7963 BLOCK_INPUT;
7965 /* Create X image and pixmap. */
7966 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7967 &img->pixmap))
7969 UNBLOCK_INPUT;
7970 longjmp (mgr.setjmp_buffer, 2);
7973 /* Allocate colors. When color quantization is used,
7974 cinfo.actual_number_of_colors has been set with the number of
7975 colors generated, and cinfo.colormap is a two-dimensional array
7976 of color indices in the range 0..cinfo.actual_number_of_colors.
7977 No more than 255 colors will be generated. */
7979 int i, ir, ig, ib;
7981 if (cinfo.out_color_components > 2)
7982 ir = 0, ig = 1, ib = 2;
7983 else if (cinfo.out_color_components > 1)
7984 ir = 0, ig = 1, ib = 0;
7985 else
7986 ir = 0, ig = 0, ib = 0;
7988 /* Use the color table mechanism because it handles colors that
7989 cannot be allocated nicely. Such colors will be replaced with
7990 a default color, and we don't have to care about which colors
7991 can be freed safely, and which can't. */
7992 init_color_table ();
7993 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7994 * sizeof *colors);
7996 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7998 /* Multiply RGB values with 255 because X expects RGB values
7999 in the range 0..0xffff. */
8000 int r = cinfo.colormap[ir][i] << 8;
8001 int g = cinfo.colormap[ig][i] << 8;
8002 int b = cinfo.colormap[ib][i] << 8;
8003 colors[i] = lookup_rgb_color (f, r, g, b);
8006 /* Remember those colors actually allocated. */
8007 img->colors = colors_in_color_table (&img->ncolors);
8008 free_color_table ();
8011 /* Read pixels. */
8012 row_stride = width * cinfo.output_components;
8013 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8014 row_stride, 1);
8015 for (y = 0; y < height; ++y)
8017 jpeg_read_scanlines (&cinfo, buffer, 1);
8018 for (x = 0; x < cinfo.output_width; ++x)
8019 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8022 /* Clean up. */
8023 jpeg_finish_decompress (&cinfo);
8024 jpeg_destroy_decompress (&cinfo);
8025 if (fp)
8026 fclose (fp);
8028 /* Put the image into the pixmap. */
8029 x_put_x_image (f, ximg, img->pixmap, width, height);
8030 x_destroy_x_image (ximg);
8031 UNBLOCK_INPUT;
8032 UNGCPRO;
8033 return 1;
8036 #endif /* HAVE_JPEG */
8040 /***********************************************************************
8041 TIFF
8042 ***********************************************************************/
8044 #if HAVE_TIFF
8046 #include <tiffio.h>
8048 static int tiff_image_p P_ ((Lisp_Object object));
8049 static int tiff_load P_ ((struct frame *f, struct image *img));
8051 /* The symbol `tiff' identifying images of this type. */
8053 Lisp_Object Qtiff;
8055 /* Indices of image specification fields in tiff_format, below. */
8057 enum tiff_keyword_index
8059 TIFF_TYPE,
8060 TIFF_DATA,
8061 TIFF_FILE,
8062 TIFF_ASCENT,
8063 TIFF_MARGIN,
8064 TIFF_RELIEF,
8065 TIFF_ALGORITHM,
8066 TIFF_HEURISTIC_MASK,
8067 TIFF_LAST
8070 /* Vector of image_keyword structures describing the format
8071 of valid user-defined image specifications. */
8073 static struct image_keyword tiff_format[TIFF_LAST] =
8075 {":type", IMAGE_SYMBOL_VALUE, 1},
8076 {":data", IMAGE_STRING_VALUE, 0},
8077 {":file", IMAGE_STRING_VALUE, 0},
8078 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8079 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8080 {":relief", IMAGE_INTEGER_VALUE, 0},
8081 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8082 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8085 /* Structure describing the image type `tiff'. */
8087 static struct image_type tiff_type =
8089 &Qtiff,
8090 tiff_image_p,
8091 tiff_load,
8092 x_clear_image,
8093 NULL
8097 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8099 static int
8100 tiff_image_p (object)
8101 Lisp_Object object;
8103 struct image_keyword fmt[TIFF_LAST];
8104 bcopy (tiff_format, fmt, sizeof fmt);
8106 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
8107 || (fmt[TIFF_ASCENT].count
8108 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
8109 return 0;
8111 /* Must specify either the :data or :file keyword. */
8112 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8116 /* Reading from a memory buffer for TIFF images Based on the PNG
8117 memory source, but we have to provide a lot of extra functions.
8118 Blah.
8120 We really only need to implement read and seek, but I am not
8121 convinced that the TIFF library is smart enough not to destroy
8122 itself if we only hand it the function pointers we need to
8123 override. */
8125 typedef struct
8127 unsigned char *bytes;
8128 size_t len;
8129 int index;
8131 tiff_memory_source;
8133 static size_t
8134 tiff_read_from_memory (data, buf, size)
8135 thandle_t data;
8136 tdata_t buf;
8137 tsize_t size;
8139 tiff_memory_source *src = (tiff_memory_source *) data;
8141 if (size > src->len - src->index)
8142 return (size_t) -1;
8143 bcopy (src->bytes + src->index, buf, size);
8144 src->index += size;
8145 return size;
8148 static size_t
8149 tiff_write_from_memory (data, buf, size)
8150 thandle_t data;
8151 tdata_t buf;
8152 tsize_t size;
8154 return (size_t) -1;
8157 static toff_t
8158 tiff_seek_in_memory (data, off, whence)
8159 thandle_t data;
8160 toff_t off;
8161 int whence;
8163 tiff_memory_source *src = (tiff_memory_source *) data;
8164 int idx;
8166 switch (whence)
8168 case SEEK_SET: /* Go from beginning of source. */
8169 idx = off;
8170 break;
8172 case SEEK_END: /* Go from end of source. */
8173 idx = src->len + off;
8174 break;
8176 case SEEK_CUR: /* Go from current position. */
8177 idx = src->index + off;
8178 break;
8180 default: /* Invalid `whence'. */
8181 return -1;
8184 if (idx > src->len || idx < 0)
8185 return -1;
8187 src->index = idx;
8188 return src->index;
8191 static int
8192 tiff_close_memory (data)
8193 thandle_t data;
8195 /* NOOP */
8196 return 0;
8199 static int
8200 tiff_mmap_memory (data, pbase, psize)
8201 thandle_t data;
8202 tdata_t *pbase;
8203 toff_t *psize;
8205 /* It is already _IN_ memory. */
8206 return 0;
8209 static void
8210 tiff_unmap_memory (data, base, size)
8211 thandle_t data;
8212 tdata_t base;
8213 toff_t size;
8215 /* We don't need to do this. */
8218 static toff_t
8219 tiff_size_of_memory (data)
8220 thandle_t data;
8222 return ((tiff_memory_source *) data)->len;
8225 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8226 successful. */
8228 static int
8229 tiff_load (f, img)
8230 struct frame *f;
8231 struct image *img;
8233 Lisp_Object file, specified_file;
8234 Lisp_Object specified_data;
8235 TIFF *tiff;
8236 int width, height, x, y;
8237 uint32 *buf;
8238 int rc;
8239 XImage *ximg;
8240 struct gcpro gcpro1;
8241 tiff_memory_source memsrc;
8243 specified_file = image_spec_value (img->spec, QCfile, NULL);
8244 specified_data = image_spec_value (img->spec, QCdata, NULL);
8245 file = Qnil;
8246 GCPRO1 (file);
8248 if (NILP (specified_data))
8250 /* Read from a file */
8251 file = x_find_image_file (specified_file);
8252 if (!STRINGP (file))
8254 image_error ("Cannot find image file `%s'", file, Qnil);
8255 UNGCPRO;
8256 return 0;
8259 /* Try to open the image file. */
8260 tiff = TIFFOpen (SDATA (file), "r");
8261 if (tiff == NULL)
8263 image_error ("Cannot open `%s'", file, Qnil);
8264 UNGCPRO;
8265 return 0;
8268 else
8270 /* Memory source! */
8271 memsrc.bytes = SDATA (specified_data);
8272 memsrc.len = SBYTES (specified_data);
8273 memsrc.index = 0;
8275 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8276 (TIFFReadWriteProc) tiff_read_from_memory,
8277 (TIFFReadWriteProc) tiff_write_from_memory,
8278 tiff_seek_in_memory,
8279 tiff_close_memory,
8280 tiff_size_of_memory,
8281 tiff_mmap_memory,
8282 tiff_unmap_memory);
8284 if (!tiff)
8286 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8287 UNGCPRO;
8288 return 0;
8292 /* Get width and height of the image, and allocate a raster buffer
8293 of width x height 32-bit values. */
8294 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8295 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8296 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8298 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8299 TIFFClose (tiff);
8300 if (!rc)
8302 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8303 xfree (buf);
8304 UNGCPRO;
8305 return 0;
8308 BLOCK_INPUT;
8310 /* Create the X image and pixmap. */
8311 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8313 UNBLOCK_INPUT;
8314 xfree (buf);
8315 UNGCPRO;
8316 return 0;
8319 /* Initialize the color table. */
8320 init_color_table ();
8322 /* Process the pixel raster. Origin is in the lower-left corner. */
8323 for (y = 0; y < height; ++y)
8325 uint32 *row = buf + y * width;
8327 for (x = 0; x < width; ++x)
8329 uint32 abgr = row[x];
8330 int r = TIFFGetR (abgr) << 8;
8331 int g = TIFFGetG (abgr) << 8;
8332 int b = TIFFGetB (abgr) << 8;
8333 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8337 /* Remember the colors allocated for the image. Free the color table. */
8338 img->colors = colors_in_color_table (&img->ncolors);
8339 free_color_table ();
8341 /* Put the image into the pixmap, then free the X image and its buffer. */
8342 x_put_x_image (f, ximg, img->pixmap, width, height);
8343 x_destroy_x_image (ximg);
8344 xfree (buf);
8345 UNBLOCK_INPUT;
8347 img->width = width;
8348 img->height = height;
8350 UNGCPRO;
8351 return 1;
8354 #endif /* HAVE_TIFF != 0 */
8358 /***********************************************************************
8360 ***********************************************************************/
8362 #if HAVE_GIF
8364 #include <gif_lib.h>
8366 static int gif_image_p P_ ((Lisp_Object object));
8367 static int gif_load P_ ((struct frame *f, struct image *img));
8369 /* The symbol `gif' identifying images of this type. */
8371 Lisp_Object Qgif;
8373 /* Indices of image specification fields in gif_format, below. */
8375 enum gif_keyword_index
8377 GIF_TYPE,
8378 GIF_DATA,
8379 GIF_FILE,
8380 GIF_ASCENT,
8381 GIF_MARGIN,
8382 GIF_RELIEF,
8383 GIF_ALGORITHM,
8384 GIF_HEURISTIC_MASK,
8385 GIF_IMAGE,
8386 GIF_LAST
8389 /* Vector of image_keyword structures describing the format
8390 of valid user-defined image specifications. */
8392 static struct image_keyword gif_format[GIF_LAST] =
8394 {":type", IMAGE_SYMBOL_VALUE, 1},
8395 {":data", IMAGE_STRING_VALUE, 0},
8396 {":file", IMAGE_STRING_VALUE, 0},
8397 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8398 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8399 {":relief", IMAGE_INTEGER_VALUE, 0},
8400 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8401 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8402 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
8405 /* Structure describing the image type `gif'. */
8407 static struct image_type gif_type =
8409 &Qgif,
8410 gif_image_p,
8411 gif_load,
8412 x_clear_image,
8413 NULL
8416 /* Return non-zero if OBJECT is a valid GIF image specification. */
8418 static int
8419 gif_image_p (object)
8420 Lisp_Object object;
8422 struct image_keyword fmt[GIF_LAST];
8423 bcopy (gif_format, fmt, sizeof fmt);
8425 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
8426 || (fmt[GIF_ASCENT].count
8427 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
8428 return 0;
8430 /* Must specify either the :data or :file keyword. */
8431 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8434 /* Reading a GIF image from memory
8435 Based on the PNG memory stuff to a certain extent. */
8437 typedef struct
8439 unsigned char *bytes;
8440 size_t len;
8441 int index;
8443 gif_memory_source;
8445 /* Make the current memory source available to gif_read_from_memory.
8446 It's done this way because not all versions of libungif support
8447 a UserData field in the GifFileType structure. */
8448 static gif_memory_source *current_gif_memory_src;
8450 static int
8451 gif_read_from_memory (file, buf, len)
8452 GifFileType *file;
8453 GifByteType *buf;
8454 int len;
8456 gif_memory_source *src = current_gif_memory_src;
8458 if (len > src->len - src->index)
8459 return -1;
8461 bcopy (src->bytes + src->index, buf, len);
8462 src->index += len;
8463 return len;
8467 /* Load GIF image IMG for use on frame F. Value is non-zero if
8468 successful. */
8470 static int
8471 gif_load (f, img)
8472 struct frame *f;
8473 struct image *img;
8475 Lisp_Object file, specified_file;
8476 Lisp_Object specified_data;
8477 int rc, width, height, x, y, i;
8478 XImage *ximg;
8479 ColorMapObject *gif_color_map;
8480 unsigned long pixel_colors[256];
8481 GifFileType *gif;
8482 struct gcpro gcpro1;
8483 Lisp_Object image;
8484 int ino, image_left, image_top, image_width, image_height;
8485 gif_memory_source memsrc;
8486 unsigned char *raster;
8488 specified_file = image_spec_value (img->spec, QCfile, NULL);
8489 specified_data = image_spec_value (img->spec, QCdata, NULL);
8490 file = Qnil;
8491 GCPRO1 (file);
8493 if (NILP (specified_data))
8495 file = x_find_image_file (specified_file);
8496 if (!STRINGP (file))
8498 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8499 UNGCPRO;
8500 return 0;
8503 /* Open the GIF file. */
8504 gif = DGifOpenFileName (SDATA (file));
8505 if (gif == NULL)
8507 image_error ("Cannot open `%s'", file, Qnil);
8508 UNGCPRO;
8509 return 0;
8512 else
8514 /* Read from memory! */
8515 current_gif_memory_src = &memsrc;
8516 memsrc.bytes = SDATA (specified_data);
8517 memsrc.len = SBYTES (specified_data);
8518 memsrc.index = 0;
8520 gif = DGifOpen(&memsrc, gif_read_from_memory);
8521 if (!gif)
8523 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8524 UNGCPRO;
8525 return 0;
8529 /* Read entire contents. */
8530 rc = DGifSlurp (gif);
8531 if (rc == GIF_ERROR)
8533 image_error ("Error reading `%s'", img->spec, Qnil);
8534 DGifCloseFile (gif);
8535 UNGCPRO;
8536 return 0;
8539 image = image_spec_value (img->spec, QCindex, NULL);
8540 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8541 if (ino >= gif->ImageCount)
8543 image_error ("Invalid image number `%s' in image `%s'",
8544 image, img->spec);
8545 DGifCloseFile (gif);
8546 UNGCPRO;
8547 return 0;
8550 width = img->width = gif->SWidth;
8551 height = img->height = gif->SHeight;
8553 BLOCK_INPUT;
8555 /* Create the X image and pixmap. */
8556 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8558 UNBLOCK_INPUT;
8559 DGifCloseFile (gif);
8560 UNGCPRO;
8561 return 0;
8564 /* Allocate colors. */
8565 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8566 if (!gif_color_map)
8567 gif_color_map = gif->SColorMap;
8568 init_color_table ();
8569 bzero (pixel_colors, sizeof pixel_colors);
8571 for (i = 0; i < gif_color_map->ColorCount; ++i)
8573 int r = gif_color_map->Colors[i].Red << 8;
8574 int g = gif_color_map->Colors[i].Green << 8;
8575 int b = gif_color_map->Colors[i].Blue << 8;
8576 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8579 img->colors = colors_in_color_table (&img->ncolors);
8580 free_color_table ();
8582 /* Clear the part of the screen image that are not covered by
8583 the image from the GIF file. Full animated GIF support
8584 requires more than can be done here (see the gif89 spec,
8585 disposal methods). Let's simply assume that the part
8586 not covered by a sub-image is in the frame's background color. */
8587 image_top = gif->SavedImages[ino].ImageDesc.Top;
8588 image_left = gif->SavedImages[ino].ImageDesc.Left;
8589 image_width = gif->SavedImages[ino].ImageDesc.Width;
8590 image_height = gif->SavedImages[ino].ImageDesc.Height;
8592 for (y = 0; y < image_top; ++y)
8593 for (x = 0; x < width; ++x)
8594 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8596 for (y = image_top + image_height; y < height; ++y)
8597 for (x = 0; x < width; ++x)
8598 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8600 for (y = image_top; y < image_top + image_height; ++y)
8602 for (x = 0; x < image_left; ++x)
8603 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8604 for (x = image_left + image_width; x < width; ++x)
8605 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8608 /* Read the GIF image into the X image. We use a local variable
8609 `raster' here because RasterBits below is a char *, and invites
8610 problems with bytes >= 0x80. */
8611 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8613 if (gif->SavedImages[ino].ImageDesc.Interlace)
8615 static int interlace_start[] = {0, 4, 2, 1};
8616 static int interlace_increment[] = {8, 8, 4, 2};
8617 int pass, inc;
8618 int row = interlace_start[0];
8620 pass = 0;
8622 for (y = 0; y < image_height; y++)
8624 if (row >= image_height)
8626 row = interlace_start[++pass];
8627 while (row >= image_height)
8628 row = interlace_start[++pass];
8631 for (x = 0; x < image_width; x++)
8633 int i = raster[(y * image_width) + x];
8634 XPutPixel (ximg, x + image_left, row + image_top,
8635 pixel_colors[i]);
8638 row += interlace_increment[pass];
8641 else
8643 for (y = 0; y < image_height; ++y)
8644 for (x = 0; x < image_width; ++x)
8646 int i = raster[y* image_width + x];
8647 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8651 DGifCloseFile (gif);
8653 /* Put the image into the pixmap, then free the X image and its buffer. */
8654 x_put_x_image (f, ximg, img->pixmap, width, height);
8655 x_destroy_x_image (ximg);
8656 UNBLOCK_INPUT;
8658 UNGCPRO;
8659 return 1;
8662 #endif /* HAVE_GIF != 0 */
8666 /***********************************************************************
8667 Ghostscript
8668 ***********************************************************************/
8670 #ifdef HAVE_GHOSTSCRIPT
8671 static int gs_image_p P_ ((Lisp_Object object));
8672 static int gs_load P_ ((struct frame *f, struct image *img));
8673 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8675 /* The symbol `postscript' identifying images of this type. */
8677 Lisp_Object Qpostscript;
8679 /* Keyword symbols. */
8681 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8683 /* Indices of image specification fields in gs_format, below. */
8685 enum gs_keyword_index
8687 GS_TYPE,
8688 GS_PT_WIDTH,
8689 GS_PT_HEIGHT,
8690 GS_FILE,
8691 GS_LOADER,
8692 GS_BOUNDING_BOX,
8693 GS_ASCENT,
8694 GS_MARGIN,
8695 GS_RELIEF,
8696 GS_ALGORITHM,
8697 GS_HEURISTIC_MASK,
8698 GS_LAST
8701 /* Vector of image_keyword structures describing the format
8702 of valid user-defined image specifications. */
8704 static struct image_keyword gs_format[GS_LAST] =
8706 {":type", IMAGE_SYMBOL_VALUE, 1},
8707 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8708 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8709 {":file", IMAGE_STRING_VALUE, 1},
8710 {":loader", IMAGE_FUNCTION_VALUE, 0},
8711 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8712 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8713 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8714 {":relief", IMAGE_INTEGER_VALUE, 0},
8715 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8716 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8719 /* Structure describing the image type `ghostscript'. */
8721 static struct image_type gs_type =
8723 &Qpostscript,
8724 gs_image_p,
8725 gs_load,
8726 gs_clear_image,
8727 NULL
8731 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8733 static void
8734 gs_clear_image (f, img)
8735 struct frame *f;
8736 struct image *img;
8738 /* IMG->data.ptr_val may contain a recorded colormap. */
8739 xfree (img->data.ptr_val);
8740 x_clear_image (f, img);
8744 /* Return non-zero if OBJECT is a valid Ghostscript image
8745 specification. */
8747 static int
8748 gs_image_p (object)
8749 Lisp_Object object;
8751 struct image_keyword fmt[GS_LAST];
8752 Lisp_Object tem;
8753 int i;
8755 bcopy (gs_format, fmt, sizeof fmt);
8757 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
8758 || (fmt[GS_ASCENT].count
8759 && XFASTINT (fmt[GS_ASCENT].value) > 100))
8760 return 0;
8762 /* Bounding box must be a list or vector containing 4 integers. */
8763 tem = fmt[GS_BOUNDING_BOX].value;
8764 if (CONSP (tem))
8766 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8767 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8768 return 0;
8769 if (!NILP (tem))
8770 return 0;
8772 else if (VECTORP (tem))
8774 if (XVECTOR (tem)->size != 4)
8775 return 0;
8776 for (i = 0; i < 4; ++i)
8777 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8778 return 0;
8780 else
8781 return 0;
8783 return 1;
8787 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8788 if successful. */
8790 static int
8791 gs_load (f, img)
8792 struct frame *f;
8793 struct image *img;
8795 char buffer[100];
8796 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8797 struct gcpro gcpro1, gcpro2;
8798 Lisp_Object frame;
8799 double in_width, in_height;
8800 Lisp_Object pixel_colors = Qnil;
8802 /* Compute pixel size of pixmap needed from the given size in the
8803 image specification. Sizes in the specification are in pt. 1 pt
8804 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8805 info. */
8806 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8807 in_width = XFASTINT (pt_width) / 72.0;
8808 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
8809 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8810 in_height = XFASTINT (pt_height) / 72.0;
8811 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
8813 /* Create the pixmap. */
8814 BLOCK_INPUT;
8815 xassert (img->pixmap == 0);
8816 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
8817 img->width, img->height,
8818 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8819 UNBLOCK_INPUT;
8821 if (!img->pixmap)
8823 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8824 return 0;
8827 /* Call the loader to fill the pixmap. It returns a process object
8828 if successful. We do not record_unwind_protect here because
8829 other places in redisplay like calling window scroll functions
8830 don't either. Let the Lisp loader use `unwind-protect' instead. */
8831 GCPRO2 (window_and_pixmap_id, pixel_colors);
8833 sprintf (buffer, "%lu %lu",
8834 (unsigned long) FRAME_W32_WINDOW (f),
8835 (unsigned long) img->pixmap);
8836 window_and_pixmap_id = build_string (buffer);
8838 sprintf (buffer, "%lu %lu",
8839 FRAME_FOREGROUND_PIXEL (f),
8840 FRAME_BACKGROUND_PIXEL (f));
8841 pixel_colors = build_string (buffer);
8843 XSETFRAME (frame, f);
8844 loader = image_spec_value (img->spec, QCloader, NULL);
8845 if (NILP (loader))
8846 loader = intern ("gs-load-image");
8848 img->data.lisp_val = call6 (loader, frame, img->spec,
8849 make_number (img->width),
8850 make_number (img->height),
8851 window_and_pixmap_id,
8852 pixel_colors);
8853 UNGCPRO;
8854 return PROCESSP (img->data.lisp_val);
8858 /* Kill the Ghostscript process that was started to fill PIXMAP on
8859 frame F. Called from XTread_socket when receiving an event
8860 telling Emacs that Ghostscript has finished drawing. */
8862 void
8863 x_kill_gs_process (pixmap, f)
8864 Pixmap pixmap;
8865 struct frame *f;
8867 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8868 int class, i;
8869 struct image *img;
8871 /* Find the image containing PIXMAP. */
8872 for (i = 0; i < c->used; ++i)
8873 if (c->images[i]->pixmap == pixmap)
8874 break;
8876 /* Kill the GS process. We should have found PIXMAP in the image
8877 cache and its image should contain a process object. */
8878 xassert (i < c->used);
8879 img = c->images[i];
8880 xassert (PROCESSP (img->data.lisp_val));
8881 Fkill_process (img->data.lisp_val, Qnil);
8882 img->data.lisp_val = Qnil;
8884 /* On displays with a mutable colormap, figure out the colors
8885 allocated for the image by looking at the pixels of an XImage for
8886 img->pixmap. */
8887 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
8888 if (class != StaticColor && class != StaticGray && class != TrueColor)
8890 XImage *ximg;
8892 BLOCK_INPUT;
8894 /* Try to get an XImage for img->pixmep. */
8895 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
8896 0, 0, img->width, img->height, ~0, ZPixmap);
8897 if (ximg)
8899 int x, y;
8901 /* Initialize the color table. */
8902 init_color_table ();
8904 /* For each pixel of the image, look its color up in the
8905 color table. After having done so, the color table will
8906 contain an entry for each color used by the image. */
8907 for (y = 0; y < img->height; ++y)
8908 for (x = 0; x < img->width; ++x)
8910 unsigned long pixel = XGetPixel (ximg, x, y);
8911 lookup_pixel_color (f, pixel);
8914 /* Record colors in the image. Free color table and XImage. */
8915 img->colors = colors_in_color_table (&img->ncolors);
8916 free_color_table ();
8917 XDestroyImage (ximg);
8919 #if 0 /* This doesn't seem to be the case. If we free the colors
8920 here, we get a BadAccess later in x_clear_image when
8921 freeing the colors. */
8922 /* We have allocated colors once, but Ghostscript has also
8923 allocated colors on behalf of us. So, to get the
8924 reference counts right, free them once. */
8925 if (img->ncolors)
8927 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
8928 XFreeColors (FRAME_W32_DISPLAY (f), cmap,
8929 img->colors, img->ncolors, 0);
8931 #endif
8933 else
8934 image_error ("Cannot get X image of `%s'; colors will not be freed",
8935 img->spec, Qnil);
8937 UNBLOCK_INPUT;
8941 #endif /* HAVE_GHOSTSCRIPT */
8944 /***********************************************************************
8945 Window properties
8946 ***********************************************************************/
8948 DEFUN ("x-change-window-property", Fx_change_window_property,
8949 Sx_change_window_property, 2, 3, 0,
8950 doc: /* Change window property PROP to VALUE on the X window of FRAME.
8951 PROP and VALUE must be strings. FRAME nil or omitted means use the
8952 selected frame. Value is VALUE. */)
8953 (prop, value, frame)
8954 Lisp_Object frame, prop, value;
8956 #if 0 /* MAC_TODO : port window properties to Mac */
8957 struct frame *f = check_x_frame (frame);
8958 Atom prop_atom;
8960 CHECK_STRING (prop);
8961 CHECK_STRING (value);
8963 BLOCK_INPUT;
8964 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
8965 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
8966 prop_atom, XA_STRING, 8, PropModeReplace,
8967 SDATA (value), SCHARS (value));
8969 /* Make sure the property is set when we return. */
8970 XFlush (FRAME_W32_DISPLAY (f));
8971 UNBLOCK_INPUT;
8973 #endif /* MAC_TODO */
8975 return value;
8979 DEFUN ("x-delete-window-property", Fx_delete_window_property,
8980 Sx_delete_window_property, 1, 2, 0,
8981 doc: /* Remove window property PROP from X window of FRAME.
8982 FRAME nil or omitted means use the selected frame. Value is PROP. */)
8983 (prop, frame)
8984 Lisp_Object prop, frame;
8986 #if 0 /* MAC_TODO : port window properties to Mac */
8988 struct frame *f = check_x_frame (frame);
8989 Atom prop_atom;
8991 CHECK_STRING (prop);
8992 BLOCK_INPUT;
8993 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
8994 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
8996 /* Make sure the property is removed when we return. */
8997 XFlush (FRAME_W32_DISPLAY (f));
8998 UNBLOCK_INPUT;
8999 #endif /* MAC_TODO */
9001 return prop;
9005 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9006 1, 2, 0,
9007 doc: /* Value is the value of window property PROP on FRAME.
9008 If FRAME is nil or omitted, use the selected frame. Value is nil
9009 if FRAME hasn't a property with name PROP or if PROP has no string
9010 value. */)
9011 (prop, frame)
9012 Lisp_Object prop, frame;
9014 #if 0 /* MAC_TODO : port window properties to Mac */
9016 struct frame *f = check_x_frame (frame);
9017 Atom prop_atom;
9018 int rc;
9019 Lisp_Object prop_value = Qnil;
9020 char *tmp_data = NULL;
9021 Atom actual_type;
9022 int actual_format;
9023 unsigned long actual_size, bytes_remaining;
9025 CHECK_STRING (prop);
9026 BLOCK_INPUT;
9027 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
9028 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9029 prop_atom, 0, 0, False, XA_STRING,
9030 &actual_type, &actual_format, &actual_size,
9031 &bytes_remaining, (unsigned char **) &tmp_data);
9032 if (rc == Success)
9034 int size = bytes_remaining;
9036 XFree (tmp_data);
9037 tmp_data = NULL;
9039 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9040 prop_atom, 0, bytes_remaining,
9041 False, XA_STRING,
9042 &actual_type, &actual_format,
9043 &actual_size, &bytes_remaining,
9044 (unsigned char **) &tmp_data);
9045 if (rc == Success)
9046 prop_value = make_string (tmp_data, size);
9048 XFree (tmp_data);
9051 UNBLOCK_INPUT;
9053 return prop_value;
9055 #endif /* MAC_TODO */
9056 return Qnil;
9061 /***********************************************************************
9062 Hourglass cursor
9063 ***********************************************************************/
9065 /* If non-null, an asynchronous timer that, when it expires, displays
9066 an hourglass cursor on all frames. */
9068 static struct atimer *hourglass_atimer;
9070 /* Non-zero means an hourglass cursor is currently shown. */
9072 static int hourglass_shown_p;
9074 /* Number of seconds to wait before displaying an hourglass cursor. */
9076 static Lisp_Object Vhourglass_delay;
9078 /* Default number of seconds to wait before displaying an hourglass
9079 cursor. */
9081 #define DEFAULT_HOURGLASS_DELAY 1
9083 /* Function prototypes. */
9085 static void show_hourglass P_ ((struct atimer *));
9086 static void hide_hourglass P_ ((void));
9089 /* Cancel a currently active hourglass timer, and start a new one. */
9091 void
9092 start_hourglass ()
9094 #if 0 /* MAC_TODO: cursor shape changes. */
9095 EMACS_TIME delay;
9096 int secs, usecs = 0;
9098 cancel_hourglass ();
9100 if (INTEGERP (Vhourglass_delay)
9101 && XINT (Vhourglass_delay) > 0)
9102 secs = XFASTINT (Vhourglass_delay);
9103 else if (FLOATP (Vhourglass_delay)
9104 && XFLOAT_DATA (Vhourglass_delay) > 0)
9106 Lisp_Object tem;
9107 tem = Ftruncate (Vhourglass_delay, Qnil);
9108 secs = XFASTINT (tem);
9109 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
9111 else
9112 secs = DEFAULT_HOURGLASS_DELAY;
9114 EMACS_SET_SECS_USECS (delay, secs, usecs);
9115 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
9116 show_hourglass, NULL);
9117 #endif /* MAC_TODO */
9121 /* Cancel the hourglass cursor timer if active, hide an hourglass
9122 cursor if shown. */
9124 void
9125 cancel_hourglass ()
9127 if (hourglass_atimer)
9129 cancel_atimer (hourglass_atimer);
9130 hourglass_atimer = NULL;
9133 if (hourglass_shown_p)
9134 hide_hourglass ();
9138 /* Timer function of hourglass_atimer. TIMER is equal to
9139 hourglass_atimer.
9141 Display an hourglass cursor on all frames by mapping the frames'
9142 hourglass_window. Set the hourglass_p flag in the frames'
9143 output_data.x structure to indicate that an hourglass cursor is
9144 shown on the frames. */
9146 static void
9147 show_hourglass (timer)
9148 struct atimer *timer;
9150 #if 0 /* MAC_TODO: cursor shape changes. */
9151 /* The timer implementation will cancel this timer automatically
9152 after this function has run. Set hourglass_atimer to null
9153 so that we know the timer doesn't have to be canceled. */
9154 hourglass_atimer = NULL;
9156 if (!hourglass_shown_p)
9158 Lisp_Object rest, frame;
9160 BLOCK_INPUT;
9162 FOR_EACH_FRAME (rest, frame)
9163 if (FRAME_W32_P (XFRAME (frame)))
9165 struct frame *f = XFRAME (frame);
9167 f->output_data.w32->hourglass_p = 1;
9169 if (!f->output_data.w32->hourglass_window)
9171 unsigned long mask = CWCursor;
9172 XSetWindowAttributes attrs;
9174 attrs.cursor = f->output_data.w32->hourglass_cursor;
9176 f->output_data.w32->hourglass_window
9177 = XCreateWindow (FRAME_X_DISPLAY (f),
9178 FRAME_OUTER_WINDOW (f),
9179 0, 0, 32000, 32000, 0, 0,
9180 InputOnly,
9181 CopyFromParent,
9182 mask, &attrs);
9185 XMapRaised (FRAME_X_DISPLAY (f),
9186 f->output_data.w32->hourglass_window);
9187 XFlush (FRAME_X_DISPLAY (f));
9190 hourglass_shown_p = 1;
9191 UNBLOCK_INPUT;
9193 #endif /* MAC_TODO */
9197 /* Hide the hourglass cursor on all frames, if it is currently shown. */
9199 static void
9200 hide_hourglass ()
9202 #if 0 /* MAC_TODO: cursor shape changes. */
9203 if (hourglass_shown_p)
9205 Lisp_Object rest, frame;
9207 BLOCK_INPUT;
9208 FOR_EACH_FRAME (rest, frame)
9210 struct frame *f = XFRAME (frame);
9212 if (FRAME_W32_P (f)
9213 /* Watch out for newly created frames. */
9214 && f->output_data.x->hourglass_window)
9216 XUnmapWindow (FRAME_X_DISPLAY (f),
9217 f->output_data.x->hourglass_window);
9218 /* Sync here because XTread_socket looks at the
9219 hourglass_p flag that is reset to zero below. */
9220 XSync (FRAME_X_DISPLAY (f), False);
9221 f->output_data.x->hourglass_p = 0;
9225 hourglass_shown_p = 0;
9226 UNBLOCK_INPUT;
9228 #endif /* MAC_TODO */
9233 /***********************************************************************
9234 Tool tips
9235 ***********************************************************************/
9237 static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
9238 Lisp_Object));
9240 /* The frame of a currently visible tooltip, or null. */
9242 Lisp_Object tip_frame;
9244 /* If non-nil, a timer started that hides the last tooltip when it
9245 fires. */
9247 Lisp_Object tip_timer;
9248 Window tip_window;
9250 /* If non-nil, a vector of 3 elements containing the last args
9251 with which x-show-tip was called. See there. */
9253 Lisp_Object last_show_tip_args;
9255 /* Create a frame for a tooltip on the display described by DPYINFO.
9256 PARMS is a list of frame parameters. Value is the frame. */
9258 static Lisp_Object
9259 x_create_tip_frame (dpyinfo, parms)
9260 struct mac_display_info *dpyinfo;
9261 Lisp_Object parms;
9263 #if 0 /* MAC_TODO : Mac version */
9264 struct frame *f;
9265 Lisp_Object frame, tem;
9266 Lisp_Object name;
9267 long window_prompting = 0;
9268 int width, height;
9269 int count = SPECPDL_INDEX ();
9270 struct gcpro gcpro1, gcpro2, gcpro3;
9271 struct kboard *kb;
9273 check_x ();
9275 /* Use this general default value to start with until we know if
9276 this frame has a specified name. */
9277 Vx_resource_name = Vinvocation_name;
9279 #ifdef MULTI_KBOARD
9280 kb = dpyinfo->kboard;
9281 #else
9282 kb = &the_only_kboard;
9283 #endif
9285 /* Get the name of the frame to use for resource lookup. */
9286 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
9287 if (!STRINGP (name)
9288 && !EQ (name, Qunbound)
9289 && !NILP (name))
9290 error ("Invalid frame name--not a string or nil");
9291 Vx_resource_name = name;
9293 frame = Qnil;
9294 GCPRO3 (parms, name, frame);
9295 tip_frame = f = make_frame (1);
9296 XSETFRAME (frame, f);
9297 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9299 f->output_method = output_w32;
9300 f->output_data.w32 =
9301 (struct w32_output *) xmalloc (sizeof (struct w32_output));
9302 bzero (f->output_data.w32, sizeof (struct w32_output));
9303 #if 0
9304 f->output_data.w32->icon_bitmap = -1;
9305 #endif
9306 f->output_data.w32->fontset = -1;
9307 f->icon_name = Qnil;
9309 #ifdef MULTI_KBOARD
9310 FRAME_KBOARD (f) = kb;
9311 #endif
9312 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9313 f->output_data.w32->explicit_parent = 0;
9315 /* Set the name; the functions to which we pass f expect the name to
9316 be set. */
9317 if (EQ (name, Qunbound) || NILP (name))
9319 f->name = build_string (dpyinfo->x_id_name);
9320 f->explicit_name = 0;
9322 else
9324 f->name = name;
9325 f->explicit_name = 1;
9326 /* use the frame's title when getting resources for this frame. */
9327 specbind (Qx_resource_name, name);
9330 /* Extract the window parameters from the supplied values
9331 that are needed to determine window geometry. */
9333 Lisp_Object font;
9335 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
9337 BLOCK_INPUT;
9338 /* First, try whatever font the caller has specified. */
9339 if (STRINGP (font))
9341 tem = Fquery_fontset (font, Qnil);
9342 if (STRINGP (tem))
9343 font = x_new_fontset (f, SDATA (tem));
9344 else
9345 font = x_new_font (f, SDATA (font));
9348 /* Try out a font which we hope has bold and italic variations. */
9349 if (!STRINGP (font))
9350 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9351 if (!STRINGP (font))
9352 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9353 if (! STRINGP (font))
9354 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9355 if (! STRINGP (font))
9356 /* This was formerly the first thing tried, but it finds too many fonts
9357 and takes too long. */
9358 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9359 /* If those didn't work, look for something which will at least work. */
9360 if (! STRINGP (font))
9361 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9362 UNBLOCK_INPUT;
9363 if (! STRINGP (font))
9364 font = build_string ("fixed");
9366 x_default_parameter (f, parms, Qfont, font,
9367 "font", "Font", RES_TYPE_STRING);
9370 x_default_parameter (f, parms, Qborder_width, make_number (2),
9371 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9373 /* This defaults to 2 in order to match xterm. We recognize either
9374 internalBorderWidth or internalBorder (which is what xterm calls
9375 it). */
9376 if (NILP (Fassq (Qinternal_border_width, parms)))
9378 Lisp_Object value;
9380 value = w32_get_arg (parms, Qinternal_border_width,
9381 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9382 if (! EQ (value, Qunbound))
9383 parms = Fcons (Fcons (Qinternal_border_width, value),
9384 parms);
9387 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9388 "internalBorderWidth", "internalBorderWidth",
9389 RES_TYPE_NUMBER);
9391 /* Also do the stuff which must be set before the window exists. */
9392 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9393 "foreground", "Foreground", RES_TYPE_STRING);
9394 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9395 "background", "Background", RES_TYPE_STRING);
9396 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9397 "pointerColor", "Foreground", RES_TYPE_STRING);
9398 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9399 "cursorColor", "Foreground", RES_TYPE_STRING);
9400 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9401 "borderColor", "BorderColor", RES_TYPE_STRING);
9403 /* Init faces before x_default_parameter is called for scroll-bar
9404 parameters because that function calls x_set_scroll_bar_width,
9405 which calls change_frame_size, which calls Fset_window_buffer,
9406 which runs hooks, which call Fvertical_motion. At the end, we
9407 end up in init_iterator with a null face cache, which should not
9408 happen. */
9409 init_frame_faces (f);
9411 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9412 window_prompting = x_figure_window_size (f, parms);
9414 if (window_prompting & XNegative)
9416 if (window_prompting & YNegative)
9417 f->output_data.w32->win_gravity = SouthEastGravity;
9418 else
9419 f->output_data.w32->win_gravity = NorthEastGravity;
9421 else
9423 if (window_prompting & YNegative)
9424 f->output_data.w32->win_gravity = SouthWestGravity;
9425 else
9426 f->output_data.w32->win_gravity = NorthWestGravity;
9429 f->output_data.w32->size_hint_flags = window_prompting;
9431 XSetWindowAttributes attrs;
9432 unsigned long mask;
9434 BLOCK_INPUT;
9435 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9436 /* Window managers looks at the override-redirect flag to
9437 determine whether or net to give windows a decoration (Xlib
9438 3.2.8). */
9439 attrs.override_redirect = True;
9440 attrs.save_under = True;
9441 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9442 /* Arrange for getting MapNotify and UnmapNotify events. */
9443 attrs.event_mask = StructureNotifyMask;
9444 tip_window
9445 = FRAME_W32_WINDOW (f)
9446 = XCreateWindow (FRAME_W32_DISPLAY (f),
9447 FRAME_W32_DISPLAY_INFO (f)->root_window,
9448 /* x, y, width, height */
9449 0, 0, 1, 1,
9450 /* Border. */
9452 CopyFromParent, InputOutput, CopyFromParent,
9453 mask, &attrs);
9454 UNBLOCK_INPUT;
9457 x_make_gc (f);
9459 x_default_parameter (f, parms, Qauto_raise, Qnil,
9460 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9461 x_default_parameter (f, parms, Qauto_lower, Qnil,
9462 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9463 x_default_parameter (f, parms, Qcursor_type, Qbox,
9464 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9466 /* Dimensions, especially f->height, must be done via change_frame_size.
9467 Change will not be effected unless different from the current
9468 f->height. */
9469 width = f->width;
9470 height = f->height;
9471 f->height = 0;
9472 SET_FRAME_WIDTH (f, 0);
9473 change_frame_size (f, height, width, 1, 0, 0);
9475 /* Add `tooltip' frame parameter's default value. */
9476 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
9477 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
9478 Qnil));
9480 f->no_split = 1;
9482 UNGCPRO;
9484 /* It is now ok to make the frame official even if we get an error
9485 below. And the frame needs to be on Vframe_list or making it
9486 visible won't work. */
9487 Vframe_list = Fcons (frame, Vframe_list);
9489 /* Now that the frame is official, it counts as a reference to
9490 its display. */
9491 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
9493 return unbind_to (count, frame);
9494 #endif /* MAC_TODO */
9495 return Qnil;
9499 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
9500 doc : /* Show STRING in a "tooltip" window on frame FRAME.
9501 A tooltip window is a small window displaying a string.
9503 FRAME nil or omitted means use the selected frame.
9505 PARMS is an optional list of frame parameters which can be used to
9506 change the tooltip's appearance.
9508 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
9509 means use the default timeout of 5 seconds.
9511 If the list of frame parameters PARAMS contains a `left' parameters,
9512 the tooltip is displayed at that x-position. Otherwise it is
9513 displayed at the mouse position, with offset DX added (default is 5 if
9514 DX isn't specified). Likewise for the y-position; if a `top' frame
9515 parameter is specified, it determines the y-position of the tooltip
9516 window, otherwise it is displayed at the mouse position, with offset
9517 DY added (default is 10). */)
9518 (string, frame, parms, timeout, dx, dy)
9519 Lisp_Object string, frame, parms, timeout, dx, dy;
9521 struct frame *f;
9522 struct window *w;
9523 Window root, child;
9524 Lisp_Object buffer, top, left;
9525 struct buffer *old_buffer;
9526 struct text_pos pos;
9527 int i, width, height;
9528 int root_x, root_y, win_x, win_y;
9529 unsigned pmask;
9530 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9531 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9532 int count = SPECPDL_INDEX ();
9534 specbind (Qinhibit_redisplay, Qt);
9536 GCPRO4 (string, parms, frame, timeout);
9538 CHECK_STRING (string);
9539 f = check_x_frame (frame);
9540 if (NILP (timeout))
9541 timeout = make_number (5);
9542 else
9543 CHECK_NATNUM (timeout);
9545 if (NILP (dx))
9546 dx = make_number (5);
9547 else
9548 CHECK_NUMBER (dx);
9550 if (NILP (dy))
9551 dy = make_number (-10);
9552 else
9553 CHECK_NUMBER (dy);
9555 if (NILP (last_show_tip_args))
9556 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
9558 if (!NILP (tip_frame))
9560 Lisp_Object last_string = AREF (last_show_tip_args, 0);
9561 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
9562 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
9564 if (EQ (frame, last_frame)
9565 && !NILP (Fequal (last_string, string))
9566 && !NILP (Fequal (last_parms, parms)))
9568 struct frame *f = XFRAME (tip_frame);
9570 /* Only DX and DY have changed. */
9571 if (!NILP (tip_timer))
9573 Lisp_Object timer = tip_timer;
9574 tip_timer = Qnil;
9575 call1 (Qcancel_timer, timer);
9578 #if 0 /* MAC_TODO : Mac specifics */
9579 BLOCK_INPUT;
9580 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9581 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9582 root_x, root_y - PIXEL_HEIGHT (f));
9583 UNBLOCK_INPUT;
9584 #endif /* MAC_TODO */
9585 goto start_timer;
9589 /* Hide a previous tip, if any. */
9590 Fx_hide_tip ();
9592 ASET (last_show_tip_args, 0, string);
9593 ASET (last_show_tip_args, 1, frame);
9594 ASET (last_show_tip_args, 2, parms);
9596 /* Add default values to frame parameters. */
9597 if (NILP (Fassq (Qname, parms)))
9598 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9599 if (NILP (Fassq (Qinternal_border_width, parms)))
9600 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9601 if (NILP (Fassq (Qborder_width, parms)))
9602 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9603 if (NILP (Fassq (Qborder_color, parms)))
9604 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9605 if (NILP (Fassq (Qbackground_color, parms)))
9606 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9607 parms);
9609 /* Create a frame for the tooltip, and record it in the global
9610 variable tip_frame. */
9611 frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
9612 f = XFRAME (frame);
9614 /* Set up the frame's root window. Currently we use a size of 80
9615 columns x 40 lines. If someone wants to show a larger tip, he
9616 will loose. I don't think this is a realistic case. */
9617 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9618 w->left = w->top = make_number (0);
9619 w->width = make_number (80);
9620 w->height = make_number (40);
9621 adjust_glyphs (f);
9622 w->pseudo_window_p = 1;
9624 /* Display the tooltip text in a temporary buffer. */
9625 buffer = Fget_buffer_create (build_string (" *tip*"));
9626 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
9627 old_buffer = current_buffer;
9628 set_buffer_internal_1 (XBUFFER (buffer));
9629 Ferase_buffer ();
9630 Finsert (1, &string);
9631 clear_glyph_matrix (w->desired_matrix);
9632 clear_glyph_matrix (w->current_matrix);
9633 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9634 try_window (FRAME_ROOT_WINDOW (f), pos);
9636 /* Compute width and height of the tooltip. */
9637 width = height = 0;
9638 for (i = 0; i < w->desired_matrix->nrows; ++i)
9640 struct glyph_row *row = &w->desired_matrix->rows[i];
9641 struct glyph *last;
9642 int row_width;
9644 /* Stop at the first empty row at the end. */
9645 if (!row->enabled_p || !row->displays_text_p)
9646 break;
9648 /* Let the row go over the full width of the frame. */
9649 row->full_width_p = 1;
9651 /* There's a glyph at the end of rows that is use to place
9652 the cursor there. Don't include the width of this glyph. */
9653 if (row->used[TEXT_AREA])
9655 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
9656 row_width = row->pixel_width - last->pixel_width;
9658 else
9659 row_width = row->pixel_width;
9661 height += row->height;
9662 width = max (width, row_width);
9665 /* Add the frame's internal border to the width and height the X
9666 window should have. */
9667 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9668 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9670 /* Move the tooltip window where the mouse pointer is. Resize and
9671 show it. */
9672 #if 0 /* TODO : Mac specifics */
9673 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9675 BLOCK_INPUT;
9676 XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
9677 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
9678 XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9679 root_x + 5, root_y - height - 5, width, height);
9680 XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
9681 UNBLOCK_INPUT;
9682 #endif /* MAC_TODO */
9684 /* Draw into the window. */
9685 w->must_be_updated_p = 1;
9686 update_single_window (w, 1);
9688 /* Restore original current buffer. */
9689 set_buffer_internal_1 (old_buffer);
9690 windows_or_buffers_changed = old_windows_or_buffers_changed;
9692 start_timer:
9693 /* Let the tip disappear after timeout seconds. */
9694 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
9695 intern ("x-hide-tip"));
9697 UNGCPRO;
9698 return unbind_to (count, Qnil);
9702 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9703 doc: /* Hide the current tooltip window, if there is any.
9704 Value is t is tooltip was open, nil otherwise. */)
9707 int count;
9708 Lisp_Object deleted, frame, timer;
9709 struct gcpro gcpro1, gcpro2;
9711 /* Return quickly if nothing to do. */
9712 if (NILP (tip_timer) && NILP (tip_frame))
9713 return Qnil;
9715 frame = tip_frame;
9716 timer = tip_timer;
9717 GCPRO2 (frame, timer);
9718 tip_frame = tip_timer = deleted = Qnil;
9720 count = SPECPDL_INDEX ();
9721 specbind (Qinhibit_redisplay, Qt);
9722 specbind (Qinhibit_quit, Qt);
9724 if (!NILP (timer))
9725 call1 (Qcancel_timer, timer);
9727 if (FRAMEP (frame))
9729 Fdelete_frame (frame, Qnil);
9730 deleted = Qt;
9733 UNGCPRO;
9734 return unbind_to (count, deleted);
9739 /***********************************************************************
9740 File selection dialog
9741 ***********************************************************************/
9743 #if 0 /* MAC_TODO: can standard file dialog */
9744 extern Lisp_Object Qfile_name_history;
9746 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
9747 doc: /* Read file name, prompting with PROMPT in directory DIR.
9748 Use a file selection dialog.
9749 Select DEFAULT-FILENAME in the dialog's file selection box, if
9750 specified. Don't let the user enter a file name in the file
9751 selection dialog's entry field, if MUSTMATCH is non-nil. */)
9752 (prompt, dir, default_filename, mustmatch)
9753 Lisp_Object prompt, dir, default_filename, mustmatch;
9755 struct frame *f = SELECTED_FRAME ();
9756 Lisp_Object file = Qnil;
9757 int count = SPECPDL_INDEX ();
9758 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
9759 char filename[MAX_PATH + 1];
9760 char init_dir[MAX_PATH + 1];
9761 int use_dialog_p = 1;
9763 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
9764 CHECK_STRING (prompt);
9765 CHECK_STRING (dir);
9767 /* Create the dialog with PROMPT as title, using DIR as initial
9768 directory and using "*" as pattern. */
9769 dir = Fexpand_file_name (dir, Qnil);
9770 strncpy (init_dir, SDATA (dir), MAX_PATH);
9771 init_dir[MAX_PATH] = '\0';
9772 unixtodos_filename (init_dir);
9774 if (STRINGP (default_filename))
9776 char *file_name_only;
9777 char *full_path_name = SDATA (default_filename);
9779 unixtodos_filename (full_path_name);
9781 file_name_only = strrchr (full_path_name, '\\');
9782 if (!file_name_only)
9783 file_name_only = full_path_name;
9784 else
9786 file_name_only++;
9788 /* If default_file_name is a directory, don't use the open
9789 file dialog, as it does not support selecting
9790 directories. */
9791 if (!(*file_name_only))
9792 use_dialog_p = 0;
9795 strncpy (filename, file_name_only, MAX_PATH);
9796 filename[MAX_PATH] = '\0';
9798 else
9799 filename[0] = '\0';
9801 if (use_dialog_p)
9803 OPENFILENAME file_details;
9804 char *filename_file;
9806 /* Prevent redisplay. */
9807 specbind (Qinhibit_redisplay, Qt);
9808 BLOCK_INPUT;
9810 bzero (&file_details, sizeof (file_details));
9811 file_details.lStructSize = sizeof (file_details);
9812 file_details.hwndOwner = FRAME_W32_WINDOW (f);
9813 file_details.lpstrFile = filename;
9814 file_details.nMaxFile = sizeof (filename);
9815 file_details.lpstrInitialDir = init_dir;
9816 file_details.lpstrTitle = SDATA (prompt);
9817 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
9819 if (!NILP (mustmatch))
9820 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
9822 if (GetOpenFileName (&file_details))
9824 dostounix_filename (filename);
9825 file = build_string (filename);
9827 else
9828 file = Qnil;
9830 UNBLOCK_INPUT;
9831 file = unbind_to (count, file);
9833 /* Open File dialog will not allow folders to be selected, so resort
9834 to minibuffer completing reads for directories. */
9835 else
9836 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
9837 dir, mustmatch, dir, Qfile_name_history,
9838 default_filename, Qnil);
9840 UNGCPRO;
9842 /* Make "Cancel" equivalent to C-g. */
9843 if (NILP (file))
9844 Fsignal (Qquit, Qnil);
9846 return unbind_to (count, file);
9848 #endif /* MAC_TODO */
9852 /***********************************************************************
9853 Tests
9854 ***********************************************************************/
9856 #if GLYPH_DEBUG
9858 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9859 doc: /* Value is non-nil if SPEC is a valid image specification. */)
9860 (spec)
9861 Lisp_Object spec;
9863 return valid_image_p (spec) ? Qt : Qnil;
9867 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9868 (spec)
9869 Lisp_Object spec;
9871 int id = -1;
9873 if (valid_image_p (spec))
9874 id = lookup_image (SELECTED_FRAME (), spec);
9876 debug_print (spec);
9877 return make_number (id);
9880 #endif /* GLYPH_DEBUG != 0 */
9884 void
9885 syms_of_macfns ()
9887 /* Certainly running on Mac. */
9888 mac_in_use = 1;
9890 /* The section below is built by the lisp expression at the top of the file,
9891 just above where these variables are declared. */
9892 /*&&& init symbols here &&&*/
9893 Qauto_raise = intern ("auto-raise");
9894 staticpro (&Qauto_raise);
9895 Qauto_lower = intern ("auto-lower");
9896 staticpro (&Qauto_lower);
9897 Qborder_color = intern ("border-color");
9898 staticpro (&Qborder_color);
9899 Qborder_width = intern ("border-width");
9900 staticpro (&Qborder_width);
9901 Qcursor_color = intern ("cursor-color");
9902 staticpro (&Qcursor_color);
9903 Qcursor_type = intern ("cursor-type");
9904 staticpro (&Qcursor_type);
9905 Qgeometry = intern ("geometry");
9906 staticpro (&Qgeometry);
9907 Qicon_left = intern ("icon-left");
9908 staticpro (&Qicon_left);
9909 Qicon_top = intern ("icon-top");
9910 staticpro (&Qicon_top);
9911 Qicon_type = intern ("icon-type");
9912 staticpro (&Qicon_type);
9913 Qicon_name = intern ("icon-name");
9914 staticpro (&Qicon_name);
9915 Qinternal_border_width = intern ("internal-border-width");
9916 staticpro (&Qinternal_border_width);
9917 Qleft = intern ("left");
9918 staticpro (&Qleft);
9919 Qright = intern ("right");
9920 staticpro (&Qright);
9921 Qmouse_color = intern ("mouse-color");
9922 staticpro (&Qmouse_color);
9923 Qnone = intern ("none");
9924 staticpro (&Qnone);
9925 Qparent_id = intern ("parent-id");
9926 staticpro (&Qparent_id);
9927 Qscroll_bar_width = intern ("scroll-bar-width");
9928 staticpro (&Qscroll_bar_width);
9929 Qsuppress_icon = intern ("suppress-icon");
9930 staticpro (&Qsuppress_icon);
9931 Qundefined_color = intern ("undefined-color");
9932 staticpro (&Qundefined_color);
9933 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
9934 staticpro (&Qvertical_scroll_bars);
9935 Qvisibility = intern ("visibility");
9936 staticpro (&Qvisibility);
9937 Qwindow_id = intern ("window-id");
9938 staticpro (&Qwindow_id);
9939 Qx_frame_parameter = intern ("x-frame-parameter");
9940 staticpro (&Qx_frame_parameter);
9941 Qx_resource_name = intern ("x-resource-name");
9942 staticpro (&Qx_resource_name);
9943 Quser_position = intern ("user-position");
9944 staticpro (&Quser_position);
9945 Quser_size = intern ("user-size");
9946 staticpro (&Quser_size);
9947 Qscreen_gamma = intern ("screen-gamma");
9948 staticpro (&Qscreen_gamma);
9949 Qline_spacing = intern ("line-spacing");
9950 staticpro (&Qline_spacing);
9951 Qcenter = intern ("center");
9952 staticpro (&Qcenter);
9953 /* This is the end of symbol initialization. */
9955 Qhyper = intern ("hyper");
9956 staticpro (&Qhyper);
9957 Qsuper = intern ("super");
9958 staticpro (&Qsuper);
9959 Qmeta = intern ("meta");
9960 staticpro (&Qmeta);
9961 Qalt = intern ("alt");
9962 staticpro (&Qalt);
9963 Qctrl = intern ("ctrl");
9964 staticpro (&Qctrl);
9965 Qcontrol = intern ("control");
9966 staticpro (&Qcontrol);
9967 Qshift = intern ("shift");
9968 staticpro (&Qshift);
9970 /* Text property `display' should be nonsticky by default. */
9971 Vtext_property_default_nonsticky
9972 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
9975 Qlaplace = intern ("laplace");
9976 staticpro (&Qlaplace);
9978 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
9979 staticpro (&Qface_set_after_frame_default);
9981 Fput (Qundefined_color, Qerror_conditions,
9982 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
9983 Fput (Qundefined_color, Qerror_message,
9984 build_string ("Undefined color"));
9986 init_x_parm_symbols ();
9988 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
9989 doc: /* List of directories to search for bitmap files for w32. */);
9990 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
9992 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
9993 doc: /* The shape of the pointer when over text.
9994 Changing the value does not affect existing frames
9995 unless you set the mouse color. */);
9996 Vx_pointer_shape = Qnil;
9998 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
9999 doc: /* The name Emacs uses to look up resources; for internal use only.
10000 `x-get-resource' uses this as the first component of the instance name
10001 when requesting resource values.
10002 Emacs initially sets `x-resource-name' to the name under which Emacs
10003 was invoked, or to the value specified with the `-name' or `-rn'
10004 switches, if present. */);
10005 Vx_resource_name = Qnil;
10007 Vx_nontext_pointer_shape = Qnil;
10009 Vx_mode_pointer_shape = Qnil;
10011 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
10012 doc: /* The shape of the pointer when Emacs is hourglass.
10013 This variable takes effect when you create a new frame
10014 or when you set the mouse color. */);
10015 Vx_hourglass_pointer_shape = Qnil;
10017 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
10018 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10019 display_hourglass_p = 1;
10021 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
10022 doc: /* *Seconds to wait before displaying an hourglass pointer.
10023 Value must be an integer or float. */);
10024 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
10026 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10027 &Vx_sensitive_text_pointer_shape,
10028 doc: /* The shape of the pointer when over mouse-sensitive text.
10029 This variable takes effect when you create a new frame
10030 or when you set the mouse color. */);
10031 Vx_sensitive_text_pointer_shape = Qnil;
10033 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10034 doc: /* A string indicating the foreground color of the cursor box. */);
10035 Vx_cursor_fore_pixel = Qnil;
10037 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10038 doc: /* Non-nil if no window manager is in use.
10039 Emacs doesn't try to figure this out; this is always nil
10040 unless you set it to something else. */);
10041 /* We don't have any way to find this out, so set it to nil
10042 and maybe the user would like to set it to t. */
10043 Vx_no_window_manager = Qnil;
10045 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10046 &Vx_pixel_size_width_font_regexp,
10047 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10049 Since Emacs gets width of a font matching with this regexp from
10050 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10051 such a font. This is especially effective for such large fonts as
10052 Chinese, Japanese, and Korean. */);
10053 Vx_pixel_size_width_font_regexp = Qnil;
10055 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10056 doc: /* Time after which cached images are removed from the cache.
10057 When an image has not been displayed this many seconds, remove it
10058 from the image cache. Value must be an integer or nil with nil
10059 meaning don't clear the cache. */);
10060 Vimage_cache_eviction_delay = make_number (30 * 60);
10062 #if 0 /* MAC_TODO: implement get X resource */
10063 defsubr (&Sx_get_resource);
10064 #endif
10065 defsubr (&Sx_change_window_property);
10066 defsubr (&Sx_delete_window_property);
10067 defsubr (&Sx_window_property);
10068 defsubr (&Sxw_display_color_p);
10069 defsubr (&Sx_display_grayscale_p);
10070 defsubr (&Sxw_color_defined_p);
10071 defsubr (&Sxw_color_values);
10072 defsubr (&Sx_server_max_request_size);
10073 defsubr (&Sx_server_vendor);
10074 defsubr (&Sx_server_version);
10075 defsubr (&Sx_display_pixel_width);
10076 defsubr (&Sx_display_pixel_height);
10077 defsubr (&Sx_display_mm_width);
10078 defsubr (&Sx_display_mm_height);
10079 defsubr (&Sx_display_screens);
10080 defsubr (&Sx_display_planes);
10081 defsubr (&Sx_display_color_cells);
10082 defsubr (&Sx_display_visual_class);
10083 defsubr (&Sx_display_backing_store);
10084 defsubr (&Sx_display_save_under);
10085 #if 0 /* MAC_TODO: implement XParseGeometry */
10086 defsubr (&Sx_parse_geometry);
10087 #endif
10088 defsubr (&Sx_create_frame);
10089 #if 0 /* MAC_TODO: implement network support */
10090 defsubr (&Sx_open_connection);
10091 defsubr (&Sx_close_connection);
10092 #endif
10093 defsubr (&Sx_display_list);
10094 defsubr (&Sx_synchronize);
10096 /* Setting callback functions for fontset handler. */
10097 get_font_info_func = x_get_font_info;
10099 #if 0 /* This function pointer doesn't seem to be used anywhere.
10100 And the pointer assigned has the wrong type, anyway. */
10101 list_fonts_func = x_list_fonts;
10102 #endif
10104 load_font_func = x_load_font;
10105 find_ccl_program_func = x_find_ccl_program;
10106 query_font_func = x_query_font;
10108 set_frame_fontset_func = x_set_font;
10109 check_window_system_func = check_mac;
10111 #if 0 /* MAC_TODO: Image support for Mac Images. */
10112 Qxbm = intern ("xbm");
10113 staticpro (&Qxbm);
10114 QCtype = intern (":type");
10115 staticpro (&QCtype);
10116 QCconversion = intern (":conversion");
10117 staticpro (&QCconversion);
10118 QCheuristic_mask = intern (":heuristic-mask");
10119 staticpro (&QCheuristic_mask);
10120 QCcolor_symbols = intern (":color-symbols");
10121 staticpro (&QCcolor_symbols);
10122 QCascent = intern (":ascent");
10123 staticpro (&QCascent);
10124 QCmargin = intern (":margin");
10125 staticpro (&QCmargin);
10126 QCrelief = intern (":relief");
10127 staticpro (&QCrelief);
10128 Qpostscript = intern ("postscript");
10129 staticpro (&Qpostscript);
10130 QCloader = intern (":loader");
10131 staticpro (&QCloader);
10132 QCbounding_box = intern (":bounding-box");
10133 staticpro (&QCbounding_box);
10134 QCpt_width = intern (":pt-width");
10135 staticpro (&QCpt_width);
10136 QCpt_height = intern (":pt-height");
10137 staticpro (&QCpt_height);
10138 QCindex = intern (":index");
10139 staticpro (&QCindex);
10140 Qpbm = intern ("pbm");
10141 staticpro (&Qpbm);
10143 #if HAVE_XPM
10144 Qxpm = intern ("xpm");
10145 staticpro (&Qxpm);
10146 #endif
10148 #if HAVE_JPEG
10149 Qjpeg = intern ("jpeg");
10150 staticpro (&Qjpeg);
10151 #endif
10153 #if HAVE_TIFF
10154 Qtiff = intern ("tiff");
10155 staticpro (&Qtiff);
10156 #endif
10158 #if HAVE_GIF
10159 Qgif = intern ("gif");
10160 staticpro (&Qgif);
10161 #endif
10163 #if HAVE_PNG
10164 Qpng = intern ("png");
10165 staticpro (&Qpng);
10166 #endif
10168 defsubr (&Sclear_image_cache);
10170 #if GLYPH_DEBUG
10171 defsubr (&Simagep);
10172 defsubr (&Slookup_image);
10173 #endif
10174 #endif /* MAC_TODO */
10176 hourglass_atimer = NULL;
10177 hourglass_shown_p = 0;
10179 defsubr (&Sx_show_tip);
10180 defsubr (&Sx_hide_tip);
10181 staticpro (&tip_timer);
10182 tip_timer = Qnil;
10184 #if 0 /* MAC_TODO */
10185 defsubr (&Sx_file_dialog);
10186 #endif
10190 void
10191 init_xfns ()
10193 image_types = NULL;
10194 Vimage_types = Qnil;
10196 define_image_type (&xbm_type);
10197 #if 0 /* NTEMACS_TODO : Image support for W32 */
10198 define_image_type (&gs_type);
10199 define_image_type (&pbm_type);
10201 #if HAVE_XPM
10202 define_image_type (&xpm_type);
10203 #endif
10205 #if HAVE_JPEG
10206 define_image_type (&jpeg_type);
10207 #endif
10209 #if HAVE_TIFF
10210 define_image_type (&tiff_type);
10211 #endif
10213 #if HAVE_GIF
10214 define_image_type (&gif_type);
10215 #endif
10217 #if HAVE_PNG
10218 define_image_type (&png_type);
10219 #endif
10220 #endif /* NTEMACS_TODO */