Add Support for x86-64.
[emacs.git] / src / macfns.c
blob9571c53a760a100e361cc87019c38e2fd4918e55
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 #include <Carbon/Carbon.h>
76 #undef Z
77 #define Z (current_buffer->text->z)
78 #undef free
79 #define free unexec_free
80 #undef malloc
81 #define malloc unexec_malloc
82 #undef realloc
83 #define realloc unexec_realloc
84 #undef min
85 #define min(a, b) ((a) < (b) ? (a) : (b))
86 #undef max
87 #define max(a, b) ((a) > (b) ? (a) : (b))
88 #else /* not MAC_OSX */
89 #include <Windows.h>
90 #include <Gestalt.h>
91 #include <TextUtils.h>
92 #endif /* not MAC_OSX */
94 /*extern void free_frame_menubar ();
95 extern double atof ();
96 extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
97 extern int quit_char;*/
99 /* A definition of XColor for non-X frames. */
100 #ifndef HAVE_X_WINDOWS
101 typedef struct {
102 unsigned long pixel;
103 unsigned short red, green, blue;
104 char flags;
105 char pad;
106 } XColor;
107 #endif
109 extern char *lispy_function_keys[];
111 /* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
112 it, and including `bitmaps/gray' more than once is a problem when
113 config.h defines `static' as an empty replacement string. */
115 int gray_bitmap_width = gray_width;
116 int gray_bitmap_height = gray_height;
117 unsigned char *gray_bitmap_bits = gray_bits;
119 /* The name we're using in resource queries. */
121 Lisp_Object Vx_resource_name;
123 /* Non-zero means we're allowed to display an hourglass cursor. */
125 int display_hourglass_p;
127 /* The background and shape of the mouse pointer, and shape when not
128 over text or in the modeline. */
130 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
131 Lisp_Object Vx_hourglass_pointer_shape;
133 /* The shape when over mouse-sensitive text. */
135 Lisp_Object Vx_sensitive_text_pointer_shape;
137 /* If non-nil, the pointer shape to indicate that windows can be
138 dragged horizontally. */
140 Lisp_Object Vx_window_horizontal_drag_shape;
142 /* Color of chars displayed in cursor box. */
144 Lisp_Object Vx_cursor_fore_pixel;
146 /* Nonzero if using Windows. */
148 static int mac_in_use;
150 /* Non nil if no window manager is in use. */
152 Lisp_Object Vx_no_window_manager;
154 /* Search path for bitmap files. */
156 Lisp_Object Vx_bitmap_file_path;
158 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
160 Lisp_Object Vx_pixel_size_width_font_regexp;
162 /* Evaluate this expression to rebuild the section of syms_of_macfns
163 that initializes and staticpros the symbols declared below. Note
164 that Emacs 18 has a bug that keeps C-x C-e from being able to
165 evaluate this expression.
167 (progn
168 ;; Accumulate a list of the symbols we want to initialize from the
169 ;; declarations at the top of the file.
170 (goto-char (point-min))
171 (search-forward "/\*&&& symbols declared here &&&*\/\n")
172 (let (symbol-list)
173 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
174 (setq symbol-list
175 (cons (buffer-substring (match-beginning 1) (match-end 1))
176 symbol-list))
177 (forward-line 1))
178 (setq symbol-list (nreverse symbol-list))
179 ;; Delete the section of syms_of_... where we initialize the symbols.
180 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
181 (let ((start (point)))
182 (while (looking-at "^ Q")
183 (forward-line 2))
184 (kill-region start (point)))
185 ;; Write a new symbol initialization section.
186 (while symbol-list
187 (insert (format " %s = intern (\"" (car symbol-list)))
188 (let ((start (point)))
189 (insert (substring (car symbol-list) 1))
190 (subst-char-in-region start (point) ?_ ?-))
191 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
192 (setq symbol-list (cdr symbol-list)))))
196 /*&&& symbols declared here &&&*/
197 Lisp_Object Qauto_raise;
198 Lisp_Object Qauto_lower;
199 Lisp_Object Qbar;
200 Lisp_Object Qborder_color;
201 Lisp_Object Qborder_width;
202 Lisp_Object Qbox;
203 Lisp_Object Qcursor_color;
204 Lisp_Object Qcursor_type;
205 Lisp_Object Qgeometry;
206 Lisp_Object Qicon_left;
207 Lisp_Object Qicon_top;
208 Lisp_Object Qicon_type;
209 Lisp_Object Qicon_name;
210 Lisp_Object Qinternal_border_width;
211 Lisp_Object Qleft;
212 Lisp_Object Qright;
213 Lisp_Object Qmouse_color;
214 Lisp_Object Qnone;
215 Lisp_Object Qparent_id;
216 Lisp_Object Qscroll_bar_width;
217 Lisp_Object Qsuppress_icon;
218 Lisp_Object Qundefined_color;
219 Lisp_Object Qvertical_scroll_bars;
220 Lisp_Object Qvisibility;
221 Lisp_Object Qwindow_id;
222 Lisp_Object Qx_frame_parameter;
223 Lisp_Object Qx_resource_name;
224 Lisp_Object Quser_position;
225 Lisp_Object Quser_size;
226 Lisp_Object Qscreen_gamma;
227 Lisp_Object Qline_spacing;
228 Lisp_Object Qcenter;
229 Lisp_Object Qcancel_timer;
230 Lisp_Object Qhyper;
231 Lisp_Object Qsuper;
232 Lisp_Object Qmeta;
233 Lisp_Object Qalt;
234 Lisp_Object Qctrl;
235 Lisp_Object Qcontrol;
236 Lisp_Object Qshift;
238 extern Lisp_Object Qtop;
239 extern Lisp_Object Qdisplay;
240 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
241 extern Lisp_Object Qtool_bar_lines;
243 /* These are defined in frame.c. */
244 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
245 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
246 extern Lisp_Object Qtool_bar_lines;
248 extern Lisp_Object Vwindow_system_version;
250 Lisp_Object Qface_set_after_frame_default;
252 extern int mac_initialized;
254 /* Functions in macterm.c. */
255 extern void x_set_offset (struct frame *, int, int, int);
256 extern void x_wm_set_icon_position (struct frame *, int, int);
257 extern void x_display_cursor (struct window *, int, int, int, int, int);
258 extern void x_set_window_size (struct frame *, int, int, int);
259 extern void x_make_frame_visible (struct frame *);
260 extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
261 extern struct font_info *x_get_font_info (FRAME_PTR, int);
262 extern struct font_info *x_load_font (struct frame *, char *, int);
263 extern void x_find_ccl_program (struct font_info *);
264 extern struct font_info *x_query_font (struct frame *, char *);
265 extern void mac_initialize ();
267 /* compare two strings ignoring case */
269 static int
270 stricmp (const char *s, const char *t)
272 for ( ; tolower (*s) == tolower (*t); s++, t++)
273 if (*s == '\0')
274 return 0;
275 return tolower (*s) - tolower (*t);
278 /* compare two strings up to n characters, ignoring case */
280 static int
281 strnicmp (const char *s, const char *t, unsigned int n)
283 for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
284 if (*s == '\0')
285 return 0;
286 return n == 0 ? 0 : tolower (*s) - tolower (*t);
290 /* Error if we are not running on Mac OS. */
292 void
293 check_mac ()
295 if (! mac_in_use)
296 error ("Mac OS not in use or not initialized");
299 /* Nonzero if we can use mouse menus.
300 You should not call this unless HAVE_MENUS is defined. */
303 have_menus_p ()
305 return mac_in_use;
308 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
309 and checking validity for Mac. */
311 FRAME_PTR
312 check_x_frame (frame)
313 Lisp_Object frame;
315 FRAME_PTR f;
317 if (NILP (frame))
318 frame = selected_frame;
319 CHECK_LIVE_FRAME (frame);
320 f = XFRAME (frame);
321 if (! FRAME_MAC_P (f))
322 error ("non-mac frame used");
323 return f;
326 /* Let the user specify an display with a frame.
327 nil stands for the selected frame--or, if that is not a mac frame,
328 the first display on the list. */
330 static struct mac_display_info *
331 check_x_display_info (frame)
332 Lisp_Object frame;
334 if (!mac_initialized)
336 mac_initialize ();
337 mac_initialized = 1;
340 if (NILP (frame))
342 struct frame *sf = XFRAME (selected_frame);
344 if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
345 return FRAME_MAC_DISPLAY_INFO (sf);
346 else
347 return &one_mac_display_info;
349 else if (STRINGP (frame))
350 return x_display_info_for_name (frame);
351 else
353 FRAME_PTR f;
355 CHECK_LIVE_FRAME (frame);
356 f = XFRAME (frame);
357 if (! FRAME_MAC_P (f))
358 error ("non-mac frame used");
359 return FRAME_MAC_DISPLAY_INFO (f);
363 /* Return the Emacs frame-object corresponding to an mac window.
364 It could be the frame's main window or an icon window. */
366 /* This function can be called during GC, so use GC_xxx type test macros. */
368 struct frame *
369 x_window_to_frame (dpyinfo, wdesc)
370 struct mac_display_info *dpyinfo;
371 WindowPtr wdesc;
373 Lisp_Object tail, frame;
374 struct frame *f;
376 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
378 frame = XCAR (tail);
379 if (!GC_FRAMEP (frame))
380 continue;
381 f = XFRAME (frame);
382 if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
383 continue;
384 /*if (f->output_data.w32->hourglass_window == wdesc)
385 return f;*/
387 /* MAC_TODO: Check tooltips when supported. */
388 if (FRAME_MAC_WINDOW (f) == wdesc)
389 return f;
391 return 0;
396 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
397 id, which is just an int that this section returns. Bitmaps are
398 reference counted so they can be shared among frames.
400 Bitmap indices are guaranteed to be > 0, so a negative number can
401 be used to indicate no bitmap.
403 If you use x_create_bitmap_from_data, then you must keep track of
404 the bitmaps yourself. That is, creating a bitmap from the same
405 data more than once will not be caught. */
408 /* Functions to access the contents of a bitmap, given an id. */
411 x_bitmap_height (f, id)
412 FRAME_PTR f;
413 int id;
415 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
419 x_bitmap_width (f, id)
420 FRAME_PTR f;
421 int id;
423 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
426 #if 0 /* MAC_TODO : not used anywhere (?) */
428 x_bitmap_pixmap (f, id)
429 FRAME_PTR f;
430 int id;
432 return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
434 #endif
436 /* Allocate a new bitmap record. Returns index of new record. */
438 static int
439 x_allocate_bitmap_record (f)
440 FRAME_PTR f;
442 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
443 int i;
445 if (dpyinfo->bitmaps == NULL)
447 dpyinfo->bitmaps_size = 10;
448 dpyinfo->bitmaps = (struct mac_bitmap_record *)
449 xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
450 dpyinfo->bitmaps_last = 1;
451 return 1;
454 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
455 return ++dpyinfo->bitmaps_last;
457 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
458 if (dpyinfo->bitmaps[i].refcount == 0)
459 return i + 1;
461 dpyinfo->bitmaps_size *= 2;
462 dpyinfo->bitmaps = (struct mac_bitmap_record *)
463 xrealloc (dpyinfo->bitmaps,
464 dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
465 return ++dpyinfo->bitmaps_last;
468 /* Add one reference to the reference count of the bitmap with id
469 ID. */
471 void
472 x_reference_bitmap (f, id)
473 FRAME_PTR f;
474 int id;
476 ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
479 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
480 BITS. */
483 x_create_bitmap_from_data (f, bits, width, height)
484 struct frame *f;
485 char *bits;
486 unsigned int width, height;
488 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
489 int id;
491 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
493 id = x_allocate_bitmap_record (f);
495 if (width % 16 != 0)
496 return -1;
498 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
499 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
500 return -1;
502 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
504 dpyinfo->bitmaps[id - 1].refcount = 1;
505 dpyinfo->bitmaps[id - 1].height = height;
506 dpyinfo->bitmaps[id - 1].width = width;
508 return id;
511 /* Create bitmap from file FILE for frame F. */
514 x_create_bitmap_from_file (f, file)
515 struct frame *f;
516 Lisp_Object file;
518 return -1;
519 #if 0 /* MAC_TODO : bitmap support */
520 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
521 unsigned int width, height;
522 HBITMAP bitmap;
523 int xhot, yhot, result, id;
524 Lisp_Object found;
525 int fd;
526 char *filename;
527 HINSTANCE hinst;
529 /* Look for an existing bitmap with the same name. */
530 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
532 if (dpyinfo->bitmaps[id].refcount
533 && dpyinfo->bitmaps[id].file
534 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
536 ++dpyinfo->bitmaps[id].refcount;
537 return id + 1;
541 /* Search bitmap-file-path for the file, if appropriate. */
542 fd = openp (Vx_bitmap_file_path, file, "", &found, Qnil);
543 if (fd < 0)
544 return -1;
545 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
546 if (fd == 0)
547 return -1;
548 emacs_close (fd);
550 filename = (char *) XSTRING (found)->data;
552 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
554 if (hinst == NULL)
555 return -1;
558 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
559 filename, &width, &height, &bitmap, &xhot, &yhot);
560 if (result != BitmapSuccess)
561 return -1;
563 id = x_allocate_bitmap_record (f);
564 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
565 dpyinfo->bitmaps[id - 1].refcount = 1;
566 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
567 dpyinfo->bitmaps[id - 1].depth = 1;
568 dpyinfo->bitmaps[id - 1].height = height;
569 dpyinfo->bitmaps[id - 1].width = width;
570 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
572 return id;
573 #endif /* MAC_TODO */
576 /* Remove reference to bitmap with id number ID. */
578 void
579 x_destroy_bitmap (f, id)
580 FRAME_PTR f;
581 int id;
583 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
585 if (id > 0)
587 --dpyinfo->bitmaps[id - 1].refcount;
588 if (dpyinfo->bitmaps[id - 1].refcount == 0)
590 BLOCK_INPUT;
591 dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
592 UNBLOCK_INPUT;
597 /* Free all the bitmaps for the display specified by DPYINFO. */
599 static void
600 x_destroy_all_bitmaps (dpyinfo)
601 struct mac_display_info *dpyinfo;
603 int i;
604 for (i = 0; i < dpyinfo->bitmaps_last; i++)
605 if (dpyinfo->bitmaps[i].refcount > 0)
606 xfree (dpyinfo->bitmaps[i].bitmap_data);
607 dpyinfo->bitmaps_last = 0;
610 /* Connect the frame-parameter names for W32 frames
611 to the ways of passing the parameter values to the window system.
613 The name of a parameter, as a Lisp symbol,
614 has an `x-frame-parameter' property which is an integer in Lisp
615 but can be interpreted as an `enum x_frame_parm' in C. */
617 struct x_frame_parm_table
619 char *name;
620 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
623 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
624 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
625 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
626 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
627 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
628 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
629 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
630 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
631 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
632 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
633 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
634 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
635 Lisp_Object));
636 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
637 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
638 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
639 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
640 Lisp_Object));
641 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
642 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
643 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
644 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
645 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
646 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
647 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
648 Lisp_Object));
649 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
650 Lisp_Object));
651 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
652 Lisp_Object,
653 Lisp_Object,
654 char *, char *,
655 int));
656 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
658 static struct x_frame_parm_table x_frame_parms[] =
660 "auto-raise", x_set_autoraise,
661 "auto-lower", x_set_autolower,
662 "background-color", x_set_background_color,
663 "border-color", x_set_border_color,
664 "border-width", x_set_border_width,
665 "cursor-color", x_set_cursor_color,
666 "cursor-type", x_set_cursor_type,
667 "font", x_set_font,
668 "foreground-color", x_set_foreground_color,
669 "icon-name", x_set_icon_name,
670 #if 0 /* MAC_TODO: no icons for Mac */
671 "icon-type", x_set_icon_type,
672 #endif
673 "internal-border-width", x_set_internal_border_width,
674 "menu-bar-lines", x_set_menu_bar_lines,
675 "mouse-color", x_set_mouse_color,
676 "name", x_explicitly_set_name,
677 "scroll-bar-width", x_set_scroll_bar_width,
678 "title", x_set_title,
679 "unsplittable", x_set_unsplittable,
680 "vertical-scroll-bars", x_set_vertical_scroll_bars,
681 "visibility", x_set_visibility,
682 "tool-bar-lines", x_set_tool_bar_lines,
683 #if 0 /* MAC_TODO: cannot set color of scroll bar on the Mac? */
684 "scroll-bar-foreground", x_set_scroll_bar_foreground,
685 "scroll-bar-background", x_set_scroll_bar_background,
686 #endif
687 "screen-gamma", x_set_screen_gamma,
688 "line-spacing", x_set_line_spacing
691 /* Attach the `x-frame-parameter' properties to
692 the Lisp symbol names of parameters relevant to Mac. */
694 void
695 init_x_parm_symbols ()
697 int i;
699 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
700 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
701 make_number (i));
704 /* Change the parameters of frame F as specified by ALIST.
705 If a parameter is not specially recognized, do nothing;
706 otherwise call the `x_set_...' function for that parameter. */
708 void
709 x_set_frame_parameters (f, alist)
710 FRAME_PTR f;
711 Lisp_Object alist;
713 Lisp_Object tail;
715 /* If both of these parameters are present, it's more efficient to
716 set them both at once. So we wait until we've looked at the
717 entire list before we set them. */
718 int width, height;
720 /* Same here. */
721 Lisp_Object left, top;
723 /* Same with these. */
724 Lisp_Object icon_left, icon_top;
726 /* Record in these vectors all the parms specified. */
727 Lisp_Object *parms;
728 Lisp_Object *values;
729 int i, p;
730 int left_no_change = 0, top_no_change = 0;
731 int icon_left_no_change = 0, icon_top_no_change = 0;
733 struct gcpro gcpro1, gcpro2;
735 i = 0;
736 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
737 i++;
739 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
740 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
742 /* Extract parm names and values into those vectors. */
744 i = 0;
745 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
747 Lisp_Object elt;
749 elt = Fcar (tail);
750 parms[i] = Fcar (elt);
751 values[i] = Fcdr (elt);
752 i++;
754 /* TAIL and ALIST are not used again below here. */
755 alist = tail = Qnil;
757 GCPRO2 (*parms, *values);
758 gcpro1.nvars = i;
759 gcpro2.nvars = i;
761 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
762 because their values appear in VALUES and strings are not valid. */
763 top = left = Qunbound;
764 icon_left = icon_top = Qunbound;
766 /* Provide default values for HEIGHT and WIDTH. */
767 if (FRAME_NEW_WIDTH (f))
768 width = FRAME_NEW_WIDTH (f);
769 else
770 width = FRAME_WIDTH (f);
772 if (FRAME_NEW_HEIGHT (f))
773 height = FRAME_NEW_HEIGHT (f);
774 else
775 height = FRAME_HEIGHT (f);
777 /* Process foreground_color and background_color before anything else.
778 They are independent of other properties, but other properties (e.g.,
779 cursor_color) are dependent upon them. */
780 for (p = 0; p < i; p++)
782 Lisp_Object prop, val;
784 prop = parms[p];
785 val = values[p];
786 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
788 register Lisp_Object param_index, old_value;
790 param_index = Fget (prop, Qx_frame_parameter);
791 old_value = get_frame_param (f, prop);
792 store_frame_param (f, prop, val);
793 if (NATNUMP (param_index)
794 && (XFASTINT (param_index)
795 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
796 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
800 /* Now process them in reverse of specified order. */
801 for (i--; i >= 0; i--)
803 Lisp_Object prop, val;
805 prop = parms[i];
806 val = values[i];
808 if (EQ (prop, Qwidth) && NUMBERP (val))
809 width = XFASTINT (val);
810 else if (EQ (prop, Qheight) && NUMBERP (val))
811 height = XFASTINT (val);
812 else if (EQ (prop, Qtop))
813 top = val;
814 else if (EQ (prop, Qleft))
815 left = val;
816 else if (EQ (prop, Qicon_top))
817 icon_top = val;
818 else if (EQ (prop, Qicon_left))
819 icon_left = val;
820 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
821 /* Processed above. */
822 continue;
823 else
825 register Lisp_Object param_index, old_value;
827 param_index = Fget (prop, Qx_frame_parameter);
828 old_value = get_frame_param (f, prop);
829 store_frame_param (f, prop, val);
830 if (NATNUMP (param_index)
831 && (XFASTINT (param_index)
832 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
833 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
837 /* Don't die if just one of these was set. */
838 if (EQ (left, Qunbound))
840 left_no_change = 1;
841 if (f->output_data.mac->left_pos < 0)
842 left = Fcons (Qplus,
843 Fcons (make_number (f->output_data.mac->left_pos),
844 Qnil));
845 else
846 XSETINT (left, f->output_data.mac->left_pos);
848 if (EQ (top, Qunbound))
850 top_no_change = 1;
851 if (f->output_data.mac->top_pos < 0)
852 top = Fcons (Qplus,
853 Fcons (make_number (f->output_data.mac->top_pos), Qnil));
854 else
855 XSETINT (top, f->output_data.mac->top_pos);
858 /* If one of the icon positions was not set, preserve or default it. */
859 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
861 icon_left_no_change = 1;
862 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
863 if (NILP (icon_left))
864 XSETINT (icon_left, 0);
866 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
868 icon_top_no_change = 1;
869 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
870 if (NILP (icon_top))
871 XSETINT (icon_top, 0);
874 /* Don't set these parameters unless they've been explicitly
875 specified. The window might be mapped or resized while we're in
876 this function, and we don't want to override that unless the lisp
877 code has asked for it.
879 Don't set these parameters unless they actually differ from the
880 window's current parameters; the window may not actually exist
881 yet. */
883 Lisp_Object frame;
885 check_frame_size (f, &height, &width);
887 XSETFRAME (frame, f);
889 if (width != FRAME_WIDTH (f)
890 || height != FRAME_HEIGHT (f)
891 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
892 Fset_frame_size (frame, make_number (width), make_number (height));
894 if ((!NILP (left) || !NILP (top))
895 && ! (left_no_change && top_no_change)
896 && ! (NUMBERP (left) && XINT (left) == f->output_data.mac->left_pos
897 && NUMBERP (top) && XINT (top) == f->output_data.mac->top_pos))
899 int leftpos = 0;
900 int toppos = 0;
902 /* Record the signs. */
903 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
904 if (EQ (left, Qminus))
905 f->output_data.mac->size_hint_flags |= XNegative;
906 else if (INTEGERP (left))
908 leftpos = XINT (left);
909 if (leftpos < 0)
910 f->output_data.mac->size_hint_flags |= XNegative;
912 else if (CONSP (left) && EQ (XCAR (left), Qminus)
913 && CONSP (XCDR (left))
914 && INTEGERP (XCAR (XCDR (left))))
916 leftpos = - XINT (XCAR (XCDR (left)));
917 f->output_data.mac->size_hint_flags |= XNegative;
919 else if (CONSP (left) && EQ (XCAR (left), Qplus)
920 && CONSP (XCDR (left))
921 && INTEGERP (XCAR (XCDR (left))))
923 leftpos = XINT (XCAR (XCDR (left)));
926 if (EQ (top, Qminus))
927 f->output_data.mac->size_hint_flags |= YNegative;
928 else if (INTEGERP (top))
930 toppos = XINT (top);
931 if (toppos < 0)
932 f->output_data.mac->size_hint_flags |= YNegative;
934 else if (CONSP (top) && EQ (XCAR (top), Qminus)
935 && CONSP (XCDR (top))
936 && INTEGERP (XCAR (XCDR (top))))
938 toppos = - XINT (XCAR (XCDR (top)));
939 f->output_data.mac->size_hint_flags |= YNegative;
941 else if (CONSP (top) && EQ (XCAR (top), Qplus)
942 && CONSP (XCDR (top))
943 && INTEGERP (XCAR (XCDR (top))))
945 toppos = XINT (XCAR (XCDR (top)));
949 /* Store the numeric value of the position. */
950 f->output_data.mac->top_pos = toppos;
951 f->output_data.mac->left_pos = leftpos;
953 f->output_data.mac->win_gravity = NorthWestGravity;
955 /* Actually set that position, and convert to absolute. */
956 x_set_offset (f, leftpos, toppos, -1);
959 if ((!NILP (icon_left) || !NILP (icon_top))
960 && ! (icon_left_no_change && icon_top_no_change))
961 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
964 UNGCPRO;
967 /* Store the screen positions of frame F into XPTR and YPTR.
968 These are the positions of the containing window manager window,
969 not Emacs's own window. */
971 void
972 x_real_positions (f, xptr, yptr)
973 FRAME_PTR f;
974 int *xptr, *yptr;
976 Point pt;
977 GrafPtr oldport;
979 #ifdef TARGET_API_MAC_CARBON
981 Rect r;
983 GetWindowPortBounds (f->output_data.mac->mWP, &r);
984 SetPt (&pt, r.left, r.top);
986 #else /* not TARGET_API_MAC_CARBON */
987 SetPt (&pt,
988 f->output_data.mac->mWP->portRect.left,
989 f->output_data.mac->mWP->portRect.top);
990 #endif /* not TARGET_API_MAC_CARBON */
991 GetPort (&oldport);
992 LocalToGlobal (&pt);
993 SetPort (oldport);
995 *xptr = pt.h;
996 *yptr = pt.v;
999 /* Insert a description of internally-recorded parameters of frame X
1000 into the parameter alist *ALISTPTR that is to be given to the user.
1001 Only parameters that are specific to Mac and whose values are not
1002 correctly recorded in the frame's param_alist need to be considered
1003 here. */
1005 void
1006 x_report_frame_params (f, alistptr)
1007 struct frame *f;
1008 Lisp_Object *alistptr;
1010 char buf[16];
1011 Lisp_Object tem;
1013 /* Represent negative positions (off the top or left screen edge)
1014 in a way that Fmodify_frame_parameters will understand correctly. */
1015 XSETINT (tem, f->output_data.mac->left_pos);
1016 if (f->output_data.mac->left_pos >= 0)
1017 store_in_alist (alistptr, Qleft, tem);
1018 else
1019 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1021 XSETINT (tem, f->output_data.mac->top_pos);
1022 if (f->output_data.mac->top_pos >= 0)
1023 store_in_alist (alistptr, Qtop, tem);
1024 else
1025 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1027 store_in_alist (alistptr, Qborder_width,
1028 make_number (f->output_data.mac->border_width));
1029 store_in_alist (alistptr, Qinternal_border_width,
1030 make_number (f->output_data.mac->internal_border_width));
1031 sprintf (buf, "%ld", (long) FRAME_MAC_WINDOW (f));
1032 store_in_alist (alistptr, Qwindow_id,
1033 build_string (buf));
1034 store_in_alist (alistptr, Qicon_name, f->icon_name);
1035 FRAME_SAMPLE_VISIBILITY (f);
1036 store_in_alist (alistptr, Qvisibility,
1037 (FRAME_VISIBLE_P (f) ? Qt
1038 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1039 store_in_alist (alistptr, Qdisplay,
1040 XCAR (FRAME_MAC_DISPLAY_INFO (f)->name_list_element));
1043 /* The default colors for the Mac color map */
1044 typedef struct colormap_t
1046 unsigned long color;
1047 char *name;
1048 } colormap_t;
1050 colormap_t mac_color_map[] =
1052 { RGB_TO_ULONG(255, 250, 250), "snow" },
1053 { RGB_TO_ULONG(248, 248, 255), "ghost white" },
1054 { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
1055 { RGB_TO_ULONG(245, 245, 245), "white smoke" },
1056 { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
1057 { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
1058 { RGB_TO_ULONG(255, 250, 240), "floral white" },
1059 { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
1060 { RGB_TO_ULONG(253, 245, 230), "old lace" },
1061 { RGB_TO_ULONG(253, 245, 230), "OldLace" },
1062 { RGB_TO_ULONG(250, 240, 230), "linen" },
1063 { RGB_TO_ULONG(250, 235, 215), "antique white" },
1064 { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
1065 { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
1066 { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
1067 { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
1068 { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
1069 { RGB_TO_ULONG(255, 228, 196), "bisque" },
1070 { RGB_TO_ULONG(255, 218, 185), "peach puff" },
1071 { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
1072 { RGB_TO_ULONG(255, 222, 173), "navajo white" },
1073 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
1074 { RGB_TO_ULONG(255, 228, 181), "moccasin" },
1075 { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
1076 { RGB_TO_ULONG(255, 255, 240), "ivory" },
1077 { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
1078 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
1079 { RGB_TO_ULONG(255, 245, 238), "seashell" },
1080 { RGB_TO_ULONG(240, 255, 240), "honeydew" },
1081 { RGB_TO_ULONG(245, 255, 250), "mint cream" },
1082 { RGB_TO_ULONG(245, 255, 250), "MintCream" },
1083 { RGB_TO_ULONG(240, 255, 255), "azure" },
1084 { RGB_TO_ULONG(240, 248, 255), "alice blue" },
1085 { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
1086 { RGB_TO_ULONG(230, 230, 250), "lavender" },
1087 { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
1088 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
1089 { RGB_TO_ULONG(255, 228, 225), "misty rose" },
1090 { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
1091 { RGB_TO_ULONG(255, 255, 255), "white" },
1092 { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
1093 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
1094 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
1095 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
1096 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
1097 { RGB_TO_ULONG(105, 105, 105), "dim gray" },
1098 { RGB_TO_ULONG(105, 105, 105), "DimGray" },
1099 { RGB_TO_ULONG(105, 105, 105), "dim grey" },
1100 { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
1101 { RGB_TO_ULONG(112, 128, 144), "slate gray" },
1102 { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
1103 { RGB_TO_ULONG(112, 128, 144), "slate grey" },
1104 { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
1105 { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
1106 { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
1107 { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
1108 { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
1109 { RGB_TO_ULONG(190, 190, 190), "gray" },
1110 { RGB_TO_ULONG(190, 190, 190), "grey" },
1111 { RGB_TO_ULONG(211, 211, 211), "light grey" },
1112 { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
1113 { RGB_TO_ULONG(211, 211, 211), "light gray" },
1114 { RGB_TO_ULONG(211, 211, 211), "LightGray" },
1115 { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
1116 { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
1117 { RGB_TO_ULONG(0 , 0 , 128), "navy" },
1118 { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
1119 { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
1120 { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
1121 { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
1122 { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
1123 { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
1124 { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
1125 { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
1126 { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
1127 { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
1128 { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
1129 { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
1130 { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
1131 { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
1132 { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
1133 { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
1134 { RGB_TO_ULONG(0 , 0 , 255), "blue" },
1135 { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
1136 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
1137 { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
1138 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
1139 { RGB_TO_ULONG(135, 206, 235), "sky blue" },
1140 { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
1141 { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
1142 { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
1143 { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
1144 { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
1145 { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
1146 { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
1147 { RGB_TO_ULONG(173, 216, 230), "light blue" },
1148 { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
1149 { RGB_TO_ULONG(176, 224, 230), "powder blue" },
1150 { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
1151 { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
1152 { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
1153 { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
1154 { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
1155 { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
1156 { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
1157 { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
1158 { RGB_TO_ULONG(0 , 255, 255), "cyan" },
1159 { RGB_TO_ULONG(224, 255, 255), "light cyan" },
1160 { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
1161 { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
1162 { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
1163 { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
1164 { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
1165 { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
1166 { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
1167 { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
1168 { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
1169 { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
1170 { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
1171 { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
1172 { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
1173 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
1174 { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
1175 { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
1176 { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
1177 { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
1178 { RGB_TO_ULONG(152, 251, 152), "pale green" },
1179 { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
1180 { RGB_TO_ULONG(0 , 255, 127), "spring green" },
1181 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
1182 { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
1183 { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
1184 { RGB_TO_ULONG(0 , 255, 0 ), "green" },
1185 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
1186 { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
1187 { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
1188 { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
1189 { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
1190 { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
1191 { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
1192 { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
1193 { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
1194 { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
1195 { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
1196 { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
1197 { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
1198 { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
1199 { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
1200 { RGB_TO_ULONG(240, 230, 140), "khaki" },
1201 { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
1202 { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
1203 { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
1204 { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
1205 { RGB_TO_ULONG(255, 255, 224), "light yellow" },
1206 { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
1207 { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
1208 { RGB_TO_ULONG(255, 215, 0 ), "gold" },
1209 { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
1210 { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
1211 { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
1212 { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
1213 { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
1214 { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
1215 { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
1216 { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
1217 { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
1218 { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
1219 { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
1220 { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
1221 { RGB_TO_ULONG(205, 133, 63 ), "peru" },
1222 { RGB_TO_ULONG(222, 184, 135), "burlywood" },
1223 { RGB_TO_ULONG(245, 245, 220), "beige" },
1224 { RGB_TO_ULONG(245, 222, 179), "wheat" },
1225 { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
1226 { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
1227 { RGB_TO_ULONG(210, 180, 140), "tan" },
1228 { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
1229 { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
1230 { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
1231 { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
1232 { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
1233 { RGB_TO_ULONG(250, 128, 114), "salmon" },
1234 { RGB_TO_ULONG(255, 160, 122), "light salmon" },
1235 { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
1236 { RGB_TO_ULONG(255, 165, 0 ), "orange" },
1237 { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
1238 { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
1239 { RGB_TO_ULONG(255, 127, 80 ), "coral" },
1240 { RGB_TO_ULONG(240, 128, 128), "light coral" },
1241 { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
1242 { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
1243 { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
1244 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
1245 { RGB_TO_ULONG(255, 0 , 0 ), "red" },
1246 { RGB_TO_ULONG(255, 105, 180), "hot pink" },
1247 { RGB_TO_ULONG(255, 105, 180), "HotPink" },
1248 { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
1249 { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
1250 { RGB_TO_ULONG(255, 192, 203), "pink" },
1251 { RGB_TO_ULONG(255, 182, 193), "light pink" },
1252 { RGB_TO_ULONG(255, 182, 193), "LightPink" },
1253 { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
1254 { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
1255 { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
1256 { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
1257 { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
1258 { RGB_TO_ULONG(208, 32 , 144), "violet red" },
1259 { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
1260 { RGB_TO_ULONG(255, 0 , 255), "magenta" },
1261 { RGB_TO_ULONG(238, 130, 238), "violet" },
1262 { RGB_TO_ULONG(221, 160, 221), "plum" },
1263 { RGB_TO_ULONG(218, 112, 214), "orchid" },
1264 { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
1265 { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
1266 { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
1267 { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
1268 { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
1269 { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
1270 { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
1271 { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
1272 { RGB_TO_ULONG(160, 32 , 240), "purple" },
1273 { RGB_TO_ULONG(147, 112, 219), "medium purple" },
1274 { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
1275 { RGB_TO_ULONG(216, 191, 216), "thistle" },
1276 { RGB_TO_ULONG(255, 250, 250), "snow1" },
1277 { RGB_TO_ULONG(238, 233, 233), "snow2" },
1278 { RGB_TO_ULONG(205, 201, 201), "snow3" },
1279 { RGB_TO_ULONG(139, 137, 137), "snow4" },
1280 { RGB_TO_ULONG(255, 245, 238), "seashell1" },
1281 { RGB_TO_ULONG(238, 229, 222), "seashell2" },
1282 { RGB_TO_ULONG(205, 197, 191), "seashell3" },
1283 { RGB_TO_ULONG(139, 134, 130), "seashell4" },
1284 { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
1285 { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
1286 { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
1287 { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
1288 { RGB_TO_ULONG(255, 228, 196), "bisque1" },
1289 { RGB_TO_ULONG(238, 213, 183), "bisque2" },
1290 { RGB_TO_ULONG(205, 183, 158), "bisque3" },
1291 { RGB_TO_ULONG(139, 125, 107), "bisque4" },
1292 { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
1293 { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
1294 { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
1295 { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
1296 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
1297 { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
1298 { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
1299 { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
1300 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
1301 { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
1302 { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
1303 { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
1304 { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
1305 { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
1306 { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
1307 { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
1308 { RGB_TO_ULONG(255, 255, 240), "ivory1" },
1309 { RGB_TO_ULONG(238, 238, 224), "ivory2" },
1310 { RGB_TO_ULONG(205, 205, 193), "ivory3" },
1311 { RGB_TO_ULONG(139, 139, 131), "ivory4" },
1312 { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
1313 { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
1314 { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
1315 { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
1316 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
1317 { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
1318 { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
1319 { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
1320 { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
1321 { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
1322 { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
1323 { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
1324 { RGB_TO_ULONG(240, 255, 255), "azure1" },
1325 { RGB_TO_ULONG(224, 238, 238), "azure2" },
1326 { RGB_TO_ULONG(193, 205, 205), "azure3" },
1327 { RGB_TO_ULONG(131, 139, 139), "azure4" },
1328 { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
1329 { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
1330 { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
1331 { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
1332 { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
1333 { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
1334 { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
1335 { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
1336 { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
1337 { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
1338 { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
1339 { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
1340 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
1341 { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
1342 { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
1343 { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
1344 { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
1345 { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
1346 { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
1347 { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
1348 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
1349 { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
1350 { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
1351 { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
1352 { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
1353 { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
1354 { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
1355 { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
1356 { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
1357 { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
1358 { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
1359 { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
1360 { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
1361 { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
1362 { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
1363 { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
1364 { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
1365 { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
1366 { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
1367 { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
1368 { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
1369 { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
1370 { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
1371 { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
1372 { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
1373 { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
1374 { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
1375 { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
1376 { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
1377 { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
1378 { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
1379 { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
1380 { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
1381 { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
1382 { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
1383 { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
1384 { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
1385 { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
1386 { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
1387 { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
1388 { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
1389 { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
1390 { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
1391 { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
1392 { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
1393 { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
1394 { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
1395 { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
1396 { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
1397 { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
1398 { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
1399 { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
1400 { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
1401 { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
1402 { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
1403 { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
1404 { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
1405 { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
1406 { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
1407 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
1408 { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
1409 { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
1410 { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
1411 { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
1412 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
1413 { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
1414 { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
1415 { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
1416 { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
1417 { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
1418 { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
1419 { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
1420 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
1421 { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
1422 { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
1423 { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
1424 { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
1425 { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
1426 { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
1427 { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
1428 { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
1429 { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
1430 { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
1431 { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
1432 { RGB_TO_ULONG(255, 246, 143), "khaki1" },
1433 { RGB_TO_ULONG(238, 230, 133), "khaki2" },
1434 { RGB_TO_ULONG(205, 198, 115), "khaki3" },
1435 { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
1436 { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
1437 { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
1438 { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
1439 { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
1440 { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
1441 { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
1442 { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
1443 { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
1444 { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
1445 { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
1446 { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
1447 { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
1448 { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
1449 { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
1450 { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
1451 { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
1452 { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
1453 { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
1454 { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
1455 { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
1456 { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
1457 { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
1458 { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
1459 { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
1460 { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
1461 { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
1462 { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
1463 { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
1464 { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
1465 { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
1466 { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
1467 { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
1468 { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
1469 { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
1470 { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
1471 { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
1472 { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
1473 { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
1474 { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
1475 { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
1476 { RGB_TO_ULONG(255, 231, 186), "wheat1" },
1477 { RGB_TO_ULONG(238, 216, 174), "wheat2" },
1478 { RGB_TO_ULONG(205, 186, 150), "wheat3" },
1479 { RGB_TO_ULONG(139, 126, 102), "wheat4" },
1480 { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
1481 { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
1482 { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
1483 { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
1484 { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
1485 { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
1486 { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
1487 { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
1488 { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
1489 { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
1490 { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
1491 { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
1492 { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
1493 { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
1494 { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
1495 { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
1496 { RGB_TO_ULONG(255, 140, 105), "salmon1" },
1497 { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
1498 { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
1499 { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
1500 { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
1501 { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
1502 { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
1503 { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
1504 { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
1505 { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
1506 { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
1507 { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
1508 { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
1509 { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
1510 { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
1511 { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
1512 { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
1513 { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
1514 { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
1515 { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
1516 { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
1517 { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
1518 { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
1519 { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
1520 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
1521 { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
1522 { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
1523 { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
1524 { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
1525 { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
1526 { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
1527 { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
1528 { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
1529 { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
1530 { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
1531 { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
1532 { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
1533 { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
1534 { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
1535 { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
1536 { RGB_TO_ULONG(255, 181, 197), "pink1" },
1537 { RGB_TO_ULONG(238, 169, 184), "pink2" },
1538 { RGB_TO_ULONG(205, 145, 158), "pink3" },
1539 { RGB_TO_ULONG(139, 99 , 108), "pink4" },
1540 { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
1541 { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
1542 { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
1543 { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
1544 { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
1545 { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
1546 { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
1547 { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
1548 { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
1549 { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
1550 { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
1551 { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
1552 { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
1553 { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
1554 { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
1555 { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
1556 { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
1557 { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
1558 { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
1559 { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
1560 { RGB_TO_ULONG(255, 131, 250), "orchid1" },
1561 { RGB_TO_ULONG(238, 122, 233), "orchid2" },
1562 { RGB_TO_ULONG(205, 105, 201), "orchid3" },
1563 { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
1564 { RGB_TO_ULONG(255, 187, 255), "plum1" },
1565 { RGB_TO_ULONG(238, 174, 238), "plum2" },
1566 { RGB_TO_ULONG(205, 150, 205), "plum3" },
1567 { RGB_TO_ULONG(139, 102, 139), "plum4" },
1568 { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
1569 { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
1570 { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
1571 { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
1572 { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
1573 { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
1574 { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
1575 { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
1576 { RGB_TO_ULONG(155, 48 , 255), "purple1" },
1577 { RGB_TO_ULONG(145, 44 , 238), "purple2" },
1578 { RGB_TO_ULONG(125, 38 , 205), "purple3" },
1579 { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
1580 { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
1581 { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
1582 { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
1583 { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
1584 { RGB_TO_ULONG(255, 225, 255), "thistle1" },
1585 { RGB_TO_ULONG(238, 210, 238), "thistle2" },
1586 { RGB_TO_ULONG(205, 181, 205), "thistle3" },
1587 { RGB_TO_ULONG(139, 123, 139), "thistle4" },
1588 { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
1589 { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
1590 { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
1591 { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
1592 { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
1593 { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
1594 { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
1595 { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
1596 { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
1597 { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
1598 { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
1599 { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
1600 { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
1601 { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
1602 { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
1603 { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
1604 { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
1605 { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
1606 { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
1607 { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
1608 { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
1609 { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
1610 { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
1611 { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
1612 { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
1613 { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
1614 { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
1615 { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
1616 { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
1617 { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
1618 { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
1619 { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
1620 { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
1621 { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
1622 { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
1623 { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
1624 { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
1625 { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
1626 { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
1627 { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
1628 { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
1629 { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
1630 { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
1631 { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
1632 { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
1633 { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
1634 { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
1635 { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
1636 { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
1637 { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
1638 { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
1639 { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
1640 { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
1641 { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
1642 { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
1643 { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
1644 { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
1645 { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
1646 { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
1647 { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
1648 { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
1649 { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
1650 { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
1651 { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
1652 { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
1653 { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
1654 { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
1655 { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
1656 { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
1657 { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
1658 { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
1659 { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
1660 { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
1661 { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
1662 { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
1663 { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
1664 { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
1665 { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
1666 { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
1667 { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
1668 { RGB_TO_ULONG(102, 102, 102), "gray40" },
1669 { RGB_TO_ULONG(102, 102, 102), "grey40" },
1670 { RGB_TO_ULONG(105, 105, 105), "gray41" },
1671 { RGB_TO_ULONG(105, 105, 105), "grey41" },
1672 { RGB_TO_ULONG(107, 107, 107), "gray42" },
1673 { RGB_TO_ULONG(107, 107, 107), "grey42" },
1674 { RGB_TO_ULONG(110, 110, 110), "gray43" },
1675 { RGB_TO_ULONG(110, 110, 110), "grey43" },
1676 { RGB_TO_ULONG(112, 112, 112), "gray44" },
1677 { RGB_TO_ULONG(112, 112, 112), "grey44" },
1678 { RGB_TO_ULONG(115, 115, 115), "gray45" },
1679 { RGB_TO_ULONG(115, 115, 115), "grey45" },
1680 { RGB_TO_ULONG(117, 117, 117), "gray46" },
1681 { RGB_TO_ULONG(117, 117, 117), "grey46" },
1682 { RGB_TO_ULONG(120, 120, 120), "gray47" },
1683 { RGB_TO_ULONG(120, 120, 120), "grey47" },
1684 { RGB_TO_ULONG(122, 122, 122), "gray48" },
1685 { RGB_TO_ULONG(122, 122, 122), "grey48" },
1686 { RGB_TO_ULONG(125, 125, 125), "gray49" },
1687 { RGB_TO_ULONG(125, 125, 125), "grey49" },
1688 { RGB_TO_ULONG(127, 127, 127), "gray50" },
1689 { RGB_TO_ULONG(127, 127, 127), "grey50" },
1690 { RGB_TO_ULONG(130, 130, 130), "gray51" },
1691 { RGB_TO_ULONG(130, 130, 130), "grey51" },
1692 { RGB_TO_ULONG(133, 133, 133), "gray52" },
1693 { RGB_TO_ULONG(133, 133, 133), "grey52" },
1694 { RGB_TO_ULONG(135, 135, 135), "gray53" },
1695 { RGB_TO_ULONG(135, 135, 135), "grey53" },
1696 { RGB_TO_ULONG(138, 138, 138), "gray54" },
1697 { RGB_TO_ULONG(138, 138, 138), "grey54" },
1698 { RGB_TO_ULONG(140, 140, 140), "gray55" },
1699 { RGB_TO_ULONG(140, 140, 140), "grey55" },
1700 { RGB_TO_ULONG(143, 143, 143), "gray56" },
1701 { RGB_TO_ULONG(143, 143, 143), "grey56" },
1702 { RGB_TO_ULONG(145, 145, 145), "gray57" },
1703 { RGB_TO_ULONG(145, 145, 145), "grey57" },
1704 { RGB_TO_ULONG(148, 148, 148), "gray58" },
1705 { RGB_TO_ULONG(148, 148, 148), "grey58" },
1706 { RGB_TO_ULONG(150, 150, 150), "gray59" },
1707 { RGB_TO_ULONG(150, 150, 150), "grey59" },
1708 { RGB_TO_ULONG(153, 153, 153), "gray60" },
1709 { RGB_TO_ULONG(153, 153, 153), "grey60" },
1710 { RGB_TO_ULONG(156, 156, 156), "gray61" },
1711 { RGB_TO_ULONG(156, 156, 156), "grey61" },
1712 { RGB_TO_ULONG(158, 158, 158), "gray62" },
1713 { RGB_TO_ULONG(158, 158, 158), "grey62" },
1714 { RGB_TO_ULONG(161, 161, 161), "gray63" },
1715 { RGB_TO_ULONG(161, 161, 161), "grey63" },
1716 { RGB_TO_ULONG(163, 163, 163), "gray64" },
1717 { RGB_TO_ULONG(163, 163, 163), "grey64" },
1718 { RGB_TO_ULONG(166, 166, 166), "gray65" },
1719 { RGB_TO_ULONG(166, 166, 166), "grey65" },
1720 { RGB_TO_ULONG(168, 168, 168), "gray66" },
1721 { RGB_TO_ULONG(168, 168, 168), "grey66" },
1722 { RGB_TO_ULONG(171, 171, 171), "gray67" },
1723 { RGB_TO_ULONG(171, 171, 171), "grey67" },
1724 { RGB_TO_ULONG(173, 173, 173), "gray68" },
1725 { RGB_TO_ULONG(173, 173, 173), "grey68" },
1726 { RGB_TO_ULONG(176, 176, 176), "gray69" },
1727 { RGB_TO_ULONG(176, 176, 176), "grey69" },
1728 { RGB_TO_ULONG(179, 179, 179), "gray70" },
1729 { RGB_TO_ULONG(179, 179, 179), "grey70" },
1730 { RGB_TO_ULONG(181, 181, 181), "gray71" },
1731 { RGB_TO_ULONG(181, 181, 181), "grey71" },
1732 { RGB_TO_ULONG(184, 184, 184), "gray72" },
1733 { RGB_TO_ULONG(184, 184, 184), "grey72" },
1734 { RGB_TO_ULONG(186, 186, 186), "gray73" },
1735 { RGB_TO_ULONG(186, 186, 186), "grey73" },
1736 { RGB_TO_ULONG(189, 189, 189), "gray74" },
1737 { RGB_TO_ULONG(189, 189, 189), "grey74" },
1738 { RGB_TO_ULONG(191, 191, 191), "gray75" },
1739 { RGB_TO_ULONG(191, 191, 191), "grey75" },
1740 { RGB_TO_ULONG(194, 194, 194), "gray76" },
1741 { RGB_TO_ULONG(194, 194, 194), "grey76" },
1742 { RGB_TO_ULONG(196, 196, 196), "gray77" },
1743 { RGB_TO_ULONG(196, 196, 196), "grey77" },
1744 { RGB_TO_ULONG(199, 199, 199), "gray78" },
1745 { RGB_TO_ULONG(199, 199, 199), "grey78" },
1746 { RGB_TO_ULONG(201, 201, 201), "gray79" },
1747 { RGB_TO_ULONG(201, 201, 201), "grey79" },
1748 { RGB_TO_ULONG(204, 204, 204), "gray80" },
1749 { RGB_TO_ULONG(204, 204, 204), "grey80" },
1750 { RGB_TO_ULONG(207, 207, 207), "gray81" },
1751 { RGB_TO_ULONG(207, 207, 207), "grey81" },
1752 { RGB_TO_ULONG(209, 209, 209), "gray82" },
1753 { RGB_TO_ULONG(209, 209, 209), "grey82" },
1754 { RGB_TO_ULONG(212, 212, 212), "gray83" },
1755 { RGB_TO_ULONG(212, 212, 212), "grey83" },
1756 { RGB_TO_ULONG(214, 214, 214), "gray84" },
1757 { RGB_TO_ULONG(214, 214, 214), "grey84" },
1758 { RGB_TO_ULONG(217, 217, 217), "gray85" },
1759 { RGB_TO_ULONG(217, 217, 217), "grey85" },
1760 { RGB_TO_ULONG(219, 219, 219), "gray86" },
1761 { RGB_TO_ULONG(219, 219, 219), "grey86" },
1762 { RGB_TO_ULONG(222, 222, 222), "gray87" },
1763 { RGB_TO_ULONG(222, 222, 222), "grey87" },
1764 { RGB_TO_ULONG(224, 224, 224), "gray88" },
1765 { RGB_TO_ULONG(224, 224, 224), "grey88" },
1766 { RGB_TO_ULONG(227, 227, 227), "gray89" },
1767 { RGB_TO_ULONG(227, 227, 227), "grey89" },
1768 { RGB_TO_ULONG(229, 229, 229), "gray90" },
1769 { RGB_TO_ULONG(229, 229, 229), "grey90" },
1770 { RGB_TO_ULONG(232, 232, 232), "gray91" },
1771 { RGB_TO_ULONG(232, 232, 232), "grey91" },
1772 { RGB_TO_ULONG(235, 235, 235), "gray92" },
1773 { RGB_TO_ULONG(235, 235, 235), "grey92" },
1774 { RGB_TO_ULONG(237, 237, 237), "gray93" },
1775 { RGB_TO_ULONG(237, 237, 237), "grey93" },
1776 { RGB_TO_ULONG(240, 240, 240), "gray94" },
1777 { RGB_TO_ULONG(240, 240, 240), "grey94" },
1778 { RGB_TO_ULONG(242, 242, 242), "gray95" },
1779 { RGB_TO_ULONG(242, 242, 242), "grey95" },
1780 { RGB_TO_ULONG(245, 245, 245), "gray96" },
1781 { RGB_TO_ULONG(245, 245, 245), "grey96" },
1782 { RGB_TO_ULONG(247, 247, 247), "gray97" },
1783 { RGB_TO_ULONG(247, 247, 247), "grey97" },
1784 { RGB_TO_ULONG(250, 250, 250), "gray98" },
1785 { RGB_TO_ULONG(250, 250, 250), "grey98" },
1786 { RGB_TO_ULONG(252, 252, 252), "gray99" },
1787 { RGB_TO_ULONG(252, 252, 252), "grey99" },
1788 { RGB_TO_ULONG(255, 255, 255), "gray100" },
1789 { RGB_TO_ULONG(255, 255, 255), "grey100" },
1790 { RGB_TO_ULONG(169, 169, 169), "dark grey" },
1791 { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
1792 { RGB_TO_ULONG(169, 169, 169), "dark gray" },
1793 { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
1794 { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
1795 { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
1796 { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
1797 { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
1798 { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
1799 { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
1800 { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
1801 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1802 { RGB_TO_ULONG(144, 238, 144), "light green" },
1803 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1806 unsigned long
1807 mac_color_map_lookup (colorname)
1808 char *colorname;
1810 Lisp_Object ret = Qnil;
1811 int i;
1813 BLOCK_INPUT;
1815 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
1816 if (stricmp (colorname, mac_color_map[i].name) == 0)
1818 ret = mac_color_map[i].color;
1819 break;
1822 UNBLOCK_INPUT;
1824 return ret;
1827 Lisp_Object
1828 x_to_mac_color (colorname)
1829 char * colorname;
1831 register Lisp_Object tail, ret = Qnil;
1833 BLOCK_INPUT;
1835 if (colorname[0] == '#')
1837 /* Could be an old-style RGB Device specification. */
1838 char *color;
1839 int size;
1840 color = colorname + 1;
1842 size = strlen(color);
1843 if (size == 3 || size == 6 || size == 9 || size == 12)
1845 unsigned long colorval;
1846 int i, pos;
1847 pos = 0;
1848 size /= 3;
1849 colorval = 0;
1851 for (i = 0; i < 3; i++)
1853 char *end;
1854 char t;
1855 unsigned long value;
1857 /* The check for 'x' in the following conditional takes into
1858 account the fact that strtol allows a "0x" in front of
1859 our numbers, and we don't. */
1860 if (!isxdigit(color[0]) || color[1] == 'x')
1861 break;
1862 t = color[size];
1863 color[size] = '\0';
1864 value = strtoul(color, &end, 16);
1865 color[size] = t;
1866 if (errno == ERANGE || end - color != size)
1867 break;
1868 switch (size)
1870 case 1:
1871 value = value * 0x10;
1872 break;
1873 case 2:
1874 break;
1875 case 3:
1876 value /= 0x10;
1877 break;
1878 case 4:
1879 value /= 0x100;
1880 break;
1882 colorval |= (value << pos);
1883 pos += 0x8;
1884 if (i == 2)
1886 UNBLOCK_INPUT;
1887 return (colorval);
1889 color = end;
1893 else if (strnicmp(colorname, "rgb:", 4) == 0)
1895 char *color;
1896 unsigned long colorval;
1897 int i, pos;
1898 pos = 0;
1900 colorval = 0;
1901 color = colorname + 4;
1902 for (i = 0; i < 3; i++)
1904 char *end;
1905 unsigned long value;
1907 /* The check for 'x' in the following conditional takes into
1908 account the fact that strtol allows a "0x" in front of
1909 our numbers, and we don't. */
1910 if (!isxdigit(color[0]) || color[1] == 'x')
1911 break;
1912 value = strtoul(color, &end, 16);
1913 if (errno == ERANGE)
1914 break;
1915 switch (end - color)
1917 case 1:
1918 value = value * 0x10 + value;
1919 break;
1920 case 2:
1921 break;
1922 case 3:
1923 value /= 0x10;
1924 break;
1925 case 4:
1926 value /= 0x100;
1927 break;
1928 default:
1929 value = ULONG_MAX;
1931 if (value == ULONG_MAX)
1932 break;
1933 colorval |= (value << pos);
1934 pos += 0x8;
1935 if (i == 2)
1937 if (*end != '\0')
1938 break;
1939 UNBLOCK_INPUT;
1940 return (colorval);
1942 if (*end != '/')
1943 break;
1944 color = end + 1;
1947 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1949 /* This is an RGB Intensity specification. */
1950 char *color;
1951 unsigned long colorval;
1952 int i, pos;
1953 pos = 0;
1955 colorval = 0;
1956 color = colorname + 5;
1957 for (i = 0; i < 3; i++)
1959 char *end;
1960 double value;
1961 unsigned long val;
1963 value = strtod(color, &end);
1964 if (errno == ERANGE)
1965 break;
1966 if (value < 0.0 || value > 1.0)
1967 break;
1968 val = (unsigned long)(0x100 * value);
1969 /* We used 0x100 instead of 0xFF to give an continuous
1970 range between 0.0 and 1.0 inclusive. The next statement
1971 fixes the 1.0 case. */
1972 if (val == 0x100)
1973 val = 0xFF;
1974 colorval |= (val << pos);
1975 pos += 0x8;
1976 if (i == 2)
1978 if (*end != '\0')
1979 break;
1980 UNBLOCK_INPUT;
1981 return (colorval);
1983 if (*end != '/')
1984 break;
1985 color = end + 1;
1989 ret = mac_color_map_lookup (colorname);
1991 UNBLOCK_INPUT;
1992 return ret;
1995 /* Gamma-correct COLOR on frame F. */
1997 void
1998 gamma_correct (f, color)
1999 struct frame *f;
2000 unsigned long *color;
2002 if (f->gamma)
2004 unsigned long red, green, blue;
2006 red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2007 green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2008 blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
2009 *color = RGB_TO_ULONG (red, green, blue);
2013 /* Decide if color named COLOR is valid for the display associated
2014 with the selected frame; if so, return the rgb values in COLOR_DEF.
2015 If ALLOC is nonzero, allocate a new colormap cell. */
2018 mac_defined_color (f, color, color_def, alloc)
2019 FRAME_PTR f;
2020 char *color;
2021 XColor *color_def;
2022 int alloc;
2024 register Lisp_Object tem;
2025 unsigned long mac_color_ref;
2027 tem = x_to_mac_color (color);
2029 if (!NILP (tem))
2031 if (f)
2033 /* Apply gamma correction. */
2034 mac_color_ref = XUINT (tem);
2035 gamma_correct (f, &mac_color_ref);
2036 XSETINT (tem, mac_color_ref);
2039 color_def->pixel = mac_color_ref;
2040 color_def->red = RED_FROM_ULONG (mac_color_ref);
2041 color_def->green = GREEN_FROM_ULONG (mac_color_ref);
2042 color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
2044 return 1;
2046 else
2048 return 0;
2052 /* Given a string ARG naming a color, compute a pixel value from it
2053 suitable for screen F.
2054 If F is not a color screen, return DEF (default) regardless of what
2055 ARG says. */
2058 x_decode_color (f, arg, def)
2059 FRAME_PTR f;
2060 Lisp_Object arg;
2061 int def;
2063 XColor cdef;
2065 CHECK_STRING (arg);
2067 if (strcmp (XSTRING (arg)->data, "black") == 0)
2068 return BLACK_PIX_DEFAULT (f);
2069 else if (strcmp (XSTRING (arg)->data, "white") == 0)
2070 return WHITE_PIX_DEFAULT (f);
2072 #if 0
2073 if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
2074 * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
2075 return def;
2076 #endif
2078 if (mac_defined_color (f, XSTRING (arg)->data, &cdef, 1))
2079 return cdef.pixel;
2081 /* defined_color failed; return an ultimate default. */
2082 return def;
2085 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
2086 the previous value of that parameter, NEW_VALUE is the new value. */
2088 static void
2089 x_set_line_spacing (f, new_value, old_value)
2090 struct frame *f;
2091 Lisp_Object new_value, old_value;
2093 if (NILP (new_value))
2094 f->extra_line_spacing = 0;
2095 else if (NATNUMP (new_value))
2096 f->extra_line_spacing = XFASTINT (new_value);
2097 else
2098 Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
2099 Fcons (new_value, Qnil)));
2100 if (FRAME_VISIBLE_P (f))
2101 redraw_frame (f);
2105 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
2106 the previous value of that parameter, NEW_VALUE is the new value. */
2108 static void
2109 x_set_screen_gamma (f, new_value, old_value)
2110 struct frame *f;
2111 Lisp_Object new_value, old_value;
2113 if (NILP (new_value))
2114 f->gamma = 0;
2115 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
2116 /* The value 0.4545 is the normal viewing gamma. */
2117 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
2118 else
2119 Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
2120 Fcons (new_value, Qnil)));
2122 clear_face_cache (0);
2126 /* Functions called only from `x_set_frame_param'
2127 to set individual parameters.
2129 If FRAME_MAC_WINDOW (f) is 0,
2130 the frame is being created and its window does not exist yet.
2131 In that case, just record the parameter's new value
2132 in the standard place; do not attempt to change the window. */
2134 void
2135 x_set_foreground_color (f, arg, oldval)
2136 struct frame *f;
2137 Lisp_Object arg, oldval;
2139 FRAME_FOREGROUND_PIXEL (f)
2140 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2142 if (FRAME_MAC_WINDOW (f) != 0)
2144 update_face_from_frame_parameter (f, Qforeground_color, arg);
2145 if (FRAME_VISIBLE_P (f))
2146 redraw_frame (f);
2150 void
2151 x_set_background_color (f, arg, oldval)
2152 struct frame *f;
2153 Lisp_Object arg, oldval;
2155 FRAME_BACKGROUND_PIXEL (f)
2156 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
2158 if (FRAME_MAC_WINDOW (f) != 0)
2160 update_face_from_frame_parameter (f, Qbackground_color, arg);
2162 if (FRAME_VISIBLE_P (f))
2163 redraw_frame (f);
2167 void
2168 x_set_mouse_color (f, arg, oldval)
2169 struct frame *f;
2170 Lisp_Object arg, oldval;
2172 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
2173 int count;
2174 int mask_color;
2176 if (!EQ (Qnil, arg))
2177 f->output_data.mac->mouse_pixel
2178 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2179 mask_color = FRAME_BACKGROUND_PIXEL (f);
2181 /* Don't let pointers be invisible. */
2182 if (mask_color == f->output_data.mac->mouse_pixel
2183 && mask_color == FRAME_BACKGROUND_PIXEL (f))
2184 f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
2186 #if 0 /* MAC_TODO : cursor changes */
2187 BLOCK_INPUT;
2189 /* It's not okay to crash if the user selects a screwy cursor. */
2190 count = x_catch_errors (FRAME_W32_DISPLAY (f));
2192 if (!EQ (Qnil, Vx_pointer_shape))
2194 CHECK_NUMBER (Vx_pointer_shape);
2195 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
2197 else
2198 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2199 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
2201 if (!EQ (Qnil, Vx_nontext_pointer_shape))
2203 CHECK_NUMBER (Vx_nontext_pointer_shape);
2204 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2205 XINT (Vx_nontext_pointer_shape));
2207 else
2208 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
2209 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2211 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
2213 CHECK_NUMBER (Vx_hourglass_pointer_shape);
2214 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2215 XINT (Vx_hourglass_pointer_shape));
2217 else
2218 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
2219 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
2221 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
2222 if (!EQ (Qnil, Vx_mode_pointer_shape))
2224 CHECK_NUMBER (Vx_mode_pointer_shape);
2225 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2226 XINT (Vx_mode_pointer_shape));
2228 else
2229 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
2230 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
2232 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
2234 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
2235 cross_cursor
2236 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2237 XINT (Vx_sensitive_text_pointer_shape));
2239 else
2240 cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
2242 if (!NILP (Vx_window_horizontal_drag_shape))
2244 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
2245 horizontal_drag_cursor
2246 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
2247 XINT (Vx_window_horizontal_drag_shape));
2249 else
2250 horizontal_drag_cursor
2251 = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
2253 /* Check and report errors with the above calls. */
2254 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
2255 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
2258 XColor fore_color, back_color;
2260 fore_color.pixel = f->output_data.w32->mouse_pixel;
2261 back_color.pixel = mask_color;
2262 XQueryColor (FRAME_W32_DISPLAY (f),
2263 DefaultColormap (FRAME_W32_DISPLAY (f),
2264 DefaultScreen (FRAME_W32_DISPLAY (f))),
2265 &fore_color);
2266 XQueryColor (FRAME_W32_DISPLAY (f),
2267 DefaultColormap (FRAME_W32_DISPLAY (f),
2268 DefaultScreen (FRAME_W32_DISPLAY (f))),
2269 &back_color);
2270 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
2271 &fore_color, &back_color);
2272 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
2273 &fore_color, &back_color);
2274 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
2275 &fore_color, &back_color);
2276 XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
2277 &fore_color, &back_color);
2278 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
2279 &fore_color, &back_color);
2282 if (FRAME_W32_WINDOW (f) != 0)
2283 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
2285 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
2286 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
2287 f->output_data.w32->text_cursor = cursor;
2289 if (nontext_cursor != f->output_data.w32->nontext_cursor
2290 && f->output_data.w32->nontext_cursor != 0)
2291 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
2292 f->output_data.w32->nontext_cursor = nontext_cursor;
2294 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
2295 && f->output_data.w32->hourglass_cursor != 0)
2296 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
2297 f->output_data.w32->hourglass_cursor = hourglass_cursor;
2299 if (mode_cursor != f->output_data.w32->modeline_cursor
2300 && f->output_data.w32->modeline_cursor != 0)
2301 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
2302 f->output_data.w32->modeline_cursor = mode_cursor;
2304 if (cross_cursor != f->output_data.w32->cross_cursor
2305 && f->output_data.w32->cross_cursor != 0)
2306 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
2307 f->output_data.w32->cross_cursor = cross_cursor;
2309 XFlush (FRAME_W32_DISPLAY (f));
2310 UNBLOCK_INPUT;
2312 update_face_from_frame_parameter (f, Qmouse_color, arg);
2313 #endif /* MAC_TODO */
2316 void
2317 x_set_cursor_color (f, arg, oldval)
2318 struct frame *f;
2319 Lisp_Object arg, oldval;
2321 unsigned long fore_pixel;
2323 if (!NILP (Vx_cursor_fore_pixel))
2324 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
2325 WHITE_PIX_DEFAULT (f));
2326 else
2327 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2328 f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2330 /* Make sure that the cursor color differs from the background color. */
2331 if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
2333 f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
2334 if (f->output_data.mac->cursor_pixel == fore_pixel)
2335 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
2337 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
2339 #if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
2340 if (FRAME_MAC_WINDOW (f) != 0)
2342 if (FRAME_VISIBLE_P (f))
2344 x_display_cursor (f, 0);
2345 x_display_cursor (f, 1);
2348 #endif
2350 update_face_from_frame_parameter (f, Qcursor_color, arg);
2353 /* Set the border-color of frame F to pixel value PIX.
2354 Note that this does not fully take effect if done before
2355 F has an window. */
2356 void
2357 x_set_border_pixel (f, pix)
2358 struct frame *f;
2359 int pix;
2361 f->output_data.mac->border_pixel = pix;
2363 if (FRAME_MAC_WINDOW (f) != 0 && f->output_data.mac->border_width > 0)
2365 if (FRAME_VISIBLE_P (f))
2366 redraw_frame (f);
2370 /* Set the border-color of frame F to value described by ARG.
2371 ARG can be a string naming a color.
2372 The border-color is used for the border that is drawn by the server.
2373 Note that this does not fully take effect if done before
2374 F has a window; it must be redone when the window is created. */
2376 void
2377 x_set_border_color (f, arg, oldval)
2378 struct frame *f;
2379 Lisp_Object arg, oldval;
2381 int pix;
2383 CHECK_STRING (arg);
2384 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2385 x_set_border_pixel (f, pix);
2386 update_face_from_frame_parameter (f, Qborder_color, arg);
2389 /* Value is the internal representation of the specified cursor type
2390 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2391 of the bar cursor. */
2393 enum text_cursor_kinds
2394 x_specified_cursor_type (arg, width)
2395 Lisp_Object arg;
2396 int *width;
2398 enum text_cursor_kinds type;
2400 if (EQ (arg, Qbar))
2402 type = BAR_CURSOR;
2403 *width = 2;
2405 else if (CONSP (arg)
2406 && EQ (XCAR (arg), Qbar)
2407 && INTEGERP (XCDR (arg))
2408 && XINT (XCDR (arg)) >= 0)
2410 type = BAR_CURSOR;
2411 *width = XINT (XCDR (arg));
2413 else if (NILP (arg))
2414 type = NO_CURSOR;
2415 else
2416 /* Treat anything unknown as "box cursor".
2417 It was bad to signal an error; people have trouble fixing
2418 .Xdefaults with Emacs, when it has something bad in it. */
2419 type = FILLED_BOX_CURSOR;
2421 return type;
2424 void
2425 x_set_cursor_type (f, arg, oldval)
2426 FRAME_PTR f;
2427 Lisp_Object arg, oldval;
2429 int width;
2431 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
2432 f->output_data.mac->cursor_width = width;
2434 /* Make sure the cursor gets redrawn. This is overkill, but how
2435 often do people change cursor types? */
2436 update_mode_lines++;
2439 #if 0 /* MAC_TODO: really no icon for Mac */
2440 void
2441 x_set_icon_type (f, arg, oldval)
2442 struct frame *f;
2443 Lisp_Object arg, oldval;
2445 int result;
2447 if (NILP (arg) && NILP (oldval))
2448 return;
2450 if (STRINGP (arg) && STRINGP (oldval)
2451 && EQ (Fstring_equal (oldval, arg), Qt))
2452 return;
2454 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2455 return;
2457 BLOCK_INPUT;
2459 result = x_bitmap_icon (f, arg);
2460 if (result)
2462 UNBLOCK_INPUT;
2463 error ("No icon window available");
2466 UNBLOCK_INPUT;
2468 #endif /* MAC_TODO */
2470 /* Return non-nil if frame F wants a bitmap icon. */
2472 Lisp_Object
2473 x_icon_type (f)
2474 FRAME_PTR f;
2476 Lisp_Object tem;
2478 tem = assq_no_quit (Qicon_type, f->param_alist);
2479 if (CONSP (tem))
2480 return XCDR (tem);
2481 else
2482 return Qnil;
2485 void
2486 x_set_icon_name (f, arg, oldval)
2487 struct frame *f;
2488 Lisp_Object arg, oldval;
2490 int result;
2492 if (STRINGP (arg))
2494 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2495 return;
2497 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2498 return;
2500 f->icon_name = arg;
2502 #if 0 /* MAC_TODO */
2503 if (f->output_data.w32->icon_bitmap != 0)
2504 return;
2506 BLOCK_INPUT;
2508 result = x_text_icon (f,
2509 (char *) XSTRING ((!NILP (f->icon_name)
2510 ? f->icon_name
2511 : !NILP (f->title)
2512 ? f->title
2513 : f->name))->data);
2515 if (result)
2517 UNBLOCK_INPUT;
2518 error ("No icon window available");
2521 /* If the window was unmapped (and its icon was mapped),
2522 the new icon is not mapped, so map the window in its stead. */
2523 if (FRAME_VISIBLE_P (f))
2525 #ifdef USE_X_TOOLKIT
2526 XtPopup (f->output_data.w32->widget, XtGrabNone);
2527 #endif
2528 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2531 XFlush (FRAME_W32_DISPLAY (f));
2532 UNBLOCK_INPUT;
2533 #endif /* MAC_TODO */
2536 extern Lisp_Object x_new_font ();
2537 extern Lisp_Object x_new_fontset();
2539 void
2540 x_set_font (f, arg, oldval)
2541 struct frame *f;
2542 Lisp_Object arg, oldval;
2544 Lisp_Object result;
2545 Lisp_Object fontset_name;
2546 Lisp_Object frame;
2547 int old_fontset = FRAME_FONTSET(f);
2549 CHECK_STRING (arg);
2551 fontset_name = Fquery_fontset (arg, Qnil);
2553 BLOCK_INPUT;
2554 result = (STRINGP (fontset_name)
2555 ? x_new_fontset (f, XSTRING (fontset_name)->data)
2556 : x_new_font (f, XSTRING (arg)->data));
2557 UNBLOCK_INPUT;
2559 if (EQ (result, Qnil))
2560 error ("Font `%s' is not defined", XSTRING (arg)->data);
2561 else if (EQ (result, Qt))
2562 error ("The characters of the given font have varying widths");
2563 else if (STRINGP (result))
2565 if (STRINGP (fontset_name))
2567 /* Fontset names are built from ASCII font names, so the
2568 names may be equal despite there was a change. */
2569 if (old_fontset == FRAME_FONTSET (f))
2570 return;
2572 else if (!NILP (Fequal (result, oldval)))
2573 return;
2575 store_frame_param (f, Qfont, result);
2576 recompute_basic_faces (f);
2578 else
2579 abort ();
2581 do_pending_window_change (0);
2583 /* Don't call `face-set-after-frame-default' when faces haven't been
2584 initialized yet. This is the case when called from
2585 Fx_create_frame. In that case, the X widget or window doesn't
2586 exist either, and we can end up in x_report_frame_params with a
2587 null widget which gives a segfault. */
2588 if (FRAME_FACE_CACHE (f))
2590 XSETFRAME (frame, f);
2591 call1 (Qface_set_after_frame_default, frame);
2595 void
2596 x_set_border_width (f, arg, oldval)
2597 struct frame *f;
2598 Lisp_Object arg, oldval;
2600 CHECK_NUMBER (arg);
2602 if (XINT (arg) == f->output_data.mac->border_width)
2603 return;
2605 #if 0 /* MAC_TODO */
2606 if (FRAME_MAC_WINDOW (f) != 0)
2607 error ("Cannot change the border width of a window");
2608 #endif
2610 f->output_data.mac->border_width = XINT (arg);
2613 void
2614 x_set_internal_border_width (f, arg, oldval)
2615 struct frame *f;
2616 Lisp_Object arg, oldval;
2618 int old = f->output_data.mac->internal_border_width;
2620 CHECK_NUMBER (arg);
2621 f->output_data.mac->internal_border_width = XINT (arg);
2622 if (f->output_data.mac->internal_border_width < 0)
2623 f->output_data.mac->internal_border_width = 0;
2625 if (f->output_data.mac->internal_border_width == old)
2626 return;
2628 if (FRAME_MAC_WINDOW (f) != 0)
2630 x_set_window_size (f, 0, f->width, f->height);
2631 SET_FRAME_GARBAGED (f);
2632 do_pending_window_change (0);
2634 else
2635 SET_FRAME_GARBAGED (f);
2638 void
2639 x_set_visibility (f, value, oldval)
2640 struct frame *f;
2641 Lisp_Object value, oldval;
2643 Lisp_Object frame;
2644 XSETFRAME (frame, f);
2646 if (NILP (value))
2647 Fmake_frame_invisible (frame, Qt);
2648 else if (EQ (value, Qicon))
2649 Ficonify_frame (frame);
2650 else
2651 Fmake_frame_visible (frame);
2655 /* Change window heights in windows rooted in WINDOW by N lines. */
2657 static void
2658 x_change_window_heights (window, n)
2659 Lisp_Object window;
2660 int n;
2662 struct window *w = XWINDOW (window);
2664 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2665 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2667 if (INTEGERP (w->orig_top))
2668 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2669 if (INTEGERP (w->orig_height))
2670 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2672 /* Handle just the top child in a vertical split. */
2673 if (!NILP (w->vchild))
2674 x_change_window_heights (w->vchild, n);
2676 /* Adjust all children in a horizontal split. */
2677 for (window = w->hchild; !NILP (window); window = w->next)
2679 w = XWINDOW (window);
2680 x_change_window_heights (window, n);
2684 void
2685 x_set_menu_bar_lines (f, value, oldval)
2686 struct frame *f;
2687 Lisp_Object value, oldval;
2689 int nlines;
2690 int olines = FRAME_MENU_BAR_LINES (f);
2692 /* Right now, menu bars don't work properly in minibuf-only frames;
2693 most of the commands try to apply themselves to the minibuffer
2694 frame itself, and get an error because you can't switch buffers
2695 in or split the minibuffer window. */
2696 if (FRAME_MINIBUF_ONLY_P (f))
2697 return;
2699 if (INTEGERP (value))
2700 nlines = XINT (value);
2701 else
2702 nlines = 0;
2704 FRAME_MENU_BAR_LINES (f) = 0;
2705 if (nlines)
2706 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2707 else
2709 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2710 free_frame_menubar (f);
2711 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2713 /* Adjust the frame size so that the client (text) dimensions
2714 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2715 set correctly. */
2716 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2717 do_pending_window_change (0);
2719 adjust_glyphs (f);
2723 /* Set the number of lines used for the tool bar of frame F to VALUE.
2724 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2725 is the old number of tool bar lines. This function changes the
2726 height of all windows on frame F to match the new tool bar height.
2727 The frame's height doesn't change. */
2729 void
2730 x_set_tool_bar_lines (f, value, oldval)
2731 struct frame *f;
2732 Lisp_Object value, oldval;
2734 int delta, nlines, root_height;
2735 Lisp_Object root_window;
2737 /* Treat tool bars like menu bars. */
2738 if (FRAME_MINIBUF_ONLY_P (f))
2739 return;
2741 /* Use VALUE only if an integer >= 0. */
2742 if (INTEGERP (value) && XINT (value) >= 0)
2743 nlines = XFASTINT (value);
2744 else
2745 nlines = 0;
2747 /* Make sure we redisplay all windows in this frame. */
2748 ++windows_or_buffers_changed;
2750 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2752 /* Don't resize the tool-bar to more than we have room for. */
2753 root_window = FRAME_ROOT_WINDOW (f);
2754 root_height = XINT (XWINDOW (root_window)->height);
2755 if (root_height - delta < 1)
2757 delta = root_height - 1;
2758 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2761 FRAME_TOOL_BAR_LINES (f) = nlines;
2762 x_change_window_heights (root_window, delta);
2763 adjust_glyphs (f);
2765 /* We also have to make sure that the internal border at the top of
2766 the frame, below the menu bar or tool bar, is redrawn when the
2767 tool bar disappears. This is so because the internal border is
2768 below the tool bar if one is displayed, but is below the menu bar
2769 if there isn't a tool bar. The tool bar draws into the area
2770 below the menu bar. */
2771 if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2773 updating_frame = f;
2774 clear_frame ();
2775 clear_current_matrices (f);
2776 updating_frame = NULL;
2779 /* If the tool bar gets smaller, the internal border below it
2780 has to be cleared. It was formerly part of the display
2781 of the larger tool bar, and updating windows won't clear it. */
2782 if (delta < 0)
2784 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2785 int width = PIXEL_WIDTH (f);
2786 int y = nlines * CANON_Y_UNIT (f);
2788 BLOCK_INPUT;
2789 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2790 0, y, width, height, 0);
2791 UNBLOCK_INPUT;
2793 if (WINDOWP (f->tool_bar_window))
2794 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2799 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2800 w32_id_name.
2802 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2803 name; if NAME is a string, set F's name to NAME and set
2804 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2806 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2807 suggesting a new name, which lisp code should override; if
2808 F->explicit_name is set, ignore the new name; otherwise, set it. */
2810 void
2811 x_set_name (f, name, explicit)
2812 struct frame *f;
2813 Lisp_Object name;
2814 int explicit;
2816 /* Make sure that requests from lisp code override requests from
2817 Emacs redisplay code. */
2818 if (explicit)
2820 /* If we're switching from explicit to implicit, we had better
2821 update the mode lines and thereby update the title. */
2822 if (f->explicit_name && NILP (name))
2823 update_mode_lines = 1;
2825 f->explicit_name = ! NILP (name);
2827 else if (f->explicit_name)
2828 return;
2830 /* If NAME is nil, set the name to the w32_id_name. */
2831 if (NILP (name))
2833 /* Check for no change needed in this very common case
2834 before we do any consing. */
2835 if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
2836 XSTRING (f->name)->data))
2837 return;
2838 name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
2840 else
2841 CHECK_STRING (name);
2843 /* Don't change the name if it's already NAME. */
2844 if (! NILP (Fstring_equal (name, f->name)))
2845 return;
2847 f->name = name;
2849 /* For setting the frame title, the title parameter should override
2850 the name parameter. */
2851 if (! NILP (f->title))
2852 name = f->title;
2854 if (FRAME_MAC_WINDOW (f))
2856 if (STRING_MULTIBYTE (name))
2857 #if 0 /* MAC_TODO: encoding title string */
2858 name = ENCODE_SYSTEM (name);
2859 #else
2860 return;
2861 #endif
2863 BLOCK_INPUT;
2866 Str255 windowTitle;
2867 if (strlen (XSTRING (name)->data) < 255)
2869 strcpy (windowTitle, XSTRING (name)->data);
2870 c2pstr (windowTitle);
2871 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2875 UNBLOCK_INPUT;
2879 /* This function should be called when the user's lisp code has
2880 specified a name for the frame; the name will override any set by the
2881 redisplay code. */
2882 void
2883 x_explicitly_set_name (f, arg, oldval)
2884 FRAME_PTR f;
2885 Lisp_Object arg, oldval;
2887 x_set_name (f, arg, 1);
2890 /* This function should be called by Emacs redisplay code to set the
2891 name; names set this way will never override names set by the user's
2892 lisp code. */
2893 void
2894 x_implicitly_set_name (f, arg, oldval)
2895 FRAME_PTR f;
2896 Lisp_Object arg, oldval;
2898 x_set_name (f, arg, 0);
2901 /* Change the title of frame F to NAME.
2902 If NAME is nil, use the frame name as the title.
2904 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2905 name; if NAME is a string, set F's name to NAME and set
2906 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2908 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2909 suggesting a new name, which lisp code should override; if
2910 F->explicit_name is set, ignore the new name; otherwise, set it. */
2912 void
2913 x_set_title (f, name, old_name)
2914 struct frame *f;
2915 Lisp_Object name, old_name;
2917 /* Don't change the title if it's already NAME. */
2918 if (EQ (name, f->title))
2919 return;
2921 update_mode_lines = 1;
2923 f->title = name;
2925 if (NILP (name))
2926 name = f->name;
2928 if (FRAME_MAC_WINDOW (f))
2930 if (STRING_MULTIBYTE (name))
2931 #if 0 /* MAC_TODO: encoding title string */
2932 name = ENCODE_SYSTEM (name);
2933 #else
2934 return;
2935 #endif
2937 BLOCK_INPUT;
2940 Str255 windowTitle;
2941 if (strlen (XSTRING (name)->data) < 255)
2943 strcpy (windowTitle, XSTRING (name)->data);
2944 c2pstr (windowTitle);
2945 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2949 UNBLOCK_INPUT;
2953 void
2954 x_set_autoraise (f, arg, oldval)
2955 struct frame *f;
2956 Lisp_Object arg, oldval;
2958 f->auto_raise = !EQ (Qnil, arg);
2961 void
2962 x_set_autolower (f, arg, oldval)
2963 struct frame *f;
2964 Lisp_Object arg, oldval;
2966 f->auto_lower = !EQ (Qnil, arg);
2969 void
2970 x_set_unsplittable (f, arg, oldval)
2971 struct frame *f;
2972 Lisp_Object arg, oldval;
2974 f->no_split = !NILP (arg);
2977 void
2978 x_set_vertical_scroll_bars (f, arg, oldval)
2979 struct frame *f;
2980 Lisp_Object arg, oldval;
2982 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2983 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2984 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2985 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2987 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2988 = (NILP (arg)
2989 ? vertical_scroll_bar_none
2990 : EQ (Qright, arg)
2991 ? vertical_scroll_bar_right
2992 : vertical_scroll_bar_left);
2994 /* We set this parameter before creating the window for the
2995 frame, so we can get the geometry right from the start.
2996 However, if the window hasn't been created yet, we shouldn't
2997 call x_set_window_size. */
2998 if (FRAME_MAC_WINDOW (f))
2999 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
3000 do_pending_window_change (0);
3004 void
3005 x_set_scroll_bar_width (f, arg, oldval)
3006 struct frame *f;
3007 Lisp_Object arg, oldval;
3009 /* Imitate X without X Toolkit */
3011 int wid = FONT_WIDTH (f->output_data.mac->font);
3013 if (NILP (arg))
3015 #ifdef MAC_OSX
3016 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 16; /* Aqua scroll bars. */
3017 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
3018 wid - 1) / wid;
3019 #else /* not MAC_OSX */
3020 /* Make the actual width at least 14 pixels and a multiple of a
3021 character width. */
3022 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
3024 /* Use all of that space (aside from required margins) for the
3025 scroll bar. */
3026 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
3027 #endif /* not MAC_OSX */
3028 if (FRAME_MAC_WINDOW (f))
3029 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
3030 do_pending_window_change (0);
3032 else if (INTEGERP (arg) && XINT (arg) > 0
3033 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
3035 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
3036 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
3038 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
3039 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
3040 if (FRAME_MAC_WINDOW (f))
3041 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
3042 do_pending_window_change (0);
3044 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
3045 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3046 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3049 /* Subroutines of creating an frame. */
3051 /* Make sure that Vx_resource_name is set to a reasonable value.
3052 Fix it up, or set it to `emacs' if it is too hopeless. */
3054 static void
3055 validate_x_resource_name ()
3057 int len = 0;
3058 /* Number of valid characters in the resource name. */
3059 int good_count = 0;
3060 /* Number of invalid characters in the resource name. */
3061 int bad_count = 0;
3062 Lisp_Object new;
3063 int i;
3065 if (STRINGP (Vx_resource_name))
3067 unsigned char *p = XSTRING (Vx_resource_name)->data;
3068 int i;
3070 len = STRING_BYTES (XSTRING (Vx_resource_name));
3072 /* Only letters, digits, - and _ are valid in resource names.
3073 Count the valid characters and count the invalid ones. */
3074 for (i = 0; i < len; i++)
3076 int c = p[i];
3077 if (! ((c >= 'a' && c <= 'z')
3078 || (c >= 'A' && c <= 'Z')
3079 || (c >= '0' && c <= '9')
3080 || c == '-' || c == '_'))
3081 bad_count++;
3082 else
3083 good_count++;
3086 else
3087 /* Not a string => completely invalid. */
3088 bad_count = 5, good_count = 0;
3090 /* If name is valid already, return. */
3091 if (bad_count == 0)
3092 return;
3094 /* If name is entirely invalid, or nearly so, use `emacs'. */
3095 if (good_count == 0
3096 || (good_count == 1 && bad_count > 0))
3098 Vx_resource_name = build_string ("emacs");
3099 return;
3102 /* Name is partly valid. Copy it and replace the invalid characters
3103 with underscores. */
3105 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3107 for (i = 0; i < len; i++)
3109 int c = XSTRING (new)->data[i];
3110 if (! ((c >= 'a' && c <= 'z')
3111 || (c >= 'A' && c <= 'Z')
3112 || (c >= '0' && c <= '9')
3113 || c == '-' || c == '_'))
3114 XSTRING (new)->data[i] = '_';
3119 #if 0 /* MAC_TODO: implement resource strings */
3120 extern char *x_get_string_resource ();
3122 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
3123 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3124 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3125 class, where INSTANCE is the name under which Emacs was invoked, or
3126 the name specified by the `-name' or `-rn' command-line arguments.
3128 The optional arguments COMPONENT and SUBCLASS add to the key and the
3129 class, respectively. You must specify both of them or neither.
3130 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3131 and the class is `Emacs.CLASS.SUBCLASS'. */)
3132 (attribute, class, component, subclass)
3133 Lisp_Object attribute, class, component, subclass;
3135 register char *value;
3136 char *name_key;
3137 char *class_key;
3139 CHECK_STRING (attribute);
3140 CHECK_STRING (class);
3142 if (!NILP (component))
3143 CHECK_STRING (component);
3144 if (!NILP (subclass))
3145 CHECK_STRING (subclass);
3146 if (NILP (component) != NILP (subclass))
3147 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3149 validate_x_resource_name ();
3151 /* Allocate space for the components, the dots which separate them,
3152 and the final '\0'. Make them big enough for the worst case. */
3153 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
3154 + (STRINGP (component)
3155 ? STRING_BYTES (XSTRING (component)) : 0)
3156 + STRING_BYTES (XSTRING (attribute))
3157 + 3);
3159 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3160 + STRING_BYTES (XSTRING (class))
3161 + (STRINGP (subclass)
3162 ? STRING_BYTES (XSTRING (subclass)) : 0)
3163 + 3);
3165 /* Start with emacs.FRAMENAME for the name (the specific one)
3166 and with `Emacs' for the class key (the general one). */
3167 strcpy (name_key, XSTRING (Vx_resource_name)->data);
3168 strcpy (class_key, EMACS_CLASS);
3170 strcat (class_key, ".");
3171 strcat (class_key, XSTRING (class)->data);
3173 if (!NILP (component))
3175 strcat (class_key, ".");
3176 strcat (class_key, XSTRING (subclass)->data);
3178 strcat (name_key, ".");
3179 strcat (name_key, XSTRING (component)->data);
3182 strcat (name_key, ".");
3183 strcat (name_key, XSTRING (attribute)->data);
3185 value = x_get_string_resource (Qnil,
3186 name_key, class_key);
3188 if (value != (char *) 0)
3189 return build_string (value);
3190 else
3191 return Qnil;
3194 /* Used when C code wants a resource value. */
3196 char *
3197 x_get_resource_string (attribute, class)
3198 char *attribute, *class;
3200 char *name_key;
3201 char *class_key;
3202 struct frame *sf = SELECTED_FRAME ();
3204 /* Allocate space for the components, the dots which separate them,
3205 and the final '\0'. */
3206 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
3207 + strlen (attribute) + 2);
3208 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
3209 + strlen (class) + 2);
3211 sprintf (name_key, "%s.%s",
3212 XSTRING (Vinvocation_name)->data,
3213 attribute);
3214 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
3216 return x_get_string_resource (sf, name_key, class_key);
3218 #endif /* MAC_TODO */
3220 /* Types we might convert a resource string into. */
3221 enum resource_types
3223 RES_TYPE_NUMBER,
3224 RES_TYPE_FLOAT,
3225 RES_TYPE_BOOLEAN,
3226 RES_TYPE_STRING,
3227 RES_TYPE_SYMBOL
3230 /* Return the value of parameter PARAM.
3232 First search ALIST, then Vdefault_frame_alist, then the X defaults
3233 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3235 Convert the resource to the type specified by desired_type.
3237 If no default is specified, return Qunbound. If you call
3238 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3239 and don't let it get stored in any Lisp-visible variables! */
3241 static Lisp_Object
3242 mac_get_arg (alist, param, attribute, class, type)
3243 Lisp_Object alist, param;
3244 char *attribute;
3245 char *class;
3246 enum resource_types type;
3248 register Lisp_Object tem;
3250 tem = Fassq (param, alist);
3251 if (EQ (tem, Qnil))
3252 tem = Fassq (param, Vdefault_frame_alist);
3253 if (EQ (tem, Qnil))
3256 #if 0 /* MAC_TODO: search resource also */
3257 if (attribute)
3259 tem = Fx_get_resource (build_string (attribute),
3260 build_string (class),
3261 Qnil, Qnil);
3263 if (NILP (tem))
3264 return Qunbound;
3266 switch (type)
3268 case RES_TYPE_NUMBER:
3269 return make_number (atoi (XSTRING (tem)->data));
3271 case RES_TYPE_FLOAT:
3272 return make_float (atof (XSTRING (tem)->data));
3274 case RES_TYPE_BOOLEAN:
3275 tem = Fdowncase (tem);
3276 if (!strcmp (XSTRING (tem)->data, "on")
3277 || !strcmp (XSTRING (tem)->data, "true"))
3278 return Qt;
3279 else
3280 return Qnil;
3282 case RES_TYPE_STRING:
3283 return tem;
3285 case RES_TYPE_SYMBOL:
3286 /* As a special case, we map the values `true' and `on'
3287 to Qt, and `false' and `off' to Qnil. */
3289 Lisp_Object lower;
3290 lower = Fdowncase (tem);
3291 if (!strcmp (XSTRING (lower)->data, "on")
3292 || !strcmp (XSTRING (lower)->data, "true"))
3293 return Qt;
3294 else if (!strcmp (XSTRING (lower)->data, "off")
3295 || !strcmp (XSTRING (lower)->data, "false"))
3296 return Qnil;
3297 else
3298 return Fintern (tem, Qnil);
3301 default:
3302 abort ();
3305 else
3306 #endif /* MAC_TODO */
3307 return Qunbound;
3309 return Fcdr (tem);
3312 /* Record in frame F the specified or default value according to ALIST
3313 of the parameter named PROP (a Lisp symbol).
3314 If no value is specified for PROP, look for an X default for XPROP
3315 on the frame named NAME.
3316 If that is not found either, use the value DEFLT. */
3318 static Lisp_Object
3319 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3320 struct frame *f;
3321 Lisp_Object alist;
3322 Lisp_Object prop;
3323 Lisp_Object deflt;
3324 char *xprop;
3325 char *xclass;
3326 enum resource_types type;
3328 Lisp_Object tem;
3330 tem = mac_get_arg (alist, prop, xprop, xclass, type);
3331 if (EQ (tem, Qunbound))
3332 tem = deflt;
3333 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3334 return tem;
3337 /* XParseGeometry copied from w32xfns.c */
3340 * XParseGeometry parses strings of the form
3341 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
3342 * width, height, xoffset, and yoffset are unsigned integers.
3343 * Example: "=80x24+300-49"
3344 * The equal sign is optional.
3345 * It returns a bitmask that indicates which of the four values
3346 * were actually found in the string. For each value found,
3347 * the corresponding argument is updated; for each value
3348 * not found, the corresponding argument is left unchanged.
3351 static int
3352 read_integer (string, NextString)
3353 register char *string;
3354 char **NextString;
3356 register int Result = 0;
3357 int Sign = 1;
3359 if (*string == '+')
3360 string++;
3361 else if (*string == '-')
3363 string++;
3364 Sign = -1;
3366 for (; (*string >= '0') && (*string <= '9'); string++)
3368 Result = (Result * 10) + (*string - '0');
3370 *NextString = string;
3371 if (Sign >= 0)
3372 return (Result);
3373 else
3374 return (-Result);
3377 int
3378 XParseGeometry (string, x, y, width, height)
3379 char *string;
3380 int *x, *y;
3381 unsigned int *width, *height; /* RETURN */
3383 int mask = NoValue;
3384 register char *strind;
3385 unsigned int tempWidth, tempHeight;
3386 int tempX, tempY;
3387 char *nextCharacter;
3389 if ((string == NULL) || (*string == '\0')) return (mask);
3390 if (*string == '=')
3391 string++; /* ignore possible '=' at beg of geometry spec */
3393 strind = (char *)string;
3394 if (*strind != '+' && *strind != '-' && *strind != 'x')
3396 tempWidth = read_integer (strind, &nextCharacter);
3397 if (strind == nextCharacter)
3398 return (0);
3399 strind = nextCharacter;
3400 mask |= WidthValue;
3403 if (*strind == 'x' || *strind == 'X')
3405 strind++;
3406 tempHeight = read_integer (strind, &nextCharacter);
3407 if (strind == nextCharacter)
3408 return (0);
3409 strind = nextCharacter;
3410 mask |= HeightValue;
3413 if ((*strind == '+') || (*strind == '-'))
3415 if (*strind == '-')
3417 strind++;
3418 tempX = -read_integer (strind, &nextCharacter);
3419 if (strind == nextCharacter)
3420 return (0);
3421 strind = nextCharacter;
3422 mask |= XNegative;
3425 else
3427 strind++;
3428 tempX = read_integer (strind, &nextCharacter);
3429 if (strind == nextCharacter)
3430 return (0);
3431 strind = nextCharacter;
3433 mask |= XValue;
3434 if ((*strind == '+') || (*strind == '-'))
3436 if (*strind == '-')
3438 strind++;
3439 tempY = -read_integer (strind, &nextCharacter);
3440 if (strind == nextCharacter)
3441 return (0);
3442 strind = nextCharacter;
3443 mask |= YNegative;
3446 else
3448 strind++;
3449 tempY = read_integer (strind, &nextCharacter);
3450 if (strind == nextCharacter)
3451 return (0);
3452 strind = nextCharacter;
3454 mask |= YValue;
3458 /* If strind isn't at the end of the string the it's an invalid
3459 geometry specification. */
3461 if (*strind != '\0') return (0);
3463 if (mask & XValue)
3464 *x = tempX;
3465 if (mask & YValue)
3466 *y = tempY;
3467 if (mask & WidthValue)
3468 *width = tempWidth;
3469 if (mask & HeightValue)
3470 *height = tempHeight;
3471 return (mask);
3474 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3475 doc: /* Parse an X-style geometry string STRING.
3476 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3477 The properties returned may include `top', `left', `height', and `width'.
3478 The value of `left' or `top' may be an integer,
3479 or a list (+ N) meaning N pixels relative to top/left corner,
3480 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3481 (string)
3482 Lisp_Object string;
3484 int geometry, x, y;
3485 unsigned int width, height;
3486 Lisp_Object result;
3488 CHECK_STRING (string);
3490 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3491 &x, &y, &width, &height);
3493 result = Qnil;
3494 if (geometry & XValue)
3496 Lisp_Object element;
3498 if (x >= 0 && (geometry & XNegative))
3499 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3500 else if (x < 0 && ! (geometry & XNegative))
3501 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3502 else
3503 element = Fcons (Qleft, make_number (x));
3504 result = Fcons (element, result);
3507 if (geometry & YValue)
3509 Lisp_Object element;
3511 if (y >= 0 && (geometry & YNegative))
3512 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3513 else if (y < 0 && ! (geometry & YNegative))
3514 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3515 else
3516 element = Fcons (Qtop, make_number (y));
3517 result = Fcons (element, result);
3520 if (geometry & WidthValue)
3521 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3522 if (geometry & HeightValue)
3523 result = Fcons (Fcons (Qheight, make_number (height)), result);
3525 return result;
3528 /* Calculate the desired size and position of this window,
3529 and return the flags saying which aspects were specified.
3531 This function does not make the coordinates positive. */
3533 #define DEFAULT_ROWS 40
3534 #define DEFAULT_COLS 80
3536 static int
3537 x_figure_window_size (f, parms)
3538 struct frame *f;
3539 Lisp_Object parms;
3541 register Lisp_Object tem0, tem1, tem2;
3542 long window_prompting = 0;
3544 /* Default values if we fall through.
3545 Actually, if that happens we should get
3546 window manager prompting. */
3547 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3548 f->height = DEFAULT_ROWS;
3549 /* Window managers expect that if program-specified
3550 positions are not (0,0), they're intentional, not defaults. */
3551 f->output_data.mac->top_pos = 0;
3552 f->output_data.mac->left_pos = 0;
3554 tem0 = mac_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3555 tem1 = mac_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3556 tem2 = mac_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3557 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3559 if (!EQ (tem0, Qunbound))
3561 CHECK_NUMBER (tem0);
3562 f->height = XINT (tem0);
3564 if (!EQ (tem1, Qunbound))
3566 CHECK_NUMBER (tem1);
3567 SET_FRAME_WIDTH (f, XINT (tem1));
3569 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3570 window_prompting |= USSize;
3571 else
3572 window_prompting |= PSize;
3575 f->output_data.mac->vertical_scroll_bar_extra
3576 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3578 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3579 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3580 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
3582 x_compute_fringe_widths (f, 0);
3584 f->output_data.mac->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3585 f->output_data.mac->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3587 tem0 = mac_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3588 tem1 = mac_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3589 tem2 = mac_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3590 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3592 if (EQ (tem0, Qminus))
3594 f->output_data.mac->top_pos = 0;
3595 window_prompting |= YNegative;
3597 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3598 && CONSP (XCDR (tem0))
3599 && INTEGERP (XCAR (XCDR (tem0))))
3601 f->output_data.mac->top_pos = - XINT (XCAR (XCDR (tem0)));
3602 window_prompting |= YNegative;
3604 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3605 && CONSP (XCDR (tem0))
3606 && INTEGERP (XCAR (XCDR (tem0))))
3608 f->output_data.mac->top_pos = XINT (XCAR (XCDR (tem0)));
3610 else if (EQ (tem0, Qunbound))
3611 f->output_data.mac->top_pos = 0;
3612 else
3614 CHECK_NUMBER (tem0);
3615 f->output_data.mac->top_pos = XINT (tem0);
3616 if (f->output_data.mac->top_pos < 0)
3617 window_prompting |= YNegative;
3620 if (EQ (tem1, Qminus))
3622 f->output_data.mac->left_pos = 0;
3623 window_prompting |= XNegative;
3625 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3626 && CONSP (XCDR (tem1))
3627 && INTEGERP (XCAR (XCDR (tem1))))
3629 f->output_data.mac->left_pos = - XINT (XCAR (XCDR (tem1)));
3630 window_prompting |= XNegative;
3632 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3633 && CONSP (XCDR (tem1))
3634 && INTEGERP (XCAR (XCDR (tem1))))
3636 f->output_data.mac->left_pos = XINT (XCAR (XCDR (tem1)));
3638 else if (EQ (tem1, Qunbound))
3639 f->output_data.mac->left_pos = 0;
3640 else
3642 CHECK_NUMBER (tem1);
3643 f->output_data.mac->left_pos = XINT (tem1);
3644 if (f->output_data.mac->left_pos < 0)
3645 window_prompting |= XNegative;
3648 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3649 window_prompting |= USPosition;
3650 else
3651 window_prompting |= PPosition;
3654 return window_prompting;
3658 #if 0 /* MAC_TODO */
3659 /* Create and set up the Mac window for frame F. */
3661 static void
3662 mac_window (f, window_prompting, minibuffer_only)
3663 struct frame *f;
3664 long window_prompting;
3665 int minibuffer_only;
3667 Rect r;
3669 BLOCK_INPUT;
3671 /* Use the resource name as the top-level window name
3672 for looking up resources. Make a non-Lisp copy
3673 for the window manager, so GC relocation won't bother it.
3675 Elsewhere we specify the window name for the window manager. */
3678 char *str = (char *) XSTRING (Vx_resource_name)->data;
3679 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3680 strcpy (f->namebuf, str);
3683 SetRect (&r, f->output_data.mac->left_pos, f->output_data.mac->top_pos,
3684 f->output_data.mac->left_pos + PIXEL_WIDTH (f),
3685 f->output_data.mac->top_pos + PIXEL_HEIGHT (f));
3686 FRAME_MAC_WINDOW (f)
3687 = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
3689 validate_x_resource_name ();
3691 /* x_set_name normally ignores requests to set the name if the
3692 requested name is the same as the current name. This is the one
3693 place where that assumption isn't correct; f->name is set, but
3694 the server hasn't been told. */
3696 Lisp_Object name;
3697 int explicit = f->explicit_name;
3699 f->explicit_name = 0;
3700 name = f->name;
3701 f->name = Qnil;
3702 x_set_name (f, name, explicit);
3705 ShowWindow (FRAME_MAC_WINDOW (f));
3707 UNBLOCK_INPUT;
3709 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3710 initialize_frame_menubar (f);
3712 if (FRAME_MAC_WINDOW (f) == 0)
3713 error ("Unable to create window");
3715 #endif /* MAC_TODO */
3717 /* Handle the icon stuff for this window. Perhaps later we might
3718 want an x_set_icon_position which can be called interactively as
3719 well. */
3721 static void
3722 x_icon (f, parms)
3723 struct frame *f;
3724 Lisp_Object parms;
3726 Lisp_Object icon_x, icon_y;
3728 /* Set the position of the icon. Note that Windows 95 groups all
3729 icons in the tray. */
3730 icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3731 icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3732 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3734 CHECK_NUMBER (icon_x);
3735 CHECK_NUMBER (icon_y);
3737 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3738 error ("Both left and top icon corners of icon must be specified");
3740 BLOCK_INPUT;
3742 if (! EQ (icon_x, Qunbound))
3743 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3745 #if 0 /* TODO */
3746 /* Start up iconic or window? */
3747 x_wm_set_window_state
3748 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
3749 ? IconicState
3750 : NormalState));
3752 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3753 ? f->icon_name
3754 : f->name))->data);
3755 #endif
3757 UNBLOCK_INPUT;
3761 void
3762 x_make_gc (f)
3763 struct frame *f;
3765 XGCValues gc_values;
3767 BLOCK_INPUT;
3769 /* Create the GC's of this frame.
3770 Note that many default values are used. */
3772 /* Normal video */
3773 gc_values.font = f->output_data.mac->font;
3774 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3775 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3776 f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3777 FRAME_MAC_WINDOW (f),
3778 GCFont | GCForeground | GCBackground,
3779 &gc_values);
3781 /* Reverse video style. */
3782 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3783 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3784 f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3785 FRAME_MAC_WINDOW (f),
3786 GCFont | GCForeground | GCBackground,
3787 &gc_values);
3789 /* Cursor has cursor-color background, background-color foreground. */
3790 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3791 gc_values.background = f->output_data.mac->cursor_pixel;
3792 f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
3793 FRAME_MAC_WINDOW (f),
3794 GCFont | GCForeground | GCBackground,
3795 &gc_values);
3797 /* Reliefs. */
3798 f->output_data.mac->white_relief.gc = 0;
3799 f->output_data.mac->black_relief.gc = 0;
3801 UNBLOCK_INPUT;
3805 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3806 1, 1, 0,
3807 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
3808 Returns an Emacs frame object.
3809 ALIST is an alist of frame parameters.
3810 If the parameters specify that the frame should not have a minibuffer,
3811 and do not specify a specific minibuffer window to use,
3812 then `default-minibuffer-frame' must be a frame whose minibuffer can
3813 be shared by the new frame.
3815 This function is an internal primitive--use `make-frame' instead. */)
3816 (parms)
3817 Lisp_Object parms;
3819 struct frame *f;
3820 Lisp_Object frame, tem;
3821 Lisp_Object name;
3822 int minibuffer_only = 0;
3823 long window_prompting = 0;
3824 int width, height;
3825 int count = BINDING_STACK_SIZE ();
3826 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3827 Lisp_Object display;
3828 struct mac_display_info *dpyinfo = NULL;
3829 Lisp_Object parent;
3830 struct kboard *kb;
3831 char x_frame_name[10];
3832 static int x_frame_count = 2; /* begins at 2 because terminal frame is F1 */
3834 check_mac ();
3836 /* Use this general default value to start with
3837 until we know if this frame has a specified name. */
3838 Vx_resource_name = Vinvocation_name;
3840 display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3841 if (EQ (display, Qunbound))
3842 display = Qnil;
3843 dpyinfo = check_x_display_info (display);
3844 #ifdef MULTI_KBOARD
3845 kb = dpyinfo->kboard;
3846 #else
3847 kb = &the_only_kboard;
3848 #endif
3850 name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
3851 if (!STRINGP (name)
3852 && ! EQ (name, Qunbound)
3853 && ! NILP (name))
3854 error ("Invalid frame name--not a string or nil");
3856 if (STRINGP (name))
3857 Vx_resource_name = name;
3859 /* See if parent window is specified. */
3860 parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3861 if (EQ (parent, Qunbound))
3862 parent = Qnil;
3863 if (! NILP (parent))
3864 CHECK_NUMBER (parent);
3866 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3867 /* No need to protect DISPLAY because that's not used after passing
3868 it to make_frame_without_minibuffer. */
3869 frame = Qnil;
3870 GCPRO4 (parms, parent, name, frame);
3871 tem = mac_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
3872 RES_TYPE_SYMBOL);
3873 if (EQ (tem, Qnone) || NILP (tem))
3874 f = make_frame_without_minibuffer (Qnil, kb, display);
3875 else if (EQ (tem, Qonly))
3877 f = make_minibuffer_frame ();
3878 minibuffer_only = 1;
3880 else if (WINDOWP (tem))
3881 f = make_frame_without_minibuffer (tem, kb, display);
3882 else
3883 f = make_frame (1);
3885 if (EQ (name, Qunbound) || NILP (name))
3887 sprintf (x_frame_name, "F%d", x_frame_count++);
3888 f->name = build_string (x_frame_name);
3889 f->explicit_name = 0;
3891 else
3893 f->name = name;
3894 f->explicit_name = 1;
3897 XSETFRAME (frame, f);
3899 /* Note that X Windows does support scroll bars. */
3900 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3902 f->output_method = output_mac;
3903 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
3904 bzero (f->output_data.mac, sizeof (struct mac_output));
3905 FRAME_FONTSET (f) = -1;
3906 f->output_data.mac->scroll_bar_foreground_pixel = -1;
3907 f->output_data.mac->scroll_bar_background_pixel = -1;
3909 #if 0
3910 FRAME_FONTSET (f) = -1;
3911 #endif
3913 f->icon_name
3914 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
3915 if (! STRINGP (f->icon_name))
3916 f->icon_name = Qnil;
3918 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
3919 #ifdef MULTI_KBOARD
3920 FRAME_KBOARD (f) = kb;
3921 #endif
3923 /* Specify the parent under which to make this window. */
3925 if (!NILP (parent))
3927 f->output_data.mac->parent_desc = (Window) parent;
3928 f->output_data.mac->explicit_parent = 1;
3930 else
3932 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
3933 f->output_data.mac->explicit_parent = 0;
3936 /* Set the name; the functions to which we pass f expect the name to
3937 be set. */
3938 if (EQ (name, Qunbound) || NILP (name))
3940 f->name = build_string (dpyinfo->mac_id_name);
3941 f->explicit_name = 0;
3943 else
3945 f->name = name;
3946 f->explicit_name = 1;
3947 /* use the frame's title when getting resources for this frame. */
3948 specbind (Qx_resource_name, name);
3951 /* Extract the window parameters from the supplied values
3952 that are needed to determine window geometry. */
3954 Lisp_Object font;
3956 font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
3958 BLOCK_INPUT;
3959 /* First, try whatever font the caller has specified. */
3960 if (STRINGP (font))
3962 tem = Fquery_fontset (font, Qnil);
3963 if (STRINGP (tem))
3964 font = x_new_fontset (f, XSTRING (tem)->data);
3965 else
3966 font = x_new_font (f, XSTRING (font)->data);
3968 /* Try out a font which we hope has bold and italic variations. */
3969 if (! STRINGP (font))
3970 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
3971 /* If those didn't work, look for something which will at least work. */
3972 if (!STRINGP (font))
3973 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
3974 if (! STRINGP (font))
3975 font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
3976 if (! STRINGP (font))
3977 error ("Cannot find any usable font");
3978 UNBLOCK_INPUT;
3980 x_default_parameter (f, parms, Qfont, font,
3981 "font", "Font", RES_TYPE_STRING);
3984 x_default_parameter (f, parms, Qborder_width, make_number (0),
3985 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
3986 /* This defaults to 2 in order to match xterm. We recognize either
3987 internalBorderWidth or internalBorder (which is what xterm calls
3988 it). */
3989 if (NILP (Fassq (Qinternal_border_width, parms)))
3991 Lisp_Object value;
3993 value = mac_get_arg (parms, Qinternal_border_width,
3994 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
3995 if (! EQ (value, Qunbound))
3996 parms = Fcons (Fcons (Qinternal_border_width, value),
3997 parms);
3999 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4000 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
4001 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
4002 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
4003 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
4005 /* Also do the stuff which must be set before the window exists. */
4006 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4007 "foreground", "Foreground", RES_TYPE_STRING);
4008 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4009 "background", "Background", RES_TYPE_STRING);
4010 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4011 "pointerColor", "Foreground", RES_TYPE_STRING);
4012 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4013 "cursorColor", "Foreground", RES_TYPE_STRING);
4014 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4015 "borderColor", "BorderColor", RES_TYPE_STRING);
4016 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4017 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4018 x_default_parameter (f, parms, Qline_spacing, Qnil,
4019 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4020 x_default_parameter (f, parms, Qleft_fringe, Qnil,
4021 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4022 x_default_parameter (f, parms, Qright_fringe, Qnil,
4023 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4026 /* Init faces before x_default_parameter is called for scroll-bar
4027 parameters because that function calls x_set_scroll_bar_width,
4028 which calls change_frame_size, which calls Fset_window_buffer,
4029 which runs hooks, which call Fvertical_motion. At the end, we
4030 end up in init_iterator with a null face cache, which should not
4031 happen. */
4032 init_frame_faces (f);
4034 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4035 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4036 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
4037 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4038 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4039 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
4040 x_default_parameter (f, parms, Qtitle, Qnil,
4041 "title", "Title", RES_TYPE_STRING);
4043 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
4044 window_prompting = x_figure_window_size (f, parms);
4046 if (window_prompting & XNegative)
4048 if (window_prompting & YNegative)
4049 f->output_data.mac->win_gravity = SouthEastGravity;
4050 else
4051 f->output_data.mac->win_gravity = NorthEastGravity;
4053 else
4055 if (window_prompting & YNegative)
4056 f->output_data.mac->win_gravity = SouthWestGravity;
4057 else
4058 f->output_data.mac->win_gravity = NorthWestGravity;
4061 f->output_data.mac->size_hint_flags = window_prompting;
4063 tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4064 f->no_split = minibuffer_only || EQ (tem, Qt);
4066 /* Create the window. Add the tool-bar height to the initial frame
4067 height so that the user gets a text display area of the size he
4068 specified with -g or via the registry. Later changes of the
4069 tool-bar height don't change the frame size. This is done so that
4070 users can create tall Emacs frames without having to guess how
4071 tall the tool-bar will get. */
4072 f->height += FRAME_TOOL_BAR_LINES (f);
4074 /* mac_window (f, window_prompting, minibuffer_only); */
4075 make_mac_frame (f);
4077 x_icon (f, parms);
4079 x_make_gc (f);
4081 /* Now consider the frame official. */
4082 FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
4083 Vframe_list = Fcons (frame, Vframe_list);
4085 /* We need to do this after creating the window, so that the
4086 icon-creation functions can say whose icon they're describing. */
4087 x_default_parameter (f, parms, Qicon_type, Qnil,
4088 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4090 x_default_parameter (f, parms, Qauto_raise, Qnil,
4091 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4092 x_default_parameter (f, parms, Qauto_lower, Qnil,
4093 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4094 x_default_parameter (f, parms, Qcursor_type, Qbox,
4095 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4096 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4097 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
4099 /* Dimensions, especially f->height, must be done via change_frame_size.
4100 Change will not be effected unless different from the current
4101 f->height. */
4102 width = f->width;
4103 height = f->height;
4105 f->height = 0;
4106 SET_FRAME_WIDTH (f, 0);
4107 change_frame_size (f, height, width, 1, 0, 0);
4109 /* Set up faces after all frame parameters are known. */
4110 call1 (Qface_set_after_frame_default, frame);
4112 #if 0 /* MAC_TODO: when we have window manager hints */
4113 /* Tell the server what size and position, etc, we want, and how
4114 badly we want them. This should be done after we have the menu
4115 bar so that its size can be taken into account. */
4116 BLOCK_INPUT;
4117 x_wm_set_size_hint (f, window_prompting, 0);
4118 UNBLOCK_INPUT;
4119 #endif
4121 /* Make the window appear on the frame and enable display, unless
4122 the caller says not to. However, with explicit parent, Emacs
4123 cannot control visibility, so don't try. */
4124 if (! f->output_data.mac->explicit_parent)
4126 Lisp_Object visibility;
4128 visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
4129 if (EQ (visibility, Qunbound))
4130 visibility = Qt;
4132 #if 0 /* MAC_TODO: really no iconify on Mac */
4133 if (EQ (visibility, Qicon))
4134 x_iconify_frame (f);
4135 else
4136 #endif
4137 if (! NILP (visibility))
4138 x_make_frame_visible (f);
4139 else
4140 /* Must have been Qnil. */
4143 UNGCPRO;
4145 /* Make sure windows on this frame appear in calls to next-window
4146 and similar functions. */
4147 Vwindow_list = Qnil;
4149 return unbind_to (count, frame);
4152 /* FRAME is used only to get a handle on the X display. We don't pass the
4153 display info directly because we're called from frame.c, which doesn't
4154 know about that structure. */
4155 Lisp_Object
4156 x_get_focus_frame (frame)
4157 struct frame *frame;
4159 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4160 Lisp_Object xfocus;
4161 if (! dpyinfo->x_focus_frame)
4162 return Qnil;
4164 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4165 return xfocus;
4168 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4169 doc: /* Internal function called by `color-defined-p', which see. */)
4170 (color, frame)
4171 Lisp_Object color, frame;
4173 XColor foo;
4174 FRAME_PTR f = check_x_frame (frame);
4176 CHECK_STRING (color);
4178 if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
4179 return Qt;
4180 else
4181 return Qnil;
4184 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4185 doc: /* Internal function called by `color-values', which see. */)
4186 (color, frame)
4187 Lisp_Object color, frame;
4189 XColor foo;
4190 FRAME_PTR f = check_x_frame (frame);
4192 CHECK_STRING (color);
4194 if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
4196 Lisp_Object rgb[3];
4198 rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
4199 | RED_FROM_ULONG (foo.pixel));
4200 rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
4201 | GREEN_FROM_ULONG (foo.pixel));
4202 rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
4203 | BLUE_FROM_ULONG (foo.pixel));
4204 return Flist (3, rgb);
4206 else
4207 return Qnil;
4210 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4211 doc: /* Internal function called by `display-color-p', which see. */)
4212 (display)
4213 Lisp_Object display;
4215 struct mac_display_info *dpyinfo = check_x_display_info (display);
4217 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
4218 return Qnil;
4220 return Qt;
4223 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4224 0, 1, 0,
4225 doc: /* Return t if the X display supports shades of gray.
4226 Note that color displays do support shades of gray.
4227 The optional argument DISPLAY specifies which display to ask about.
4228 DISPLAY should be either a frame or a display name (a string).
4229 If omitted or nil, that stands for the selected frame's display. */)
4230 (display)
4231 Lisp_Object display;
4233 struct mac_display_info *dpyinfo = check_x_display_info (display);
4235 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
4236 return Qnil;
4238 return Qt;
4241 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4242 0, 1, 0,
4243 doc: /* Returns the width in pixels of the X display DISPLAY.
4244 The optional argument DISPLAY specifies which display to ask about.
4245 DISPLAY should be either a frame or a display name (a string).
4246 If omitted or nil, that stands for the selected frame's display. */)
4247 (display)
4248 Lisp_Object display;
4250 struct mac_display_info *dpyinfo = check_x_display_info (display);
4252 return make_number (dpyinfo->width);
4255 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4256 Sx_display_pixel_height, 0, 1, 0,
4257 doc: /* Returns the height in pixels of the X display DISPLAY.
4258 The optional argument DISPLAY specifies which display to ask about.
4259 DISPLAY should be either a frame or a display name (a string).
4260 If omitted or nil, that stands for the selected frame's display. */)
4261 (display)
4262 Lisp_Object display;
4264 struct mac_display_info *dpyinfo = check_x_display_info (display);
4266 return make_number (dpyinfo->height);
4269 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4270 0, 1, 0,
4271 doc: /* Returns the number of bitplanes of the display DISPLAY.
4272 The optional argument DISPLAY specifies which display to ask about.
4273 DISPLAY should be either a frame or a display name (a string).
4274 If omitted or nil, that stands for the selected frame's display. */)
4275 (display)
4276 Lisp_Object display;
4278 struct mac_display_info *dpyinfo = check_x_display_info (display);
4280 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
4283 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4284 0, 1, 0,
4285 doc: /* Returns the number of color cells of the display DISPLAY.
4286 The optional argument DISPLAY specifies which display to ask about.
4287 DISPLAY should be either a frame or a display name (a string).
4288 If omitted or nil, that stands for the selected frame's display. */)
4289 (display)
4290 Lisp_Object display;
4292 struct mac_display_info *dpyinfo = check_x_display_info (display);
4294 /* MAC_TODO: check whether this is right */
4295 return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
4298 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4299 Sx_server_max_request_size,
4300 0, 1, 0,
4301 doc: /* Returns the maximum request size of the server of display DISPLAY.
4302 The optional argument DISPLAY specifies which display to ask about.
4303 DISPLAY should be either a frame or a display name (a string).
4304 If omitted or nil, that stands for the selected frame's display. */)
4305 (display)
4306 Lisp_Object display;
4308 struct mac_display_info *dpyinfo = check_x_display_info (display);
4310 return make_number (1);
4313 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4314 doc: /* Returns the vendor ID string of the Mac OS system (Apple).
4315 The optional argument DISPLAY specifies which display to ask about.
4316 DISPLAY should be either a frame or a display name (a string).
4317 If omitted or nil, that stands for the selected frame's display. */)
4318 (display)
4319 Lisp_Object display;
4321 return build_string ("Apple Computers");
4324 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4325 doc: /* Returns the version numbers of the server of display DISPLAY.
4326 The value is a list of three integers: the major and minor
4327 version numbers, and the vendor-specific release
4328 number. See also the function `x-server-vendor'.
4330 The optional argument DISPLAY specifies which display to ask about.
4331 DISPLAY should be either a frame or a display name (a string).
4332 If omitted or nil, that stands for the selected frame's display. */)
4333 (display)
4334 Lisp_Object display;
4336 int mac_major_version, mac_minor_version;
4337 SInt32 response;
4339 if (Gestalt (gestaltSystemVersion, &response) != noErr)
4340 error ("Cannot get Mac OS version");
4342 mac_major_version = (response >> 8) & 0xf;
4343 mac_minor_version = (response >> 4) & 0xf;
4345 return Fcons (make_number (mac_major_version),
4346 Fcons (make_number (mac_minor_version), Qnil));
4349 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4350 doc: /* Return the number of screens on the server of display DISPLAY.
4351 The optional argument DISPLAY specifies which display to ask about.
4352 DISPLAY should be either a frame or a display name (a string).
4353 If omitted or nil, that stands for the selected frame's display. */)
4354 (display)
4355 Lisp_Object display;
4357 return make_number (1);
4360 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4361 doc: /* Return the height in millimeters of the X display DISPLAY.
4362 The optional argument DISPLAY specifies which display to ask about.
4363 DISPLAY should be either a frame or a display name (a string).
4364 If omitted or nil, that stands for the selected frame's display. */)
4365 (display)
4366 Lisp_Object display;
4368 /* MAC_TODO: this is an approximation, and only of the main display */
4370 struct mac_display_info *dpyinfo = check_x_display_info (display);
4371 short h, v;
4373 ScreenRes (&h, &v);
4375 return make_number ((int) (v / 72.0 * 25.4));
4378 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4379 doc: /* Return the width in millimeters of the X display DISPLAY.
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 /* MAC_TODO: this is an approximation, and only of the main display */
4388 struct mac_display_info *dpyinfo = check_x_display_info (display);
4389 short h, v;
4391 ScreenRes (&h, &v);
4393 return make_number ((int) (h / 72.0 * 25.4));
4396 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4397 Sx_display_backing_store, 0, 1, 0,
4398 doc: /* Returns an indication of whether display DISPLAY does backing store.
4399 The value may be `always', `when-mapped', or `not-useful'.
4400 The optional argument DISPLAY specifies which display to ask about.
4401 DISPLAY should be either a frame or a display name (a string).
4402 If omitted or nil, that stands for the selected frame's display. */)
4403 (display)
4404 Lisp_Object display;
4406 return intern ("not-useful");
4409 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4410 Sx_display_visual_class, 0, 1, 0,
4411 doc: /* Returns the visual class of the display DISPLAY.
4412 The value is one of the symbols `static-gray', `gray-scale',
4413 `static-color', `pseudo-color', `true-color', or `direct-color'.
4415 The optional argument DISPLAY specifies which display to ask about.
4416 DISPLAY should be either a frame or a display name (a string).
4417 If omitted or nil, that stands for the selected frame's display. */)
4418 (display)
4419 Lisp_Object display;
4421 struct mac_display_info *dpyinfo = check_x_display_info (display);
4423 #if 0
4424 switch (dpyinfo->visual->class)
4426 case StaticGray: return (intern ("static-gray"));
4427 case GrayScale: return (intern ("gray-scale"));
4428 case StaticColor: return (intern ("static-color"));
4429 case PseudoColor: return (intern ("pseudo-color"));
4430 case TrueColor: return (intern ("true-color"));
4431 case DirectColor: return (intern ("direct-color"));
4432 default:
4433 error ("Display has an unknown visual class");
4435 #endif /* 0 */
4437 error ("Display has an unknown visual class");
4440 DEFUN ("x-display-save-under", Fx_display_save_under,
4441 Sx_display_save_under, 0, 1, 0,
4442 doc: /* Returns t if the display DISPLAY supports the save-under feature.
4443 The optional argument DISPLAY specifies which display to ask about.
4444 DISPLAY should be either a frame or a display name (a string).
4445 If omitted or nil, that stands for the selected frame's display. */)
4446 (display)
4447 Lisp_Object display;
4449 return Qnil;
4453 x_pixel_width (f)
4454 register struct frame *f;
4456 return PIXEL_WIDTH (f);
4460 x_pixel_height (f)
4461 register struct frame *f;
4463 return PIXEL_HEIGHT (f);
4467 x_char_width (f)
4468 register struct frame *f;
4470 return FONT_WIDTH (f->output_data.mac->font);
4474 x_char_height (f)
4475 register struct frame *f;
4477 return f->output_data.mac->line_height;
4481 x_screen_planes (f)
4482 register struct frame *f;
4484 return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
4487 /* Return the display structure for the display named NAME.
4488 Open a new connection if necessary. */
4490 struct mac_display_info *
4491 x_display_info_for_name (name)
4492 Lisp_Object name;
4494 Lisp_Object names;
4495 struct mac_display_info *dpyinfo;
4497 CHECK_STRING (name);
4499 for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
4500 dpyinfo;
4501 dpyinfo = dpyinfo->next, names = XCDR (names))
4503 Lisp_Object tem;
4504 tem = Fstring_equal (XCAR (XCAR (names)), name);
4505 if (!NILP (tem))
4506 return dpyinfo;
4509 /* Use this general default value to start with. */
4510 Vx_resource_name = Vinvocation_name;
4512 validate_x_resource_name ();
4514 dpyinfo = mac_term_init (name, (unsigned char *) 0,
4515 (char *) XSTRING (Vx_resource_name)->data);
4517 if (dpyinfo == 0)
4518 error ("Cannot connect to server %s", XSTRING (name)->data);
4520 mac_in_use = 1;
4521 XSETFASTINT (Vwindow_system_version, 3);
4523 return dpyinfo;
4526 #if 0 /* MAC_TODO: implement network support */
4527 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4528 1, 3, 0,
4529 doc: /* Open a connection to a server.
4530 DISPLAY is the name of the display to connect to.
4531 Optional second arg XRM-STRING is a string of resources in xrdb format.
4532 If the optional third arg MUST-SUCCEED is non-nil,
4533 terminate Emacs if we can't open the connection. */)
4534 (display, xrm_string, must_succeed)
4535 Lisp_Object display, xrm_string, must_succeed;
4537 unsigned char *xrm_option;
4538 struct mac_display_info *dpyinfo;
4540 CHECK_STRING (display);
4541 if (! NILP (xrm_string))
4542 CHECK_STRING (xrm_string);
4544 if (! EQ (Vwindow_system, intern ("mac")))
4545 error ("Not using Mac OS");
4547 if (! NILP (xrm_string))
4548 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4549 else
4550 xrm_option = (unsigned char *) 0;
4552 validate_x_resource_name ();
4554 /* This is what opens the connection and sets x_current_display.
4555 This also initializes many symbols, such as those used for input. */
4556 dpyinfo = mac_term_init (display, xrm_option,
4557 (char *) XSTRING (Vx_resource_name)->data);
4559 if (dpyinfo == 0)
4561 if (!NILP (must_succeed))
4562 fatal ("Cannot connect to server %s.\n",
4563 XSTRING (display)->data);
4564 else
4565 error ("Cannot connect to server %s", XSTRING (display)->data);
4568 mac_in_use = 1;
4570 XSETFASTINT (Vwindow_system_version, 3);
4571 return Qnil;
4574 DEFUN ("x-close-connection", Fx_close_connection,
4575 Sx_close_connection, 1, 1, 0,
4576 doc: /* Close the connection to DISPLAY's server.
4577 For DISPLAY, specify either a frame or a display name (a string).
4578 If DISPLAY is nil, that stands for the selected frame's display. */)
4579 (display)
4580 Lisp_Object display;
4582 struct mac_display_info *dpyinfo = check_x_display_info (display);
4583 int i;
4585 if (dpyinfo->reference_count > 0)
4586 error ("Display still has frames on it");
4588 BLOCK_INPUT;
4589 /* Free the fonts in the font table. */
4590 for (i = 0; i < dpyinfo->n_fonts; i++)
4591 if (dpyinfo->font_table[i].name)
4593 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4594 xfree (dpyinfo->font_table[i].full_name);
4595 xfree (dpyinfo->font_table[i].name);
4596 x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
4598 x_destroy_all_bitmaps (dpyinfo);
4600 x_delete_display (dpyinfo);
4601 UNBLOCK_INPUT;
4603 return Qnil;
4605 #endif /* 0 */
4607 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4608 doc: /* Return the list of display names that Emacs has connections to. */)
4611 Lisp_Object tail, result;
4613 result = Qnil;
4614 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4615 result = Fcons (XCAR (XCAR (tail)), result);
4617 return result;
4620 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4621 doc: /* If ON is non-nil, report errors as soon as the erring request is made.
4622 If ON is nil, allow buffering of requests.
4623 This is a noop on Mac OS systems.
4624 The optional second argument DISPLAY specifies which display to act on.
4625 DISPLAY should be either a frame or a display name (a string).
4626 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4627 (on, display)
4628 Lisp_Object display, on;
4630 return Qnil;
4634 /***********************************************************************
4635 Image types
4636 ***********************************************************************/
4638 /* Value is the number of elements of vector VECTOR. */
4640 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4642 /* List of supported image types. Use define_image_type to add new
4643 types. Use lookup_image_type to find a type for a given symbol. */
4645 static struct image_type *image_types;
4647 /* The symbol `image' which is the car of the lists used to represent
4648 images in Lisp. */
4650 extern Lisp_Object Qimage;
4652 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4654 Lisp_Object Qxbm;
4656 /* Keywords. */
4658 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
4659 extern Lisp_Object QCdata, QCtype;
4660 Lisp_Object QCascent, QCmargin, QCrelief;
4661 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
4662 Lisp_Object QCindex;
4664 /* Other symbols. */
4666 Lisp_Object Qlaplace;
4668 /* Time in seconds after which images should be removed from the cache
4669 if not displayed. */
4671 Lisp_Object Vimage_cache_eviction_delay;
4673 /* Function prototypes. */
4675 static void define_image_type P_ ((struct image_type *type));
4676 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
4677 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
4678 static void x_laplace P_ ((struct frame *, struct image *));
4679 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
4680 Lisp_Object));
4683 /* Define a new image type from TYPE. This adds a copy of TYPE to
4684 image_types and adds the symbol *TYPE->type to Vimage_types. */
4686 static void
4687 define_image_type (type)
4688 struct image_type *type;
4690 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4691 The initialized data segment is read-only. */
4692 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
4693 bcopy (type, p, sizeof *p);
4694 p->next = image_types;
4695 image_types = p;
4696 Vimage_types = Fcons (*p->type, Vimage_types);
4700 /* Look up image type SYMBOL, and return a pointer to its image_type
4701 structure. Value is null if SYMBOL is not a known image type. */
4703 static INLINE struct image_type *
4704 lookup_image_type (symbol)
4705 Lisp_Object symbol;
4707 struct image_type *type;
4709 for (type = image_types; type; type = type->next)
4710 if (EQ (symbol, *type->type))
4711 break;
4713 return type;
4717 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4718 valid image specification is a list whose car is the symbol
4719 `image', and whose rest is a property list. The property list must
4720 contain a value for key `:type'. That value must be the name of a
4721 supported image type. The rest of the property list depends on the
4722 image type. */
4725 valid_image_p (object)
4726 Lisp_Object object;
4728 int valid_p = 0;
4730 if (CONSP (object) && EQ (XCAR (object), Qimage))
4732 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
4733 struct image_type *type = lookup_image_type (symbol);
4735 if (type)
4736 valid_p = type->valid_p (object);
4739 return valid_p;
4743 /* Log error message with format string FORMAT and argument ARG.
4744 Signaling an error, e.g. when an image cannot be loaded, is not a
4745 good idea because this would interrupt redisplay, and the error
4746 message display would lead to another redisplay. This function
4747 therefore simply displays a message. */
4749 static void
4750 image_error (format, arg1, arg2)
4751 char *format;
4752 Lisp_Object arg1, arg2;
4754 add_to_log (format, arg1, arg2);
4759 /***********************************************************************
4760 Image specifications
4761 ***********************************************************************/
4763 enum image_value_type
4765 IMAGE_DONT_CHECK_VALUE_TYPE,
4766 IMAGE_STRING_VALUE,
4767 IMAGE_SYMBOL_VALUE,
4768 IMAGE_POSITIVE_INTEGER_VALUE,
4769 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
4770 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
4771 IMAGE_ASCENT_VALUE,
4772 IMAGE_INTEGER_VALUE,
4773 IMAGE_FUNCTION_VALUE,
4774 IMAGE_NUMBER_VALUE,
4775 IMAGE_BOOL_VALUE
4778 /* Structure used when parsing image specifications. */
4780 struct image_keyword
4782 /* Name of keyword. */
4783 char *name;
4785 /* The type of value allowed. */
4786 enum image_value_type type;
4788 /* Non-zero means key must be present. */
4789 int mandatory_p;
4791 /* Used to recognize duplicate keywords in a property list. */
4792 int count;
4794 /* The value that was found. */
4795 Lisp_Object value;
4799 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
4800 int, Lisp_Object));
4801 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
4804 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
4805 has the format (image KEYWORD VALUE ...). One of the keyword/
4806 value pairs must be `:type TYPE'. KEYWORDS is a vector of
4807 image_keywords structures of size NKEYWORDS describing other
4808 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
4810 static int
4811 parse_image_spec (spec, keywords, nkeywords, type)
4812 Lisp_Object spec;
4813 struct image_keyword *keywords;
4814 int nkeywords;
4815 Lisp_Object type;
4817 int i;
4818 Lisp_Object plist;
4820 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
4821 return 0;
4823 plist = XCDR (spec);
4824 while (CONSP (plist))
4826 Lisp_Object key, value;
4828 /* First element of a pair must be a symbol. */
4829 key = XCAR (plist);
4830 plist = XCDR (plist);
4831 if (!SYMBOLP (key))
4832 return 0;
4834 /* There must follow a value. */
4835 if (!CONSP (plist))
4836 return 0;
4837 value = XCAR (plist);
4838 plist = XCDR (plist);
4840 /* Find key in KEYWORDS. Error if not found. */
4841 for (i = 0; i < nkeywords; ++i)
4842 if (strcmp (keywords[i].name, XSTRING (SYMBOL_NAME (key))->data) == 0)
4843 break;
4845 if (i == nkeywords)
4846 continue;
4848 /* Record that we recognized the keyword. If a keywords
4849 was found more than once, it's an error. */
4850 keywords[i].value = value;
4851 ++keywords[i].count;
4853 if (keywords[i].count > 1)
4854 return 0;
4856 /* Check type of value against allowed type. */
4857 switch (keywords[i].type)
4859 case IMAGE_STRING_VALUE:
4860 if (!STRINGP (value))
4861 return 0;
4862 break;
4864 case IMAGE_SYMBOL_VALUE:
4865 if (!SYMBOLP (value))
4866 return 0;
4867 break;
4869 case IMAGE_POSITIVE_INTEGER_VALUE:
4870 if (!INTEGERP (value) || XINT (value) <= 0)
4871 return 0;
4872 break;
4874 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
4875 if (INTEGERP (value) && XINT (value) >= 0)
4876 break;
4877 if (CONSP (value)
4878 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
4879 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
4880 break;
4881 return 0;
4883 case IMAGE_ASCENT_VALUE:
4884 if (SYMBOLP (value) && EQ (value, Qcenter))
4885 break;
4886 else if (INTEGERP (value)
4887 && XINT (value) >= 0
4888 && XINT (value) <= 100)
4889 break;
4890 return 0;
4892 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
4893 if (!INTEGERP (value) || XINT (value) < 0)
4894 return 0;
4895 break;
4897 case IMAGE_DONT_CHECK_VALUE_TYPE:
4898 break;
4900 case IMAGE_FUNCTION_VALUE:
4901 value = indirect_function (value);
4902 if (SUBRP (value)
4903 || COMPILEDP (value)
4904 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
4905 break;
4906 return 0;
4908 case IMAGE_NUMBER_VALUE:
4909 if (!INTEGERP (value) && !FLOATP (value))
4910 return 0;
4911 break;
4913 case IMAGE_INTEGER_VALUE:
4914 if (!INTEGERP (value))
4915 return 0;
4916 break;
4918 case IMAGE_BOOL_VALUE:
4919 if (!NILP (value) && !EQ (value, Qt))
4920 return 0;
4921 break;
4923 default:
4924 abort ();
4925 break;
4928 if (EQ (key, QCtype) && !EQ (type, value))
4929 return 0;
4932 /* Check that all mandatory fields are present. */
4933 for (i = 0; i < nkeywords; ++i)
4934 if (keywords[i].mandatory_p && keywords[i].count == 0)
4935 return 0;
4937 return NILP (plist);
4941 /* Return the value of KEY in image specification SPEC. Value is nil
4942 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
4943 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
4945 static Lisp_Object
4946 image_spec_value (spec, key, found)
4947 Lisp_Object spec, key;
4948 int *found;
4950 Lisp_Object tail;
4952 xassert (valid_image_p (spec));
4954 for (tail = XCDR (spec);
4955 CONSP (tail) && CONSP (XCDR (tail));
4956 tail = XCDR (XCDR (tail)))
4958 if (EQ (XCAR (tail), key))
4960 if (found)
4961 *found = 1;
4962 return XCAR (XCDR (tail));
4966 if (found)
4967 *found = 0;
4968 return Qnil;
4974 /***********************************************************************
4975 Image type independent image structures
4976 ***********************************************************************/
4978 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
4979 static void free_image P_ ((struct frame *f, struct image *img));
4982 /* Allocate and return a new image structure for image specification
4983 SPEC. SPEC has a hash value of HASH. */
4985 static struct image *
4986 make_image (spec, hash)
4987 Lisp_Object spec;
4988 unsigned hash;
4990 struct image *img = (struct image *) xmalloc (sizeof *img);
4992 xassert (valid_image_p (spec));
4993 bzero (img, sizeof *img);
4994 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
4995 xassert (img->type != NULL);
4996 img->spec = spec;
4997 img->data.lisp_val = Qnil;
4998 img->ascent = DEFAULT_IMAGE_ASCENT;
4999 img->hash = hash;
5000 return img;
5004 /* Free image IMG which was used on frame F, including its resources. */
5006 static void
5007 free_image (f, img)
5008 struct frame *f;
5009 struct image *img;
5011 if (img)
5013 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5015 /* Remove IMG from the hash table of its cache. */
5016 if (img->prev)
5017 img->prev->next = img->next;
5018 else
5019 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5021 if (img->next)
5022 img->next->prev = img->prev;
5024 c->images[img->id] = NULL;
5026 /* Free resources, then free IMG. */
5027 img->type->free (f, img);
5028 xfree (img);
5033 /* Prepare image IMG for display on frame F. Must be called before
5034 drawing an image. */
5036 void
5037 prepare_image_for_display (f, img)
5038 struct frame *f;
5039 struct image *img;
5041 EMACS_TIME t;
5043 /* We're about to display IMG, so set its timestamp to `now'. */
5044 EMACS_GET_TIME (t);
5045 img->timestamp = EMACS_SECS (t);
5047 /* If IMG doesn't have a pixmap yet, load it now, using the image
5048 type dependent loader function. */
5049 if (img->pixmap == 0 && !img->load_failed_p)
5050 img->load_failed_p = img->type->load (f, img) == 0;
5054 /* Value is the number of pixels for the ascent of image IMG when
5055 drawn in face FACE. */
5058 image_ascent (img, face)
5059 struct image *img;
5060 struct face *face;
5062 int height = img->height + img->vmargin;
5063 int ascent;
5065 if (img->ascent == CENTERED_IMAGE_ASCENT)
5067 if (face->font)
5068 ascent = height / 2 - (FONT_DESCENT(face->font)
5069 - FONT_BASE(face->font)) / 2;
5070 else
5071 ascent = height / 2;
5073 else
5074 ascent = height * img->ascent / 100.0;
5076 return ascent;
5081 /***********************************************************************
5082 Helper functions for X image types
5083 ***********************************************************************/
5085 static void x_clear_image P_ ((struct frame *f, struct image *img));
5086 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5087 struct image *img,
5088 Lisp_Object color_name,
5089 unsigned long dflt));
5091 /* Free X resources of image IMG which is used on frame F. */
5093 static void
5094 x_clear_image (f, img)
5095 struct frame *f;
5096 struct image *img;
5098 #if 0 /* MAC_TODO: W32 image support */
5100 if (img->pixmap)
5102 BLOCK_INPUT;
5103 XFreePixmap (NULL, img->pixmap);
5104 img->pixmap = 0;
5105 UNBLOCK_INPUT;
5108 if (img->ncolors)
5110 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
5112 /* If display has an immutable color map, freeing colors is not
5113 necessary and some servers don't allow it. So don't do it. */
5114 if (class != StaticColor
5115 && class != StaticGray
5116 && class != TrueColor)
5118 Colormap cmap;
5119 BLOCK_INPUT;
5120 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
5121 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
5122 img->ncolors, 0);
5123 UNBLOCK_INPUT;
5126 xfree (img->colors);
5127 img->colors = NULL;
5128 img->ncolors = 0;
5130 #endif /* MAC_TODO */
5134 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5135 cannot be allocated, use DFLT. Add a newly allocated color to
5136 IMG->colors, so that it can be freed again. Value is the pixel
5137 color. */
5139 static unsigned long
5140 x_alloc_image_color (f, img, color_name, dflt)
5141 struct frame *f;
5142 struct image *img;
5143 Lisp_Object color_name;
5144 unsigned long dflt;
5146 #if 0 /* MAC_TODO: allocing colors. */
5147 XColor color;
5148 unsigned long result;
5150 xassert (STRINGP (color_name));
5152 if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
5154 /* This isn't called frequently so we get away with simply
5155 reallocating the color vector to the needed size, here. */
5156 ++img->ncolors;
5157 img->colors =
5158 (unsigned long *) xrealloc (img->colors,
5159 img->ncolors * sizeof *img->colors);
5160 img->colors[img->ncolors - 1] = color.pixel;
5161 result = color.pixel;
5163 else
5164 result = dflt;
5165 return result;
5166 #endif /* MAC_TODO */
5167 return 0;
5172 /***********************************************************************
5173 Image Cache
5174 ***********************************************************************/
5176 static void cache_image P_ ((struct frame *f, struct image *img));
5179 /* Return a new, initialized image cache that is allocated from the
5180 heap. Call free_image_cache to free an image cache. */
5182 struct image_cache *
5183 make_image_cache ()
5185 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5186 int size;
5188 bzero (c, sizeof *c);
5189 c->size = 50;
5190 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5191 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5192 c->buckets = (struct image **) xmalloc (size);
5193 bzero (c->buckets, size);
5194 return c;
5198 /* Free image cache of frame F. Be aware that X frames share images
5199 caches. */
5201 void
5202 free_image_cache (f)
5203 struct frame *f;
5205 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5206 if (c)
5208 int i;
5210 /* Cache should not be referenced by any frame when freed. */
5211 xassert (c->refcount == 0);
5213 for (i = 0; i < c->used; ++i)
5214 free_image (f, c->images[i]);
5215 xfree (c->images);
5216 xfree (c->buckets);
5217 xfree (c);
5218 FRAME_X_IMAGE_CACHE (f) = NULL;
5223 /* Clear image cache of frame F. FORCE_P non-zero means free all
5224 images. FORCE_P zero means clear only images that haven't been
5225 displayed for some time. Should be called from time to time to
5226 reduce the number of loaded images. If image-eviction-seconds is
5227 non-nil, this frees images in the cache which weren't displayed for
5228 at least that many seconds. */
5230 void
5231 clear_image_cache (f, force_p)
5232 struct frame *f;
5233 int force_p;
5235 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5237 if (c && INTEGERP (Vimage_cache_eviction_delay))
5239 EMACS_TIME t;
5240 unsigned long old;
5241 int i, any_freed_p = 0;
5243 EMACS_GET_TIME (t);
5244 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5246 for (i = 0; i < c->used; ++i)
5248 struct image *img = c->images[i];
5249 if (img != NULL
5250 && (force_p
5251 || (img->timestamp > old)))
5253 free_image (f, img);
5254 any_freed_p = 1;
5258 /* We may be clearing the image cache because, for example,
5259 Emacs was iconified for a longer period of time. In that
5260 case, current matrices may still contain references to
5261 images freed above. So, clear these matrices. */
5262 if (any_freed_p)
5264 clear_current_matrices (f);
5265 ++windows_or_buffers_changed;
5271 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5272 0, 1, 0,
5273 doc: /* Clear the image cache of FRAME.
5274 FRAME nil or omitted means use the selected frame.
5275 FRAME t means clear the image caches of all frames. */)
5276 (frame)
5277 Lisp_Object frame;
5279 if (EQ (frame, Qt))
5281 Lisp_Object tail;
5283 FOR_EACH_FRAME (tail, frame)
5284 if (FRAME_MAC_P (XFRAME (frame)))
5285 clear_image_cache (XFRAME (frame), 1);
5287 else
5288 clear_image_cache (check_x_frame (frame), 1);
5290 return Qnil;
5294 /* Return the id of image with Lisp specification SPEC on frame F.
5295 SPEC must be a valid Lisp image specification (see valid_image_p). */
5298 lookup_image (f, spec)
5299 struct frame *f;
5300 Lisp_Object spec;
5302 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5303 struct image *img;
5304 int i;
5305 unsigned hash;
5306 struct gcpro gcpro1;
5307 EMACS_TIME now;
5309 /* F must be a window-system frame, and SPEC must be a valid image
5310 specification. */
5311 xassert (FRAME_WINDOW_P (f));
5312 xassert (valid_image_p (spec));
5314 GCPRO1 (spec);
5316 /* Look up SPEC in the hash table of the image cache. */
5317 hash = sxhash (spec, 0);
5318 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5320 for (img = c->buckets[i]; img; img = img->next)
5321 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5322 break;
5324 /* If not found, create a new image and cache it. */
5325 if (img == NULL)
5327 BLOCK_INPUT;
5328 img = make_image (spec, hash);
5329 cache_image (f, img);
5330 img->load_failed_p = img->type->load (f, img) == 0;
5331 xassert (!interrupt_input_blocked);
5333 /* If we can't load the image, and we don't have a width and
5334 height, use some arbitrary width and height so that we can
5335 draw a rectangle for it. */
5336 if (img->load_failed_p)
5338 Lisp_Object value;
5340 value = image_spec_value (spec, QCwidth, NULL);
5341 img->width = (INTEGERP (value)
5342 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5343 value = image_spec_value (spec, QCheight, NULL);
5344 img->height = (INTEGERP (value)
5345 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5347 else
5349 /* Handle image type independent image attributes
5350 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
5351 Lisp_Object ascent, margin, relief;
5353 ascent = image_spec_value (spec, QCascent, NULL);
5354 if (INTEGERP (ascent))
5355 img->ascent = XFASTINT (ascent);
5356 else if (EQ (ascent, Qcenter))
5357 img->ascent = CENTERED_IMAGE_ASCENT;
5359 margin = image_spec_value (spec, QCmargin, NULL);
5360 if (INTEGERP (margin) && XINT (margin) >= 0)
5361 img->vmargin = img->hmargin = XFASTINT (margin);
5362 else if (CONSP (margin) && INTEGERP (XCAR (margin))
5363 && INTEGERP (XCDR (margin)))
5365 if (XINT (XCAR (margin)) > 0)
5366 img->hmargin = XFASTINT (XCAR (margin));
5367 if (XINT (XCDR (margin)) > 0)
5368 img->vmargin = XFASTINT (XCDR (margin));
5371 relief = image_spec_value (spec, QCrelief, NULL);
5372 if (INTEGERP (relief))
5374 img->relief = XINT (relief);
5375 img->hmargin += abs (img->relief);
5376 img->vmargin += abs (img->relief);
5381 /* We're using IMG, so set its timestamp to `now'. */
5382 EMACS_GET_TIME (now);
5383 img->timestamp = EMACS_SECS (now);
5385 UNGCPRO;
5387 /* Value is the image id. */
5388 return img->id;
5392 /* Cache image IMG in the image cache of frame F. */
5394 static void
5395 cache_image (f, img)
5396 struct frame *f;
5397 struct image *img;
5399 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5400 int i;
5402 /* Find a free slot in c->images. */
5403 for (i = 0; i < c->used; ++i)
5404 if (c->images[i] == NULL)
5405 break;
5407 /* If no free slot found, maybe enlarge c->images. */
5408 if (i == c->used && c->used == c->size)
5410 c->size *= 2;
5411 c->images = (struct image **) xrealloc (c->images,
5412 c->size * sizeof *c->images);
5415 /* Add IMG to c->images, and assign IMG an id. */
5416 c->images[i] = img;
5417 img->id = i;
5418 if (i == c->used)
5419 ++c->used;
5421 /* Add IMG to the cache's hash table. */
5422 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5423 img->next = c->buckets[i];
5424 if (img->next)
5425 img->next->prev = img;
5426 img->prev = NULL;
5427 c->buckets[i] = img;
5431 /* Call FN on every image in the image cache of frame F. Used to mark
5432 Lisp Objects in the image cache. */
5434 void
5435 forall_images_in_image_cache (f, fn)
5436 struct frame *f;
5437 void (*fn) P_ ((struct image *img));
5439 if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
5441 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5442 if (c)
5444 int i;
5445 for (i = 0; i < c->used; ++i)
5446 if (c->images[i])
5447 fn (c->images[i]);
5454 /***********************************************************************
5455 Mac support code
5456 ***********************************************************************/
5458 #if 0 /* MAC_TODO: Mac specific image code. */
5460 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5461 XImage **, Pixmap *));
5462 static void x_destroy_x_image P_ ((XImage *));
5463 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5466 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5467 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5468 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5469 via xmalloc. Print error messages via image_error if an error
5470 occurs. Value is non-zero if successful. */
5472 static int
5473 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5474 struct frame *f;
5475 int width, height, depth;
5476 XImage **ximg;
5477 Pixmap *pixmap;
5479 #if 0 /* MAC_TODO: Image support for Mac */
5480 Display *display = FRAME_W32_DISPLAY (f);
5481 Screen *screen = FRAME_X_SCREEN (f);
5482 Window window = FRAME_W32_WINDOW (f);
5484 xassert (interrupt_input_blocked);
5486 if (depth <= 0)
5487 depth = DefaultDepthOfScreen (screen);
5488 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5489 depth, ZPixmap, 0, NULL, width, height,
5490 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5491 if (*ximg == NULL)
5493 image_error ("Unable to allocate X image", Qnil, Qnil);
5494 return 0;
5497 /* Allocate image raster. */
5498 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5500 /* Allocate a pixmap of the same size. */
5501 *pixmap = XCreatePixmap (display, window, width, height, depth);
5502 if (*pixmap == 0)
5504 x_destroy_x_image (*ximg);
5505 *ximg = NULL;
5506 image_error ("Unable to create X pixmap", Qnil, Qnil);
5507 return 0;
5509 #endif /* MAC_TODO */
5510 return 1;
5514 /* Destroy XImage XIMG. Free XIMG->data. */
5516 static void
5517 x_destroy_x_image (ximg)
5518 XImage *ximg;
5520 xassert (interrupt_input_blocked);
5521 if (ximg)
5523 xfree (ximg->data);
5524 ximg->data = NULL;
5525 XDestroyImage (ximg);
5530 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5531 are width and height of both the image and pixmap. */
5533 static void
5534 x_put_x_image (f, ximg, pixmap, width, height)
5535 struct frame *f;
5536 XImage *ximg;
5537 Pixmap pixmap;
5539 GC gc;
5541 xassert (interrupt_input_blocked);
5542 gc = XCreateGC (NULL, pixmap, 0, NULL);
5543 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5544 XFreeGC (NULL, gc);
5547 #endif /* MAC_TODO */
5550 /***********************************************************************
5551 Searching files
5552 ***********************************************************************/
5554 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5556 /* Find image file FILE. Look in data-directory, then
5557 x-bitmap-file-path. Value is the full name of the file found, or
5558 nil if not found. */
5560 static Lisp_Object
5561 x_find_image_file (file)
5562 Lisp_Object file;
5564 Lisp_Object file_found, search_path;
5565 struct gcpro gcpro1, gcpro2;
5566 int fd;
5568 file_found = Qnil;
5569 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5570 GCPRO2 (file_found, search_path);
5572 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5573 fd = openp (search_path, file, Qnil, &file_found, Qnil);
5575 if (fd < 0)
5576 file_found = Qnil;
5577 else
5578 close (fd);
5580 UNGCPRO;
5581 return file_found;
5585 /***********************************************************************
5586 XBM images
5587 ***********************************************************************/
5589 static int xbm_load P_ ((struct frame *f, struct image *img));
5590 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
5591 Lisp_Object file));
5592 static int xbm_image_p P_ ((Lisp_Object object));
5593 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
5594 unsigned char **));
5597 /* Indices of image specification fields in xbm_format, below. */
5599 enum xbm_keyword_index
5601 XBM_TYPE,
5602 XBM_FILE,
5603 XBM_WIDTH,
5604 XBM_HEIGHT,
5605 XBM_DATA,
5606 XBM_FOREGROUND,
5607 XBM_BACKGROUND,
5608 XBM_ASCENT,
5609 XBM_MARGIN,
5610 XBM_RELIEF,
5611 XBM_ALGORITHM,
5612 XBM_HEURISTIC_MASK,
5613 XBM_LAST
5616 /* Vector of image_keyword structures describing the format
5617 of valid XBM image specifications. */
5619 static struct image_keyword xbm_format[XBM_LAST] =
5621 {":type", IMAGE_SYMBOL_VALUE, 1},
5622 {":file", IMAGE_STRING_VALUE, 0},
5623 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5624 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5625 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5626 {":foreground", IMAGE_STRING_VALUE, 0},
5627 {":background", IMAGE_STRING_VALUE, 0},
5628 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
5629 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5630 {":relief", IMAGE_INTEGER_VALUE, 0},
5631 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5632 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5635 /* Structure describing the image type XBM. */
5637 static struct image_type xbm_type =
5639 &Qxbm,
5640 xbm_image_p,
5641 xbm_load,
5642 x_clear_image,
5643 NULL
5646 /* Tokens returned from xbm_scan. */
5648 enum xbm_token
5650 XBM_TK_IDENT = 256,
5651 XBM_TK_NUMBER
5655 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5656 A valid specification is a list starting with the symbol `image'
5657 The rest of the list is a property list which must contain an
5658 entry `:type xbm..
5660 If the specification specifies a file to load, it must contain
5661 an entry `:file FILENAME' where FILENAME is a string.
5663 If the specification is for a bitmap loaded from memory it must
5664 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5665 WIDTH and HEIGHT are integers > 0. DATA may be:
5667 1. a string large enough to hold the bitmap data, i.e. it must
5668 have a size >= (WIDTH + 7) / 8 * HEIGHT
5670 2. a bool-vector of size >= WIDTH * HEIGHT
5672 3. a vector of strings or bool-vectors, one for each line of the
5673 bitmap.
5675 Both the file and data forms may contain the additional entries
5676 `:background COLOR' and `:foreground COLOR'. If not present,
5677 foreground and background of the frame on which the image is
5678 displayed, is used. */
5680 static int
5681 xbm_image_p (object)
5682 Lisp_Object object;
5684 struct image_keyword kw[XBM_LAST];
5686 bcopy (xbm_format, kw, sizeof kw);
5687 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5688 return 0;
5690 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5692 if (kw[XBM_FILE].count)
5694 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5695 return 0;
5697 else
5699 Lisp_Object data;
5700 int width, height;
5702 /* Entries for `:width', `:height' and `:data' must be present. */
5703 if (!kw[XBM_WIDTH].count
5704 || !kw[XBM_HEIGHT].count
5705 || !kw[XBM_DATA].count)
5706 return 0;
5708 data = kw[XBM_DATA].value;
5709 width = XFASTINT (kw[XBM_WIDTH].value);
5710 height = XFASTINT (kw[XBM_HEIGHT].value);
5712 /* Check type of data, and width and height against contents of
5713 data. */
5714 if (VECTORP (data))
5716 int i;
5718 /* Number of elements of the vector must be >= height. */
5719 if (XVECTOR (data)->size < height)
5720 return 0;
5722 /* Each string or bool-vector in data must be large enough
5723 for one line of the image. */
5724 for (i = 0; i < height; ++i)
5726 Lisp_Object elt = XVECTOR (data)->contents[i];
5728 if (STRINGP (elt))
5730 if (XSTRING (elt)->size
5731 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
5732 return 0;
5734 else if (BOOL_VECTOR_P (elt))
5736 if (XBOOL_VECTOR (elt)->size < width)
5737 return 0;
5739 else
5740 return 0;
5743 else if (STRINGP (data))
5745 if (XSTRING (data)->size
5746 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
5747 return 0;
5749 else if (BOOL_VECTOR_P (data))
5751 if (XBOOL_VECTOR (data)->size < width * height)
5752 return 0;
5754 else
5755 return 0;
5758 /* Baseline must be a value between 0 and 100 (a percentage). */
5759 if (kw[XBM_ASCENT].count
5760 && XFASTINT (kw[XBM_ASCENT].value) > 100)
5761 return 0;
5763 return 1;
5767 /* Scan a bitmap file. FP is the stream to read from. Value is
5768 either an enumerator from enum xbm_token, or a character for a
5769 single-character token, or 0 at end of file. If scanning an
5770 identifier, store the lexeme of the identifier in SVAL. If
5771 scanning a number, store its value in *IVAL. */
5773 static int
5774 xbm_scan (fp, sval, ival)
5775 FILE *fp;
5776 char *sval;
5777 int *ival;
5779 int c;
5781 /* Skip white space. */
5782 while ((c = fgetc (fp)) != EOF && isspace (c))
5785 if (c == EOF)
5786 c = 0;
5787 else if (isdigit (c))
5789 int value = 0, digit;
5791 if (c == '0')
5793 c = fgetc (fp);
5794 if (c == 'x' || c == 'X')
5796 while ((c = fgetc (fp)) != EOF)
5798 if (isdigit (c))
5799 digit = c - '0';
5800 else if (c >= 'a' && c <= 'f')
5801 digit = c - 'a' + 10;
5802 else if (c >= 'A' && c <= 'F')
5803 digit = c - 'A' + 10;
5804 else
5805 break;
5806 value = 16 * value + digit;
5809 else if (isdigit (c))
5811 value = c - '0';
5812 while ((c = fgetc (fp)) != EOF
5813 && isdigit (c))
5814 value = 8 * value + c - '0';
5817 else
5819 value = c - '0';
5820 while ((c = fgetc (fp)) != EOF
5821 && isdigit (c))
5822 value = 10 * value + c - '0';
5825 if (c != EOF)
5826 ungetc (c, fp);
5827 *ival = value;
5828 c = XBM_TK_NUMBER;
5830 else if (isalpha (c) || c == '_')
5832 *sval++ = c;
5833 while ((c = fgetc (fp)) != EOF
5834 && (isalnum (c) || c == '_'))
5835 *sval++ = c;
5836 *sval = 0;
5837 if (c != EOF)
5838 ungetc (c, fp);
5839 c = XBM_TK_IDENT;
5842 return c;
5846 /* Replacement for XReadBitmapFileData which isn't available under old
5847 X versions. FILE is the name of the bitmap file to read. Set
5848 *WIDTH and *HEIGHT to the width and height of the image. Return in
5849 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
5850 successful. */
5852 static int
5853 xbm_read_bitmap_file_data (file, width, height, data)
5854 char *file;
5855 int *width, *height;
5856 unsigned char **data;
5858 FILE *fp;
5859 char buffer[BUFSIZ];
5860 int padding_p = 0;
5861 int v10 = 0;
5862 int bytes_per_line, i, nbytes;
5863 unsigned char *p;
5864 int value;
5865 int LA1;
5867 #define match() \
5868 LA1 = xbm_scan (fp, buffer, &value)
5870 #define expect(TOKEN) \
5871 if (LA1 != (TOKEN)) \
5872 goto failure; \
5873 else \
5874 match ()
5876 #define expect_ident(IDENT) \
5877 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5878 match (); \
5879 else \
5880 goto failure
5882 fp = fopen (file, "r");
5883 if (fp == NULL)
5884 return 0;
5886 *width = *height = -1;
5887 *data = NULL;
5888 LA1 = xbm_scan (fp, buffer, &value);
5890 /* Parse defines for width, height and hot-spots. */
5891 while (LA1 == '#')
5893 match ();
5894 expect_ident ("define");
5895 expect (XBM_TK_IDENT);
5897 if (LA1 == XBM_TK_NUMBER);
5899 char *p = strrchr (buffer, '_');
5900 p = p ? p + 1 : buffer;
5901 if (strcmp (p, "width") == 0)
5902 *width = value;
5903 else if (strcmp (p, "height") == 0)
5904 *height = value;
5906 expect (XBM_TK_NUMBER);
5909 if (*width < 0 || *height < 0)
5910 goto failure;
5912 /* Parse bits. Must start with `static'. */
5913 expect_ident ("static");
5914 if (LA1 == XBM_TK_IDENT)
5916 if (strcmp (buffer, "unsigned") == 0)
5918 match ();
5919 expect_ident ("char");
5921 else if (strcmp (buffer, "short") == 0)
5923 match ();
5924 v10 = 1;
5925 if (*width % 16 && *width % 16 < 9)
5926 padding_p = 1;
5928 else if (strcmp (buffer, "char") == 0)
5929 match ();
5930 else
5931 goto failure;
5933 else
5934 goto failure;
5936 expect (XBM_TK_IDENT);
5937 expect ('[');
5938 expect (']');
5939 expect ('=');
5940 expect ('{');
5942 bytes_per_line = (*width + 7) / 8 + padding_p;
5943 nbytes = bytes_per_line * *height;
5944 p = *data = (char *) xmalloc (nbytes);
5946 if (v10)
5949 for (i = 0; i < nbytes; i += 2)
5951 int val = value;
5952 expect (XBM_TK_NUMBER);
5954 *p++ = val;
5955 if (!padding_p || ((i + 2) % bytes_per_line))
5956 *p++ = value >> 8;
5958 if (LA1 == ',' || LA1 == '}')
5959 match ();
5960 else
5961 goto failure;
5964 else
5966 for (i = 0; i < nbytes; ++i)
5968 int val = value;
5969 expect (XBM_TK_NUMBER);
5971 *p++ = val;
5973 if (LA1 == ',' || LA1 == '}')
5974 match ();
5975 else
5976 goto failure;
5980 fclose (fp);
5981 return 1;
5983 failure:
5985 fclose (fp);
5986 if (*data)
5988 xfree (*data);
5989 *data = NULL;
5991 return 0;
5993 #undef match
5994 #undef expect
5995 #undef expect_ident
5999 /* Load XBM image IMG which will be displayed on frame F from file
6000 SPECIFIED_FILE. Value is non-zero if successful. */
6002 static int
6003 xbm_load_image_from_file (f, img, specified_file)
6004 struct frame *f;
6005 struct image *img;
6006 Lisp_Object specified_file;
6008 int rc;
6009 unsigned char *data;
6010 int success_p = 0;
6011 Lisp_Object file;
6012 struct gcpro gcpro1;
6014 xassert (STRINGP (specified_file));
6015 file = Qnil;
6016 GCPRO1 (file);
6018 file = x_find_image_file (specified_file);
6019 if (!STRINGP (file))
6021 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6022 UNGCPRO;
6023 return 0;
6026 rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
6027 &img->height, &data);
6028 if (rc)
6030 int depth = one_mac_display_info.n_cbits;
6031 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6032 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6033 Lisp_Object value;
6035 xassert (img->width > 0 && img->height > 0);
6037 /* Get foreground and background colors, maybe allocate colors. */
6038 value = image_spec_value (img->spec, QCforeground, NULL);
6039 if (!NILP (value))
6040 foreground = x_alloc_image_color (f, img, value, foreground);
6042 value = image_spec_value (img->spec, QCbackground, NULL);
6043 if (!NILP (value))
6044 background = x_alloc_image_color (f, img, value, background);
6046 #if 0 /* MAC_TODO : Port image display to Mac */
6047 BLOCK_INPUT;
6048 img->pixmap
6049 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
6050 FRAME_W32_WINDOW (f),
6051 data,
6052 img->width, img->height,
6053 foreground, background,
6054 depth);
6055 xfree (data);
6057 if (img->pixmap == 0)
6059 x_clear_image (f, img);
6060 image_error ("Unable to create X pixmap for `%s'", file, Qnil);
6062 else
6063 success_p = 1;
6065 UNBLOCK_INPUT;
6066 #endif /* MAC_TODO */
6068 else
6069 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6071 UNGCPRO;
6072 return success_p;
6076 /* Fill image IMG which is used on frame F with pixmap data. Value is
6077 non-zero if successful. */
6079 static int
6080 xbm_load (f, img)
6081 struct frame *f;
6082 struct image *img;
6084 int success_p = 0;
6085 Lisp_Object file_name;
6087 xassert (xbm_image_p (img->spec));
6089 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6090 file_name = image_spec_value (img->spec, QCfile, NULL);
6091 if (STRINGP (file_name))
6092 success_p = xbm_load_image_from_file (f, img, file_name);
6093 else
6095 struct image_keyword fmt[XBM_LAST];
6096 Lisp_Object data;
6097 int depth;
6098 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6099 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6100 char *bits;
6101 int parsed_p;
6103 /* Parse the list specification. */
6104 bcopy (xbm_format, fmt, sizeof fmt);
6105 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6106 xassert (parsed_p);
6108 /* Get specified width, and height. */
6109 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6110 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6111 xassert (img->width > 0 && img->height > 0);
6113 BLOCK_INPUT;
6115 if (fmt[XBM_ASCENT].count)
6116 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
6118 /* Get foreground and background colors, maybe allocate colors. */
6119 if (fmt[XBM_FOREGROUND].count)
6120 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6121 foreground);
6122 if (fmt[XBM_BACKGROUND].count)
6123 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6124 background);
6126 /* Set bits to the bitmap image data. */
6127 data = fmt[XBM_DATA].value;
6128 if (VECTORP (data))
6130 int i;
6131 char *p;
6132 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6134 p = bits = (char *) alloca (nbytes * img->height);
6135 for (i = 0; i < img->height; ++i, p += nbytes)
6137 Lisp_Object line = XVECTOR (data)->contents[i];
6138 if (STRINGP (line))
6139 bcopy (XSTRING (line)->data, p, nbytes);
6140 else
6141 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6144 else if (STRINGP (data))
6145 bits = XSTRING (data)->data;
6146 else
6147 bits = XBOOL_VECTOR (data)->data;
6149 #if 0 /* MAC_TODO : port Mac display code */
6150 /* Create the pixmap. */
6151 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6152 img->pixmap
6153 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
6154 FRAME_W32_WINDOW (f),
6155 bits,
6156 img->width, img->height,
6157 foreground, background,
6158 depth);
6159 #endif /* MAC_TODO */
6161 if (img->pixmap)
6162 success_p = 1;
6163 else
6165 image_error ("Unable to create pixmap for XBM image `%s'",
6166 img->spec, Qnil);
6167 x_clear_image (f, img);
6170 UNBLOCK_INPUT;
6173 return success_p;
6178 /***********************************************************************
6179 XPM images
6180 ***********************************************************************/
6182 #if HAVE_XPM
6184 static int xpm_image_p P_ ((Lisp_Object object));
6185 static int xpm_load P_ ((struct frame *f, struct image *img));
6186 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6188 #include "X11/xpm.h"
6190 /* The symbol `xpm' identifying XPM-format images. */
6192 Lisp_Object Qxpm;
6194 /* Indices of image specification fields in xpm_format, below. */
6196 enum xpm_keyword_index
6198 XPM_TYPE,
6199 XPM_FILE,
6200 XPM_DATA,
6201 XPM_ASCENT,
6202 XPM_MARGIN,
6203 XPM_RELIEF,
6204 XPM_ALGORITHM,
6205 XPM_HEURISTIC_MASK,
6206 XPM_COLOR_SYMBOLS,
6207 XPM_LAST
6210 /* Vector of image_keyword structures describing the format
6211 of valid XPM image specifications. */
6213 static struct image_keyword xpm_format[XPM_LAST] =
6215 {":type", IMAGE_SYMBOL_VALUE, 1},
6216 {":file", IMAGE_STRING_VALUE, 0},
6217 {":data", IMAGE_STRING_VALUE, 0},
6218 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6219 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6220 {":relief", IMAGE_INTEGER_VALUE, 0},
6221 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6222 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6223 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6226 /* Structure describing the image type XBM. */
6228 static struct image_type xpm_type =
6230 &Qxpm,
6231 xpm_image_p,
6232 xpm_load,
6233 x_clear_image,
6234 NULL
6238 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6239 for XPM images. Such a list must consist of conses whose car and
6240 cdr are strings. */
6242 static int
6243 xpm_valid_color_symbols_p (color_symbols)
6244 Lisp_Object color_symbols;
6246 while (CONSP (color_symbols))
6248 Lisp_Object sym = XCAR (color_symbols);
6249 if (!CONSP (sym)
6250 || !STRINGP (XCAR (sym))
6251 || !STRINGP (XCDR (sym)))
6252 break;
6253 color_symbols = XCDR (color_symbols);
6256 return NILP (color_symbols);
6260 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6262 static int
6263 xpm_image_p (object)
6264 Lisp_Object object;
6266 struct image_keyword fmt[XPM_LAST];
6267 bcopy (xpm_format, fmt, sizeof fmt);
6268 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6269 /* Either `:file' or `:data' must be present. */
6270 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6271 /* Either no `:color-symbols' or it's a list of conses
6272 whose car and cdr are strings. */
6273 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6274 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
6275 && (fmt[XPM_ASCENT].count == 0
6276 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
6280 /* Load image IMG which will be displayed on frame F. Value is
6281 non-zero if successful. */
6283 static int
6284 xpm_load (f, img)
6285 struct frame *f;
6286 struct image *img;
6288 int rc, i;
6289 XpmAttributes attrs;
6290 Lisp_Object specified_file, color_symbols;
6292 /* Configure the XPM lib. Use the visual of frame F. Allocate
6293 close colors. Return colors allocated. */
6294 bzero (&attrs, sizeof attrs);
6295 attrs.visual = FRAME_X_VISUAL (f);
6296 attrs.colormap = FRAME_X_COLORMAP (f);
6297 attrs.valuemask |= XpmVisual;
6298 attrs.valuemask |= XpmColormap;
6299 attrs.valuemask |= XpmReturnAllocPixels;
6300 #ifdef XpmAllocCloseColors
6301 attrs.alloc_close_colors = 1;
6302 attrs.valuemask |= XpmAllocCloseColors;
6303 #else
6304 attrs.closeness = 600;
6305 attrs.valuemask |= XpmCloseness;
6306 #endif
6308 /* If image specification contains symbolic color definitions, add
6309 these to `attrs'. */
6310 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6311 if (CONSP (color_symbols))
6313 Lisp_Object tail;
6314 XpmColorSymbol *xpm_syms;
6315 int i, size;
6317 attrs.valuemask |= XpmColorSymbols;
6319 /* Count number of symbols. */
6320 attrs.numsymbols = 0;
6321 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6322 ++attrs.numsymbols;
6324 /* Allocate an XpmColorSymbol array. */
6325 size = attrs.numsymbols * sizeof *xpm_syms;
6326 xpm_syms = (XpmColorSymbol *) alloca (size);
6327 bzero (xpm_syms, size);
6328 attrs.colorsymbols = xpm_syms;
6330 /* Fill the color symbol array. */
6331 for (tail = color_symbols, i = 0;
6332 CONSP (tail);
6333 ++i, tail = XCDR (tail))
6335 Lisp_Object name = XCAR (XCAR (tail));
6336 Lisp_Object color = XCDR (XCAR (tail));
6337 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
6338 strcpy (xpm_syms[i].name, XSTRING (name)->data);
6339 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
6340 strcpy (xpm_syms[i].value, XSTRING (color)->data);
6344 /* Create a pixmap for the image, either from a file, or from a
6345 string buffer containing data in the same format as an XPM file. */
6346 BLOCK_INPUT;
6347 specified_file = image_spec_value (img->spec, QCfile, NULL);
6348 if (STRINGP (specified_file))
6350 Lisp_Object file = x_find_image_file (specified_file);
6351 if (!STRINGP (file))
6353 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6354 UNBLOCK_INPUT;
6355 return 0;
6358 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
6359 XSTRING (file)->data, &img->pixmap, &img->mask,
6360 &attrs);
6362 else
6364 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6365 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
6366 XSTRING (buffer)->data,
6367 &img->pixmap, &img->mask,
6368 &attrs);
6370 UNBLOCK_INPUT;
6372 if (rc == XpmSuccess)
6374 /* Remember allocated colors. */
6375 img->ncolors = attrs.nalloc_pixels;
6376 img->colors = (unsigned long *) xmalloc (img->ncolors
6377 * sizeof *img->colors);
6378 for (i = 0; i < attrs.nalloc_pixels; ++i)
6379 img->colors[i] = attrs.alloc_pixels[i];
6381 img->width = attrs.width;
6382 img->height = attrs.height;
6383 xassert (img->width > 0 && img->height > 0);
6385 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6386 BLOCK_INPUT;
6387 XpmFreeAttributes (&attrs);
6388 UNBLOCK_INPUT;
6390 else
6392 switch (rc)
6394 case XpmOpenFailed:
6395 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6396 break;
6398 case XpmFileInvalid:
6399 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6400 break;
6402 case XpmNoMemory:
6403 image_error ("Out of memory (%s)", img->spec, Qnil);
6404 break;
6406 case XpmColorFailed:
6407 image_error ("Color allocation error (%s)", img->spec, Qnil);
6408 break;
6410 default:
6411 image_error ("Unknown error (%s)", img->spec, Qnil);
6412 break;
6416 return rc == XpmSuccess;
6419 #endif /* HAVE_XPM != 0 */
6422 #if 0 /* MAC_TODO : Color tables on Mac. */
6423 /***********************************************************************
6424 Color table
6425 ***********************************************************************/
6427 /* An entry in the color table mapping an RGB color to a pixel color. */
6429 struct ct_color
6431 int r, g, b;
6432 unsigned long pixel;
6434 /* Next in color table collision list. */
6435 struct ct_color *next;
6438 /* The bucket vector size to use. Must be prime. */
6440 #define CT_SIZE 101
6442 /* Value is a hash of the RGB color given by R, G, and B. */
6444 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6446 /* The color hash table. */
6448 struct ct_color **ct_table;
6450 /* Number of entries in the color table. */
6452 int ct_colors_allocated;
6454 /* Function prototypes. */
6456 static void init_color_table P_ ((void));
6457 static void free_color_table P_ ((void));
6458 static unsigned long *colors_in_color_table P_ ((int *n));
6459 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
6460 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
6463 /* Initialize the color table. */
6465 static void
6466 init_color_table ()
6468 int size = CT_SIZE * sizeof (*ct_table);
6469 ct_table = (struct ct_color **) xmalloc (size);
6470 bzero (ct_table, size);
6471 ct_colors_allocated = 0;
6475 /* Free memory associated with the color table. */
6477 static void
6478 free_color_table ()
6480 int i;
6481 struct ct_color *p, *next;
6483 for (i = 0; i < CT_SIZE; ++i)
6484 for (p = ct_table[i]; p; p = next)
6486 next = p->next;
6487 xfree (p);
6490 xfree (ct_table);
6491 ct_table = NULL;
6495 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6496 entry for that color already is in the color table, return the
6497 pixel color of that entry. Otherwise, allocate a new color for R,
6498 G, B, and make an entry in the color table. */
6500 static unsigned long
6501 lookup_rgb_color (f, r, g, b)
6502 struct frame *f;
6503 int r, g, b;
6505 unsigned hash = CT_HASH_RGB (r, g, b);
6506 int i = hash % CT_SIZE;
6507 struct ct_color *p;
6509 for (p = ct_table[i]; p; p = p->next)
6510 if (p->r == r && p->g == g && p->b == b)
6511 break;
6513 if (p == NULL)
6515 COLORREF color;
6516 Colormap cmap;
6517 int rc;
6519 color = RGB_TO_ULONG (r, g, b);
6521 ++ct_colors_allocated;
6523 p = (struct ct_color *) xmalloc (sizeof *p);
6524 p->r = r;
6525 p->g = g;
6526 p->b = b;
6527 p->pixel = color;
6528 p->next = ct_table[i];
6529 ct_table[i] = p;
6532 return p->pixel;
6536 /* Look up pixel color PIXEL which is used on frame F in the color
6537 table. If not already present, allocate it. Value is PIXEL. */
6539 static unsigned long
6540 lookup_pixel_color (f, pixel)
6541 struct frame *f;
6542 unsigned long pixel;
6544 int i = pixel % CT_SIZE;
6545 struct ct_color *p;
6547 for (p = ct_table[i]; p; p = p->next)
6548 if (p->pixel == pixel)
6549 break;
6551 if (p == NULL)
6553 XColor color;
6554 Colormap cmap;
6555 int rc;
6557 BLOCK_INPUT;
6559 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6560 color.pixel = pixel;
6561 XQueryColor (NULL, cmap, &color);
6562 rc = x_alloc_nearest_color (f, cmap, &color);
6563 UNBLOCK_INPUT;
6565 if (rc)
6567 ++ct_colors_allocated;
6569 p = (struct ct_color *) xmalloc (sizeof *p);
6570 p->r = color.red;
6571 p->g = color.green;
6572 p->b = color.blue;
6573 p->pixel = pixel;
6574 p->next = ct_table[i];
6575 ct_table[i] = p;
6577 else
6578 return FRAME_FOREGROUND_PIXEL (f);
6580 return p->pixel;
6584 /* Value is a vector of all pixel colors contained in the color table,
6585 allocated via xmalloc. Set *N to the number of colors. */
6587 static unsigned long *
6588 colors_in_color_table (n)
6589 int *n;
6591 int i, j;
6592 struct ct_color *p;
6593 unsigned long *colors;
6595 if (ct_colors_allocated == 0)
6597 *n = 0;
6598 colors = NULL;
6600 else
6602 colors = (unsigned long *) xmalloc (ct_colors_allocated
6603 * sizeof *colors);
6604 *n = ct_colors_allocated;
6606 for (i = j = 0; i < CT_SIZE; ++i)
6607 for (p = ct_table[i]; p; p = p->next)
6608 colors[j++] = p->pixel;
6611 return colors;
6614 #endif /* MAC_TODO */
6617 /***********************************************************************
6618 Algorithms
6619 ***********************************************************************/
6621 #if 0 /* MAC_TODO : Mac versions of low level algorithms */
6622 static void x_laplace_write_row P_ ((struct frame *, long *,
6623 int, XImage *, int));
6624 static void x_laplace_read_row P_ ((struct frame *, Colormap,
6625 XColor *, int, XImage *, int));
6628 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
6629 frame we operate on, CMAP is the color-map in effect, and WIDTH is
6630 the width of one row in the image. */
6632 static void
6633 x_laplace_read_row (f, cmap, colors, width, ximg, y)
6634 struct frame *f;
6635 Colormap cmap;
6636 XColor *colors;
6637 int width;
6638 XImage *ximg;
6639 int y;
6641 int x;
6643 for (x = 0; x < width; ++x)
6644 colors[x].pixel = XGetPixel (ximg, x, y);
6646 XQueryColors (NULL, cmap, colors, width);
6650 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
6651 containing the pixel colors to write. F is the frame we are
6652 working on. */
6654 static void
6655 x_laplace_write_row (f, pixels, width, ximg, y)
6656 struct frame *f;
6657 long *pixels;
6658 int width;
6659 XImage *ximg;
6660 int y;
6662 int x;
6664 for (x = 0; x < width; ++x)
6665 XPutPixel (ximg, x, y, pixels[x]);
6667 #endif /* MAC_TODO */
6669 /* Transform image IMG which is used on frame F with a Laplace
6670 edge-detection algorithm. The result is an image that can be used
6671 to draw disabled buttons, for example. */
6673 static void
6674 x_laplace (f, img)
6675 struct frame *f;
6676 struct image *img;
6678 #if 0 /* MAC_TODO : Mac version */
6679 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6680 XImage *ximg, *oimg;
6681 XColor *in[3];
6682 long *out;
6683 Pixmap pixmap;
6684 int x, y, i;
6685 long pixel;
6686 int in_y, out_y, rc;
6687 int mv2 = 45000;
6689 BLOCK_INPUT;
6691 /* Get the X image IMG->pixmap. */
6692 ximg = XGetImage (NULL, img->pixmap,
6693 0, 0, img->width, img->height, ~0, ZPixmap);
6695 /* Allocate 3 input rows, and one output row of colors. */
6696 for (i = 0; i < 3; ++i)
6697 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
6698 out = (long *) alloca (img->width * sizeof (long));
6700 /* Create an X image for output. */
6701 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
6702 &oimg, &pixmap);
6704 /* Fill first two rows. */
6705 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
6706 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
6707 in_y = 2;
6709 /* Write first row, all zeros. */
6710 init_color_table ();
6711 pixel = lookup_rgb_color (f, 0, 0, 0);
6712 for (x = 0; x < img->width; ++x)
6713 out[x] = pixel;
6714 x_laplace_write_row (f, out, img->width, oimg, 0);
6715 out_y = 1;
6717 for (y = 2; y < img->height; ++y)
6719 int rowa = y % 3;
6720 int rowb = (y + 2) % 3;
6722 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
6724 for (x = 0; x < img->width - 2; ++x)
6726 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
6727 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
6728 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
6730 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
6731 b & 0xffff);
6734 x_laplace_write_row (f, out, img->width, oimg, out_y++);
6737 /* Write last line, all zeros. */
6738 for (x = 0; x < img->width; ++x)
6739 out[x] = pixel;
6740 x_laplace_write_row (f, out, img->width, oimg, out_y);
6742 /* Free the input image, and free resources of IMG. */
6743 XDestroyImage (ximg);
6744 x_clear_image (f, img);
6746 /* Put the output image into pixmap, and destroy it. */
6747 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6748 x_destroy_x_image (oimg);
6750 /* Remember new pixmap and colors in IMG. */
6751 img->pixmap = pixmap;
6752 img->colors = colors_in_color_table (&img->ncolors);
6753 free_color_table ();
6755 UNBLOCK_INPUT;
6756 #endif /* MAC_TODO */
6760 /* Build a mask for image IMG which is used on frame F. FILE is the
6761 name of an image file, for error messages. HOW determines how to
6762 determine the background color of IMG. If it is a list '(R G B)',
6763 with R, G, and B being integers >= 0, take that as the color of the
6764 background. Otherwise, determine the background color of IMG
6765 heuristically. Value is non-zero if successful. */
6767 static int
6768 x_build_heuristic_mask (f, img, how)
6769 struct frame *f;
6770 struct image *img;
6771 Lisp_Object how;
6773 #if 0 /* MAC_TODO : Mac version */
6774 Display *dpy = FRAME_W32_DISPLAY (f);
6775 XImage *ximg, *mask_img;
6776 int x, y, rc, look_at_corners_p;
6777 unsigned long bg;
6779 BLOCK_INPUT;
6781 /* Create an image and pixmap serving as mask. */
6782 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
6783 &mask_img, &img->mask);
6784 if (!rc)
6786 UNBLOCK_INPUT;
6787 return 0;
6790 /* Get the X image of IMG->pixmap. */
6791 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
6792 ~0, ZPixmap);
6794 /* Determine the background color of ximg. If HOW is `(R G B)'
6795 take that as color. Otherwise, try to determine the color
6796 heuristically. */
6797 look_at_corners_p = 1;
6799 if (CONSP (how))
6801 int rgb[3], i = 0;
6803 while (i < 3
6804 && CONSP (how)
6805 && NATNUMP (XCAR (how)))
6807 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
6808 how = XCDR (how);
6811 if (i == 3 && NILP (how))
6813 char color_name[30];
6814 XColor exact, color;
6815 Colormap cmap;
6817 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
6819 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6820 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
6822 bg = color.pixel;
6823 look_at_corners_p = 0;
6828 if (look_at_corners_p)
6830 unsigned long corners[4];
6831 int i, best_count;
6833 /* Get the colors at the corners of ximg. */
6834 corners[0] = XGetPixel (ximg, 0, 0);
6835 corners[1] = XGetPixel (ximg, img->width - 1, 0);
6836 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
6837 corners[3] = XGetPixel (ximg, 0, img->height - 1);
6839 /* Choose the most frequently found color as background. */
6840 for (i = best_count = 0; i < 4; ++i)
6842 int j, n;
6844 for (j = n = 0; j < 4; ++j)
6845 if (corners[i] == corners[j])
6846 ++n;
6848 if (n > best_count)
6849 bg = corners[i], best_count = n;
6853 /* Set all bits in mask_img to 1 whose color in ximg is different
6854 from the background color bg. */
6855 for (y = 0; y < img->height; ++y)
6856 for (x = 0; x < img->width; ++x)
6857 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
6859 /* Put mask_img into img->mask. */
6860 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6861 x_destroy_x_image (mask_img);
6862 XDestroyImage (ximg);
6864 UNBLOCK_INPUT;
6865 #endif /* MAC_TODO */
6867 return 1;
6872 /***********************************************************************
6873 PBM (mono, gray, color)
6874 ***********************************************************************/
6875 #ifdef HAVE_PBM
6877 static int pbm_image_p P_ ((Lisp_Object object));
6878 static int pbm_load P_ ((struct frame *f, struct image *img));
6879 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
6881 /* The symbol `pbm' identifying images of this type. */
6883 Lisp_Object Qpbm;
6885 /* Indices of image specification fields in gs_format, below. */
6887 enum pbm_keyword_index
6889 PBM_TYPE,
6890 PBM_FILE,
6891 PBM_DATA,
6892 PBM_ASCENT,
6893 PBM_MARGIN,
6894 PBM_RELIEF,
6895 PBM_ALGORITHM,
6896 PBM_HEURISTIC_MASK,
6897 PBM_LAST
6900 /* Vector of image_keyword structures describing the format
6901 of valid user-defined image specifications. */
6903 static struct image_keyword pbm_format[PBM_LAST] =
6905 {":type", IMAGE_SYMBOL_VALUE, 1},
6906 {":file", IMAGE_STRING_VALUE, 0},
6907 {":data", IMAGE_STRING_VALUE, 0},
6908 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6909 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6910 {":relief", IMAGE_INTEGER_VALUE, 0},
6911 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6912 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6915 /* Structure describing the image type `pbm'. */
6917 static struct image_type pbm_type =
6919 &Qpbm,
6920 pbm_image_p,
6921 pbm_load,
6922 x_clear_image,
6923 NULL
6927 /* Return non-zero if OBJECT is a valid PBM image specification. */
6929 static int
6930 pbm_image_p (object)
6931 Lisp_Object object;
6933 struct image_keyword fmt[PBM_LAST];
6935 bcopy (pbm_format, fmt, sizeof fmt);
6937 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
6938 || (fmt[PBM_ASCENT].count
6939 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
6940 return 0;
6942 /* Must specify either :data or :file. */
6943 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
6947 /* Scan a decimal number from *S and return it. Advance *S while
6948 reading the number. END is the end of the string. Value is -1 at
6949 end of input. */
6951 static int
6952 pbm_scan_number (s, end)
6953 unsigned char **s, *end;
6955 int c, val = -1;
6957 while (*s < end)
6959 /* Skip white-space. */
6960 while (*s < end && (c = *(*s)++, isspace (c)))
6963 if (c == '#')
6965 /* Skip comment to end of line. */
6966 while (*s < end && (c = *(*s)++, c != '\n'))
6969 else if (isdigit (c))
6971 /* Read decimal number. */
6972 val = c - '0';
6973 while (*s < end && (c = *(*s)++, isdigit (c)))
6974 val = 10 * val + c - '0';
6975 break;
6977 else
6978 break;
6981 return val;
6985 /* Read FILE into memory. Value is a pointer to a buffer allocated
6986 with xmalloc holding FILE's contents. Value is null if an error
6987 occured. *SIZE is set to the size of the file. */
6989 static char *
6990 pbm_read_file (file, size)
6991 Lisp_Object file;
6992 int *size;
6994 FILE *fp = NULL;
6995 char *buf = NULL;
6996 struct stat st;
6998 if (stat (XSTRING (file)->data, &st) == 0
6999 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
7000 && (buf = (char *) xmalloc (st.st_size),
7001 fread (buf, 1, st.st_size, fp) == st.st_size))
7003 *size = st.st_size;
7004 fclose (fp);
7006 else
7008 if (fp)
7009 fclose (fp);
7010 if (buf)
7012 xfree (buf);
7013 buf = NULL;
7017 return buf;
7021 /* Load PBM image IMG for use on frame F. */
7023 static int
7024 pbm_load (f, img)
7025 struct frame *f;
7026 struct image *img;
7028 int raw_p, x, y;
7029 int width, height, max_color_idx = 0;
7030 XImage *ximg;
7031 Lisp_Object file, specified_file;
7032 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7033 struct gcpro gcpro1;
7034 unsigned char *contents = NULL;
7035 unsigned char *end, *p;
7036 int size;
7038 specified_file = image_spec_value (img->spec, QCfile, NULL);
7039 file = Qnil;
7040 GCPRO1 (file);
7042 if (STRINGP (specified_file))
7044 file = x_find_image_file (specified_file);
7045 if (!STRINGP (file))
7047 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7048 UNGCPRO;
7049 return 0;
7052 contents = pbm_read_file (file, &size);
7053 if (contents == NULL)
7055 image_error ("Error reading `%s'", file, Qnil);
7056 UNGCPRO;
7057 return 0;
7060 p = contents;
7061 end = contents + size;
7063 else
7065 Lisp_Object data;
7066 data = image_spec_value (img->spec, QCdata, NULL);
7067 p = XSTRING (data)->data;
7068 end = p + STRING_BYTES (XSTRING (data));
7071 /* Check magic number. */
7072 if (end - p < 2 || *p++ != 'P')
7074 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7075 error:
7076 xfree (contents);
7077 UNGCPRO;
7078 return 0;
7081 switch (*p++)
7083 case '1':
7084 raw_p = 0, type = PBM_MONO;
7085 break;
7087 case '2':
7088 raw_p = 0, type = PBM_GRAY;
7089 break;
7091 case '3':
7092 raw_p = 0, type = PBM_COLOR;
7093 break;
7095 case '4':
7096 raw_p = 1, type = PBM_MONO;
7097 break;
7099 case '5':
7100 raw_p = 1, type = PBM_GRAY;
7101 break;
7103 case '6':
7104 raw_p = 1, type = PBM_COLOR;
7105 break;
7107 default:
7108 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7109 goto error;
7112 /* Read width, height, maximum color-component. Characters
7113 starting with `#' up to the end of a line are ignored. */
7114 width = pbm_scan_number (&p, end);
7115 height = pbm_scan_number (&p, end);
7117 if (type != PBM_MONO)
7119 max_color_idx = pbm_scan_number (&p, end);
7120 if (raw_p && max_color_idx > 255)
7121 max_color_idx = 255;
7124 if (width < 0
7125 || height < 0
7126 || (type != PBM_MONO && max_color_idx < 0))
7127 goto error;
7129 BLOCK_INPUT;
7130 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7131 &ximg, &img->pixmap))
7133 UNBLOCK_INPUT;
7134 goto error;
7137 /* Initialize the color hash table. */
7138 init_color_table ();
7140 if (type == PBM_MONO)
7142 int c = 0, g;
7144 for (y = 0; y < height; ++y)
7145 for (x = 0; x < width; ++x)
7147 if (raw_p)
7149 if ((x & 7) == 0)
7150 c = *p++;
7151 g = c & 0x80;
7152 c <<= 1;
7154 else
7155 g = pbm_scan_number (&p, end);
7157 XPutPixel (ximg, x, y, (g
7158 ? FRAME_FOREGROUND_PIXEL (f)
7159 : FRAME_BACKGROUND_PIXEL (f)));
7162 else
7164 for (y = 0; y < height; ++y)
7165 for (x = 0; x < width; ++x)
7167 int r, g, b;
7169 if (type == PBM_GRAY)
7170 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7171 else if (raw_p)
7173 r = *p++;
7174 g = *p++;
7175 b = *p++;
7177 else
7179 r = pbm_scan_number (&p, end);
7180 g = pbm_scan_number (&p, end);
7181 b = pbm_scan_number (&p, end);
7184 if (r < 0 || g < 0 || b < 0)
7186 xfree (ximg->data);
7187 ximg->data = NULL;
7188 XDestroyImage (ximg);
7189 UNBLOCK_INPUT;
7190 image_error ("Invalid pixel value in image `%s'",
7191 img->spec, Qnil);
7192 goto error;
7195 /* RGB values are now in the range 0..max_color_idx.
7196 Scale this to the range 0..0xffff supported by X. */
7197 r = (double) r * 65535 / max_color_idx;
7198 g = (double) g * 65535 / max_color_idx;
7199 b = (double) b * 65535 / max_color_idx;
7200 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7204 /* Store in IMG->colors the colors allocated for the image, and
7205 free the color table. */
7206 img->colors = colors_in_color_table (&img->ncolors);
7207 free_color_table ();
7209 /* Put the image into a pixmap. */
7210 x_put_x_image (f, ximg, img->pixmap, width, height);
7211 x_destroy_x_image (ximg);
7212 UNBLOCK_INPUT;
7214 img->width = width;
7215 img->height = height;
7217 UNGCPRO;
7218 xfree (contents);
7219 return 1;
7221 #endif /* HAVE_PBM */
7224 /***********************************************************************
7226 ***********************************************************************/
7228 #if HAVE_PNG
7230 #include <png.h>
7232 /* Function prototypes. */
7234 static int png_image_p P_ ((Lisp_Object object));
7235 static int png_load P_ ((struct frame *f, struct image *img));
7237 /* The symbol `png' identifying images of this type. */
7239 Lisp_Object Qpng;
7241 /* Indices of image specification fields in png_format, below. */
7243 enum png_keyword_index
7245 PNG_TYPE,
7246 PNG_DATA,
7247 PNG_FILE,
7248 PNG_ASCENT,
7249 PNG_MARGIN,
7250 PNG_RELIEF,
7251 PNG_ALGORITHM,
7252 PNG_HEURISTIC_MASK,
7253 PNG_LAST
7256 /* Vector of image_keyword structures describing the format
7257 of valid user-defined image specifications. */
7259 static struct image_keyword png_format[PNG_LAST] =
7261 {":type", IMAGE_SYMBOL_VALUE, 1},
7262 {":data", IMAGE_STRING_VALUE, 0},
7263 {":file", IMAGE_STRING_VALUE, 0},
7264 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7265 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7266 {":relief", IMAGE_INTEGER_VALUE, 0},
7267 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7268 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7271 /* Structure describing the image type `png'. */
7273 static struct image_type png_type =
7275 &Qpng,
7276 png_image_p,
7277 png_load,
7278 x_clear_image,
7279 NULL
7283 /* Return non-zero if OBJECT is a valid PNG image specification. */
7285 static int
7286 png_image_p (object)
7287 Lisp_Object object;
7289 struct image_keyword fmt[PNG_LAST];
7290 bcopy (png_format, fmt, sizeof fmt);
7292 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
7293 || (fmt[PNG_ASCENT].count
7294 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
7295 return 0;
7297 /* Must specify either the :data or :file keyword. */
7298 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7302 /* Error and warning handlers installed when the PNG library
7303 is initialized. */
7305 static void
7306 my_png_error (png_ptr, msg)
7307 png_struct *png_ptr;
7308 char *msg;
7310 xassert (png_ptr != NULL);
7311 image_error ("PNG error: %s", build_string (msg), Qnil);
7312 longjmp (png_ptr->jmpbuf, 1);
7316 static void
7317 my_png_warning (png_ptr, msg)
7318 png_struct *png_ptr;
7319 char *msg;
7321 xassert (png_ptr != NULL);
7322 image_error ("PNG warning: %s", build_string (msg), Qnil);
7325 /* Memory source for PNG decoding. */
7327 struct png_memory_storage
7329 unsigned char *bytes; /* The data */
7330 size_t len; /* How big is it? */
7331 int index; /* Where are we? */
7335 /* Function set as reader function when reading PNG image from memory.
7336 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7337 bytes from the input to DATA. */
7339 static void
7340 png_read_from_memory (png_ptr, data, length)
7341 png_structp png_ptr;
7342 png_bytep data;
7343 png_size_t length;
7345 struct png_memory_storage *tbr
7346 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7348 if (length > tbr->len - tbr->index)
7349 png_error (png_ptr, "Read error");
7351 bcopy (tbr->bytes + tbr->index, data, length);
7352 tbr->index = tbr->index + length;
7355 /* Load PNG image IMG for use on frame F. Value is non-zero if
7356 successful. */
7358 static int
7359 png_load (f, img)
7360 struct frame *f;
7361 struct image *img;
7363 Lisp_Object file, specified_file;
7364 Lisp_Object specified_data;
7365 int x, y, i;
7366 XImage *ximg, *mask_img = NULL;
7367 struct gcpro gcpro1;
7368 png_struct *png_ptr = NULL;
7369 png_info *info_ptr = NULL, *end_info = NULL;
7370 FILE *fp = NULL;
7371 png_byte sig[8];
7372 png_byte *pixels = NULL;
7373 png_byte **rows = NULL;
7374 png_uint_32 width, height;
7375 int bit_depth, color_type, interlace_type;
7376 png_byte channels;
7377 png_uint_32 row_bytes;
7378 int transparent_p;
7379 char *gamma_str;
7380 double screen_gamma, image_gamma;
7381 int intent;
7382 struct png_memory_storage tbr; /* Data to be read */
7384 /* Find out what file to load. */
7385 specified_file = image_spec_value (img->spec, QCfile, NULL);
7386 specified_data = image_spec_value (img->spec, QCdata, NULL);
7387 file = Qnil;
7388 GCPRO1 (file);
7390 if (NILP (specified_data))
7392 file = x_find_image_file (specified_file);
7393 if (!STRINGP (file))
7395 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7396 UNGCPRO;
7397 return 0;
7400 /* Open the image file. */
7401 fp = fopen (XSTRING (file)->data, "rb");
7402 if (!fp)
7404 image_error ("Cannot open image file `%s'", file, Qnil);
7405 UNGCPRO;
7406 fclose (fp);
7407 return 0;
7410 /* Check PNG signature. */
7411 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7412 || !png_check_sig (sig, sizeof sig))
7414 image_error ("Not a PNG file:` %s'", file, Qnil);
7415 UNGCPRO;
7416 fclose (fp);
7417 return 0;
7420 else
7422 /* Read from memory. */
7423 tbr.bytes = XSTRING (specified_data)->data;
7424 tbr.len = STRING_BYTES (XSTRING (specified_data));
7425 tbr.index = 0;
7427 /* Check PNG signature. */
7428 if (tbr.len < sizeof sig
7429 || !png_check_sig (tbr.bytes, sizeof sig))
7431 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7432 UNGCPRO;
7433 return 0;
7436 /* Need to skip past the signature. */
7437 tbr.bytes += sizeof (sig);
7440 /* Initialize read and info structs for PNG lib. */
7441 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7442 my_png_error, my_png_warning);
7443 if (!png_ptr)
7445 if (fp) fclose (fp);
7446 UNGCPRO;
7447 return 0;
7450 info_ptr = png_create_info_struct (png_ptr);
7451 if (!info_ptr)
7453 png_destroy_read_struct (&png_ptr, NULL, NULL);
7454 if (fp) fclose (fp);
7455 UNGCPRO;
7456 return 0;
7459 end_info = png_create_info_struct (png_ptr);
7460 if (!end_info)
7462 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7463 if (fp) fclose (fp);
7464 UNGCPRO;
7465 return 0;
7468 /* Set error jump-back. We come back here when the PNG library
7469 detects an error. */
7470 if (setjmp (png_ptr->jmpbuf))
7472 error:
7473 if (png_ptr)
7474 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7475 xfree (pixels);
7476 xfree (rows);
7477 if (fp) fclose (fp);
7478 UNGCPRO;
7479 return 0;
7482 /* Read image info. */
7483 if (!NILP (specified_data))
7484 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7485 else
7486 png_init_io (png_ptr, fp);
7488 png_set_sig_bytes (png_ptr, sizeof sig);
7489 png_read_info (png_ptr, info_ptr);
7490 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7491 &interlace_type, NULL, NULL);
7493 /* If image contains simply transparency data, we prefer to
7494 construct a clipping mask. */
7495 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7496 transparent_p = 1;
7497 else
7498 transparent_p = 0;
7500 /* This function is easier to write if we only have to handle
7501 one data format: RGB or RGBA with 8 bits per channel. Let's
7502 transform other formats into that format. */
7504 /* Strip more than 8 bits per channel. */
7505 if (bit_depth == 16)
7506 png_set_strip_16 (png_ptr);
7508 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7509 if available. */
7510 png_set_expand (png_ptr);
7512 /* Convert grayscale images to RGB. */
7513 if (color_type == PNG_COLOR_TYPE_GRAY
7514 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7515 png_set_gray_to_rgb (png_ptr);
7517 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7518 gamma_str = getenv ("SCREEN_GAMMA");
7519 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
7521 /* Tell the PNG lib to handle gamma correction for us. */
7523 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7524 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7525 /* There is a special chunk in the image specifying the gamma. */
7526 png_set_sRGB (png_ptr, info_ptr, intent);
7527 else
7528 #endif
7529 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7530 /* Image contains gamma information. */
7531 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7532 else
7533 /* Use a default of 0.5 for the image gamma. */
7534 png_set_gamma (png_ptr, screen_gamma, 0.5);
7536 /* Handle alpha channel by combining the image with a background
7537 color. Do this only if a real alpha channel is supplied. For
7538 simple transparency, we prefer a clipping mask. */
7539 if (!transparent_p)
7541 png_color_16 *image_background;
7543 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
7544 /* Image contains a background color with which to
7545 combine the image. */
7546 png_set_background (png_ptr, image_background,
7547 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7548 else
7550 /* Image does not contain a background color with which
7551 to combine the image data via an alpha channel. Use
7552 the frame's background instead. */
7553 XColor color;
7554 Colormap cmap;
7555 png_color_16 frame_background;
7557 BLOCK_INPUT;
7558 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7559 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7560 XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
7561 UNBLOCK_INPUT;
7563 bzero (&frame_background, sizeof frame_background);
7564 frame_background.red = color.red;
7565 frame_background.green = color.green;
7566 frame_background.blue = color.blue;
7568 png_set_background (png_ptr, &frame_background,
7569 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7573 /* Update info structure. */
7574 png_read_update_info (png_ptr, info_ptr);
7576 /* Get number of channels. Valid values are 1 for grayscale images
7577 and images with a palette, 2 for grayscale images with transparency
7578 information (alpha channel), 3 for RGB images, and 4 for RGB
7579 images with alpha channel, i.e. RGBA. If conversions above were
7580 sufficient we should only have 3 or 4 channels here. */
7581 channels = png_get_channels (png_ptr, info_ptr);
7582 xassert (channels == 3 || channels == 4);
7584 /* Number of bytes needed for one row of the image. */
7585 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7587 /* Allocate memory for the image. */
7588 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7589 rows = (png_byte **) xmalloc (height * sizeof *rows);
7590 for (i = 0; i < height; ++i)
7591 rows[i] = pixels + i * row_bytes;
7593 /* Read the entire image. */
7594 png_read_image (png_ptr, rows);
7595 png_read_end (png_ptr, info_ptr);
7596 if (fp)
7598 fclose (fp);
7599 fp = NULL;
7602 BLOCK_INPUT;
7604 /* Create the X image and pixmap. */
7605 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7606 &img->pixmap))
7608 UNBLOCK_INPUT;
7609 goto error;
7612 /* Create an image and pixmap serving as mask if the PNG image
7613 contains an alpha channel. */
7614 if (channels == 4
7615 && !transparent_p
7616 && !x_create_x_image_and_pixmap (f, width, height, 1,
7617 &mask_img, &img->mask))
7619 x_destroy_x_image (ximg);
7620 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
7621 img->pixmap = 0;
7622 UNBLOCK_INPUT;
7623 goto error;
7626 /* Fill the X image and mask from PNG data. */
7627 init_color_table ();
7629 for (y = 0; y < height; ++y)
7631 png_byte *p = rows[y];
7633 for (x = 0; x < width; ++x)
7635 unsigned r, g, b;
7637 r = *p++ << 8;
7638 g = *p++ << 8;
7639 b = *p++ << 8;
7640 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7642 /* An alpha channel, aka mask channel, associates variable
7643 transparency with an image. Where other image formats
7644 support binary transparency---fully transparent or fully
7645 opaque---PNG allows up to 254 levels of partial transparency.
7646 The PNG library implements partial transparency by combining
7647 the image with a specified background color.
7649 I'm not sure how to handle this here nicely: because the
7650 background on which the image is displayed may change, for
7651 real alpha channel support, it would be necessary to create
7652 a new image for each possible background.
7654 What I'm doing now is that a mask is created if we have
7655 boolean transparency information. Otherwise I'm using
7656 the frame's background color to combine the image with. */
7658 if (channels == 4)
7660 if (mask_img)
7661 XPutPixel (mask_img, x, y, *p > 0);
7662 ++p;
7667 /* Remember colors allocated for this image. */
7668 img->colors = colors_in_color_table (&img->ncolors);
7669 free_color_table ();
7671 /* Clean up. */
7672 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7673 xfree (rows);
7674 xfree (pixels);
7676 img->width = width;
7677 img->height = height;
7679 /* Put the image into the pixmap, then free the X image and its buffer. */
7680 x_put_x_image (f, ximg, img->pixmap, width, height);
7681 x_destroy_x_image (ximg);
7683 /* Same for the mask. */
7684 if (mask_img)
7686 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7687 x_destroy_x_image (mask_img);
7690 UNBLOCK_INPUT;
7691 UNGCPRO;
7692 return 1;
7695 #endif /* HAVE_PNG != 0 */
7699 /***********************************************************************
7700 JPEG
7701 ***********************************************************************/
7703 #if HAVE_JPEG
7705 /* Work around a warning about HAVE_STDLIB_H being redefined in
7706 jconfig.h. */
7707 #ifdef HAVE_STDLIB_H
7708 #define HAVE_STDLIB_H_1
7709 #undef HAVE_STDLIB_H
7710 #endif /* HAVE_STLIB_H */
7712 #include <jpeglib.h>
7713 #include <jerror.h>
7714 #include <setjmp.h>
7716 #ifdef HAVE_STLIB_H_1
7717 #define HAVE_STDLIB_H 1
7718 #endif
7720 static int jpeg_image_p P_ ((Lisp_Object object));
7721 static int jpeg_load P_ ((struct frame *f, struct image *img));
7723 /* The symbol `jpeg' identifying images of this type. */
7725 Lisp_Object Qjpeg;
7727 /* Indices of image specification fields in gs_format, below. */
7729 enum jpeg_keyword_index
7731 JPEG_TYPE,
7732 JPEG_DATA,
7733 JPEG_FILE,
7734 JPEG_ASCENT,
7735 JPEG_MARGIN,
7736 JPEG_RELIEF,
7737 JPEG_ALGORITHM,
7738 JPEG_HEURISTIC_MASK,
7739 JPEG_LAST
7742 /* Vector of image_keyword structures describing the format
7743 of valid user-defined image specifications. */
7745 static struct image_keyword jpeg_format[JPEG_LAST] =
7747 {":type", IMAGE_SYMBOL_VALUE, 1},
7748 {":data", IMAGE_STRING_VALUE, 0},
7749 {":file", IMAGE_STRING_VALUE, 0},
7750 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7751 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7752 {":relief", IMAGE_INTEGER_VALUE, 0},
7753 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7754 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7757 /* Structure describing the image type `jpeg'. */
7759 static struct image_type jpeg_type =
7761 &Qjpeg,
7762 jpeg_image_p,
7763 jpeg_load,
7764 x_clear_image,
7765 NULL
7769 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7771 static int
7772 jpeg_image_p (object)
7773 Lisp_Object object;
7775 struct image_keyword fmt[JPEG_LAST];
7777 bcopy (jpeg_format, fmt, sizeof fmt);
7779 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
7780 || (fmt[JPEG_ASCENT].count
7781 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
7782 return 0;
7784 /* Must specify either the :data or :file keyword. */
7785 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
7789 struct my_jpeg_error_mgr
7791 struct jpeg_error_mgr pub;
7792 jmp_buf setjmp_buffer;
7795 static void
7796 my_error_exit (cinfo)
7797 j_common_ptr cinfo;
7799 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7800 longjmp (mgr->setjmp_buffer, 1);
7803 /* Init source method for JPEG data source manager. Called by
7804 jpeg_read_header() before any data is actually read. See
7805 libjpeg.doc from the JPEG lib distribution. */
7807 static void
7808 our_init_source (cinfo)
7809 j_decompress_ptr cinfo;
7814 /* Fill input buffer method for JPEG data source manager. Called
7815 whenever more data is needed. We read the whole image in one step,
7816 so this only adds a fake end of input marker at the end. */
7818 static boolean
7819 our_fill_input_buffer (cinfo)
7820 j_decompress_ptr cinfo;
7822 /* Insert a fake EOI marker. */
7823 struct jpeg_source_mgr *src = cinfo->src;
7824 static JOCTET buffer[2];
7826 buffer[0] = (JOCTET) 0xFF;
7827 buffer[1] = (JOCTET) JPEG_EOI;
7829 src->next_input_byte = buffer;
7830 src->bytes_in_buffer = 2;
7831 return TRUE;
7835 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7836 is the JPEG data source manager. */
7838 static void
7839 our_skip_input_data (cinfo, num_bytes)
7840 j_decompress_ptr cinfo;
7841 long num_bytes;
7843 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7845 if (src)
7847 if (num_bytes > src->bytes_in_buffer)
7848 ERREXIT (cinfo, JERR_INPUT_EOF);
7850 src->bytes_in_buffer -= num_bytes;
7851 src->next_input_byte += num_bytes;
7856 /* Method to terminate data source. Called by
7857 jpeg_finish_decompress() after all data has been processed. */
7859 static void
7860 our_term_source (cinfo)
7861 j_decompress_ptr cinfo;
7866 /* Set up the JPEG lib for reading an image from DATA which contains
7867 LEN bytes. CINFO is the decompression info structure created for
7868 reading the image. */
7870 static void
7871 jpeg_memory_src (cinfo, data, len)
7872 j_decompress_ptr cinfo;
7873 JOCTET *data;
7874 unsigned int len;
7876 struct jpeg_source_mgr *src;
7878 if (cinfo->src == NULL)
7880 /* First time for this JPEG object? */
7881 cinfo->src = (struct jpeg_source_mgr *)
7882 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7883 sizeof (struct jpeg_source_mgr));
7884 src = (struct jpeg_source_mgr *) cinfo->src;
7885 src->next_input_byte = data;
7888 src = (struct jpeg_source_mgr *) cinfo->src;
7889 src->init_source = our_init_source;
7890 src->fill_input_buffer = our_fill_input_buffer;
7891 src->skip_input_data = our_skip_input_data;
7892 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
7893 src->term_source = our_term_source;
7894 src->bytes_in_buffer = len;
7895 src->next_input_byte = data;
7899 /* Load image IMG for use on frame F. Patterned after example.c
7900 from the JPEG lib. */
7902 static int
7903 jpeg_load (f, img)
7904 struct frame *f;
7905 struct image *img;
7907 struct jpeg_decompress_struct cinfo;
7908 struct my_jpeg_error_mgr mgr;
7909 Lisp_Object file, specified_file;
7910 Lisp_Object specified_data;
7911 FILE *fp = NULL;
7912 JSAMPARRAY buffer;
7913 int row_stride, x, y;
7914 XImage *ximg = NULL;
7915 int rc;
7916 unsigned long *colors;
7917 int width, height;
7918 struct gcpro gcpro1;
7920 /* Open the JPEG file. */
7921 specified_file = image_spec_value (img->spec, QCfile, NULL);
7922 specified_data = image_spec_value (img->spec, QCdata, NULL);
7923 file = Qnil;
7924 GCPRO1 (file);
7926 if (NILP (specified_data))
7928 file = x_find_image_file (specified_file);
7929 if (!STRINGP (file))
7931 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7932 UNGCPRO;
7933 return 0;
7936 fp = fopen (XSTRING (file)->data, "r");
7937 if (fp == NULL)
7939 image_error ("Cannot open `%s'", file, Qnil);
7940 UNGCPRO;
7941 return 0;
7945 /* Customize libjpeg's error handling to call my_error_exit when an
7946 error is detected. This function will perform a longjmp. */
7947 mgr.pub.error_exit = my_error_exit;
7948 cinfo.err = jpeg_std_error (&mgr.pub);
7950 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7952 if (rc == 1)
7954 /* Called from my_error_exit. Display a JPEG error. */
7955 char buffer[JMSG_LENGTH_MAX];
7956 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7957 image_error ("Error reading JPEG image `%s': %s", img->spec,
7958 build_string (buffer));
7961 /* Close the input file and destroy the JPEG object. */
7962 if (fp)
7963 fclose (fp);
7964 jpeg_destroy_decompress (&cinfo);
7966 BLOCK_INPUT;
7968 /* If we already have an XImage, free that. */
7969 x_destroy_x_image (ximg);
7971 /* Free pixmap and colors. */
7972 x_clear_image (f, img);
7974 UNBLOCK_INPUT;
7975 UNGCPRO;
7976 return 0;
7979 /* Create the JPEG decompression object. Let it read from fp.
7980 Read the JPEG image header. */
7981 jpeg_create_decompress (&cinfo);
7983 if (NILP (specified_data))
7984 jpeg_stdio_src (&cinfo, fp);
7985 else
7986 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
7987 STRING_BYTES (XSTRING (specified_data)));
7989 jpeg_read_header (&cinfo, TRUE);
7991 /* Customize decompression so that color quantization will be used.
7992 Start decompression. */
7993 cinfo.quantize_colors = TRUE;
7994 jpeg_start_decompress (&cinfo);
7995 width = img->width = cinfo.output_width;
7996 height = img->height = cinfo.output_height;
7998 BLOCK_INPUT;
8000 /* Create X image and pixmap. */
8001 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8002 &img->pixmap))
8004 UNBLOCK_INPUT;
8005 longjmp (mgr.setjmp_buffer, 2);
8008 /* Allocate colors. When color quantization is used,
8009 cinfo.actual_number_of_colors has been set with the number of
8010 colors generated, and cinfo.colormap is a two-dimensional array
8011 of color indices in the range 0..cinfo.actual_number_of_colors.
8012 No more than 255 colors will be generated. */
8014 int i, ir, ig, ib;
8016 if (cinfo.out_color_components > 2)
8017 ir = 0, ig = 1, ib = 2;
8018 else if (cinfo.out_color_components > 1)
8019 ir = 0, ig = 1, ib = 0;
8020 else
8021 ir = 0, ig = 0, ib = 0;
8023 /* Use the color table mechanism because it handles colors that
8024 cannot be allocated nicely. Such colors will be replaced with
8025 a default color, and we don't have to care about which colors
8026 can be freed safely, and which can't. */
8027 init_color_table ();
8028 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8029 * sizeof *colors);
8031 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8033 /* Multiply RGB values with 255 because X expects RGB values
8034 in the range 0..0xffff. */
8035 int r = cinfo.colormap[ir][i] << 8;
8036 int g = cinfo.colormap[ig][i] << 8;
8037 int b = cinfo.colormap[ib][i] << 8;
8038 colors[i] = lookup_rgb_color (f, r, g, b);
8041 /* Remember those colors actually allocated. */
8042 img->colors = colors_in_color_table (&img->ncolors);
8043 free_color_table ();
8046 /* Read pixels. */
8047 row_stride = width * cinfo.output_components;
8048 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8049 row_stride, 1);
8050 for (y = 0; y < height; ++y)
8052 jpeg_read_scanlines (&cinfo, buffer, 1);
8053 for (x = 0; x < cinfo.output_width; ++x)
8054 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8057 /* Clean up. */
8058 jpeg_finish_decompress (&cinfo);
8059 jpeg_destroy_decompress (&cinfo);
8060 if (fp)
8061 fclose (fp);
8063 /* Put the image into the pixmap. */
8064 x_put_x_image (f, ximg, img->pixmap, width, height);
8065 x_destroy_x_image (ximg);
8066 UNBLOCK_INPUT;
8067 UNGCPRO;
8068 return 1;
8071 #endif /* HAVE_JPEG */
8075 /***********************************************************************
8076 TIFF
8077 ***********************************************************************/
8079 #if HAVE_TIFF
8081 #include <tiffio.h>
8083 static int tiff_image_p P_ ((Lisp_Object object));
8084 static int tiff_load P_ ((struct frame *f, struct image *img));
8086 /* The symbol `tiff' identifying images of this type. */
8088 Lisp_Object Qtiff;
8090 /* Indices of image specification fields in tiff_format, below. */
8092 enum tiff_keyword_index
8094 TIFF_TYPE,
8095 TIFF_DATA,
8096 TIFF_FILE,
8097 TIFF_ASCENT,
8098 TIFF_MARGIN,
8099 TIFF_RELIEF,
8100 TIFF_ALGORITHM,
8101 TIFF_HEURISTIC_MASK,
8102 TIFF_LAST
8105 /* Vector of image_keyword structures describing the format
8106 of valid user-defined image specifications. */
8108 static struct image_keyword tiff_format[TIFF_LAST] =
8110 {":type", IMAGE_SYMBOL_VALUE, 1},
8111 {":data", IMAGE_STRING_VALUE, 0},
8112 {":file", IMAGE_STRING_VALUE, 0},
8113 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8114 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8115 {":relief", IMAGE_INTEGER_VALUE, 0},
8116 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8117 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8120 /* Structure describing the image type `tiff'. */
8122 static struct image_type tiff_type =
8124 &Qtiff,
8125 tiff_image_p,
8126 tiff_load,
8127 x_clear_image,
8128 NULL
8132 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8134 static int
8135 tiff_image_p (object)
8136 Lisp_Object object;
8138 struct image_keyword fmt[TIFF_LAST];
8139 bcopy (tiff_format, fmt, sizeof fmt);
8141 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
8142 || (fmt[TIFF_ASCENT].count
8143 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
8144 return 0;
8146 /* Must specify either the :data or :file keyword. */
8147 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8151 /* Reading from a memory buffer for TIFF images Based on the PNG
8152 memory source, but we have to provide a lot of extra functions.
8153 Blah.
8155 We really only need to implement read and seek, but I am not
8156 convinced that the TIFF library is smart enough not to destroy
8157 itself if we only hand it the function pointers we need to
8158 override. */
8160 typedef struct
8162 unsigned char *bytes;
8163 size_t len;
8164 int index;
8166 tiff_memory_source;
8168 static size_t
8169 tiff_read_from_memory (data, buf, size)
8170 thandle_t data;
8171 tdata_t buf;
8172 tsize_t size;
8174 tiff_memory_source *src = (tiff_memory_source *) data;
8176 if (size > src->len - src->index)
8177 return (size_t) -1;
8178 bcopy (src->bytes + src->index, buf, size);
8179 src->index += size;
8180 return size;
8183 static size_t
8184 tiff_write_from_memory (data, buf, size)
8185 thandle_t data;
8186 tdata_t buf;
8187 tsize_t size;
8189 return (size_t) -1;
8192 static toff_t
8193 tiff_seek_in_memory (data, off, whence)
8194 thandle_t data;
8195 toff_t off;
8196 int whence;
8198 tiff_memory_source *src = (tiff_memory_source *) data;
8199 int idx;
8201 switch (whence)
8203 case SEEK_SET: /* Go from beginning of source. */
8204 idx = off;
8205 break;
8207 case SEEK_END: /* Go from end of source. */
8208 idx = src->len + off;
8209 break;
8211 case SEEK_CUR: /* Go from current position. */
8212 idx = src->index + off;
8213 break;
8215 default: /* Invalid `whence'. */
8216 return -1;
8219 if (idx > src->len || idx < 0)
8220 return -1;
8222 src->index = idx;
8223 return src->index;
8226 static int
8227 tiff_close_memory (data)
8228 thandle_t data;
8230 /* NOOP */
8231 return 0;
8234 static int
8235 tiff_mmap_memory (data, pbase, psize)
8236 thandle_t data;
8237 tdata_t *pbase;
8238 toff_t *psize;
8240 /* It is already _IN_ memory. */
8241 return 0;
8244 static void
8245 tiff_unmap_memory (data, base, size)
8246 thandle_t data;
8247 tdata_t base;
8248 toff_t size;
8250 /* We don't need to do this. */
8253 static toff_t
8254 tiff_size_of_memory (data)
8255 thandle_t data;
8257 return ((tiff_memory_source *) data)->len;
8260 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8261 successful. */
8263 static int
8264 tiff_load (f, img)
8265 struct frame *f;
8266 struct image *img;
8268 Lisp_Object file, specified_file;
8269 Lisp_Object specified_data;
8270 TIFF *tiff;
8271 int width, height, x, y;
8272 uint32 *buf;
8273 int rc;
8274 XImage *ximg;
8275 struct gcpro gcpro1;
8276 tiff_memory_source memsrc;
8278 specified_file = image_spec_value (img->spec, QCfile, NULL);
8279 specified_data = image_spec_value (img->spec, QCdata, NULL);
8280 file = Qnil;
8281 GCPRO1 (file);
8283 if (NILP (specified_data))
8285 /* Read from a file */
8286 file = x_find_image_file (specified_file);
8287 if (!STRINGP (file))
8289 image_error ("Cannot find image file `%s'", file, Qnil);
8290 UNGCPRO;
8291 return 0;
8294 /* Try to open the image file. */
8295 tiff = TIFFOpen (XSTRING (file)->data, "r");
8296 if (tiff == NULL)
8298 image_error ("Cannot open `%s'", file, Qnil);
8299 UNGCPRO;
8300 return 0;
8303 else
8305 /* Memory source! */
8306 memsrc.bytes = XSTRING (specified_data)->data;
8307 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8308 memsrc.index = 0;
8310 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8311 (TIFFReadWriteProc) tiff_read_from_memory,
8312 (TIFFReadWriteProc) tiff_write_from_memory,
8313 tiff_seek_in_memory,
8314 tiff_close_memory,
8315 tiff_size_of_memory,
8316 tiff_mmap_memory,
8317 tiff_unmap_memory);
8319 if (!tiff)
8321 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8322 UNGCPRO;
8323 return 0;
8327 /* Get width and height of the image, and allocate a raster buffer
8328 of width x height 32-bit values. */
8329 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8330 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8331 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8333 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8334 TIFFClose (tiff);
8335 if (!rc)
8337 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8338 xfree (buf);
8339 UNGCPRO;
8340 return 0;
8343 BLOCK_INPUT;
8345 /* Create the X image and pixmap. */
8346 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8348 UNBLOCK_INPUT;
8349 xfree (buf);
8350 UNGCPRO;
8351 return 0;
8354 /* Initialize the color table. */
8355 init_color_table ();
8357 /* Process the pixel raster. Origin is in the lower-left corner. */
8358 for (y = 0; y < height; ++y)
8360 uint32 *row = buf + y * width;
8362 for (x = 0; x < width; ++x)
8364 uint32 abgr = row[x];
8365 int r = TIFFGetR (abgr) << 8;
8366 int g = TIFFGetG (abgr) << 8;
8367 int b = TIFFGetB (abgr) << 8;
8368 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8372 /* Remember the colors allocated for the image. Free the color table. */
8373 img->colors = colors_in_color_table (&img->ncolors);
8374 free_color_table ();
8376 /* Put the image into the pixmap, then free the X image and its buffer. */
8377 x_put_x_image (f, ximg, img->pixmap, width, height);
8378 x_destroy_x_image (ximg);
8379 xfree (buf);
8380 UNBLOCK_INPUT;
8382 img->width = width;
8383 img->height = height;
8385 UNGCPRO;
8386 return 1;
8389 #endif /* HAVE_TIFF != 0 */
8393 /***********************************************************************
8395 ***********************************************************************/
8397 #if HAVE_GIF
8399 #include <gif_lib.h>
8401 static int gif_image_p P_ ((Lisp_Object object));
8402 static int gif_load P_ ((struct frame *f, struct image *img));
8404 /* The symbol `gif' identifying images of this type. */
8406 Lisp_Object Qgif;
8408 /* Indices of image specification fields in gif_format, below. */
8410 enum gif_keyword_index
8412 GIF_TYPE,
8413 GIF_DATA,
8414 GIF_FILE,
8415 GIF_ASCENT,
8416 GIF_MARGIN,
8417 GIF_RELIEF,
8418 GIF_ALGORITHM,
8419 GIF_HEURISTIC_MASK,
8420 GIF_IMAGE,
8421 GIF_LAST
8424 /* Vector of image_keyword structures describing the format
8425 of valid user-defined image specifications. */
8427 static struct image_keyword gif_format[GIF_LAST] =
8429 {":type", IMAGE_SYMBOL_VALUE, 1},
8430 {":data", IMAGE_STRING_VALUE, 0},
8431 {":file", IMAGE_STRING_VALUE, 0},
8432 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8433 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8434 {":relief", IMAGE_INTEGER_VALUE, 0},
8435 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8436 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8437 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
8440 /* Structure describing the image type `gif'. */
8442 static struct image_type gif_type =
8444 &Qgif,
8445 gif_image_p,
8446 gif_load,
8447 x_clear_image,
8448 NULL
8451 /* Return non-zero if OBJECT is a valid GIF image specification. */
8453 static int
8454 gif_image_p (object)
8455 Lisp_Object object;
8457 struct image_keyword fmt[GIF_LAST];
8458 bcopy (gif_format, fmt, sizeof fmt);
8460 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
8461 || (fmt[GIF_ASCENT].count
8462 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
8463 return 0;
8465 /* Must specify either the :data or :file keyword. */
8466 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8469 /* Reading a GIF image from memory
8470 Based on the PNG memory stuff to a certain extent. */
8472 typedef struct
8474 unsigned char *bytes;
8475 size_t len;
8476 int index;
8478 gif_memory_source;
8480 /* Make the current memory source available to gif_read_from_memory.
8481 It's done this way because not all versions of libungif support
8482 a UserData field in the GifFileType structure. */
8483 static gif_memory_source *current_gif_memory_src;
8485 static int
8486 gif_read_from_memory (file, buf, len)
8487 GifFileType *file;
8488 GifByteType *buf;
8489 int len;
8491 gif_memory_source *src = current_gif_memory_src;
8493 if (len > src->len - src->index)
8494 return -1;
8496 bcopy (src->bytes + src->index, buf, len);
8497 src->index += len;
8498 return len;
8502 /* Load GIF image IMG for use on frame F. Value is non-zero if
8503 successful. */
8505 static int
8506 gif_load (f, img)
8507 struct frame *f;
8508 struct image *img;
8510 Lisp_Object file, specified_file;
8511 Lisp_Object specified_data;
8512 int rc, width, height, x, y, i;
8513 XImage *ximg;
8514 ColorMapObject *gif_color_map;
8515 unsigned long pixel_colors[256];
8516 GifFileType *gif;
8517 struct gcpro gcpro1;
8518 Lisp_Object image;
8519 int ino, image_left, image_top, image_width, image_height;
8520 gif_memory_source memsrc;
8521 unsigned char *raster;
8523 specified_file = image_spec_value (img->spec, QCfile, NULL);
8524 specified_data = image_spec_value (img->spec, QCdata, NULL);
8525 file = Qnil;
8526 GCPRO1 (file);
8528 if (NILP (specified_data))
8530 file = x_find_image_file (specified_file);
8531 if (!STRINGP (file))
8533 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8534 UNGCPRO;
8535 return 0;
8538 /* Open the GIF file. */
8539 gif = DGifOpenFileName (XSTRING (file)->data);
8540 if (gif == NULL)
8542 image_error ("Cannot open `%s'", file, Qnil);
8543 UNGCPRO;
8544 return 0;
8547 else
8549 /* Read from memory! */
8550 current_gif_memory_src = &memsrc;
8551 memsrc.bytes = XSTRING (specified_data)->data;
8552 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8553 memsrc.index = 0;
8555 gif = DGifOpen(&memsrc, gif_read_from_memory);
8556 if (!gif)
8558 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8559 UNGCPRO;
8560 return 0;
8564 /* Read entire contents. */
8565 rc = DGifSlurp (gif);
8566 if (rc == GIF_ERROR)
8568 image_error ("Error reading `%s'", img->spec, Qnil);
8569 DGifCloseFile (gif);
8570 UNGCPRO;
8571 return 0;
8574 image = image_spec_value (img->spec, QCindex, NULL);
8575 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8576 if (ino >= gif->ImageCount)
8578 image_error ("Invalid image number `%s' in image `%s'",
8579 image, img->spec);
8580 DGifCloseFile (gif);
8581 UNGCPRO;
8582 return 0;
8585 width = img->width = gif->SWidth;
8586 height = img->height = gif->SHeight;
8588 BLOCK_INPUT;
8590 /* Create the X image and pixmap. */
8591 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8593 UNBLOCK_INPUT;
8594 DGifCloseFile (gif);
8595 UNGCPRO;
8596 return 0;
8599 /* Allocate colors. */
8600 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8601 if (!gif_color_map)
8602 gif_color_map = gif->SColorMap;
8603 init_color_table ();
8604 bzero (pixel_colors, sizeof pixel_colors);
8606 for (i = 0; i < gif_color_map->ColorCount; ++i)
8608 int r = gif_color_map->Colors[i].Red << 8;
8609 int g = gif_color_map->Colors[i].Green << 8;
8610 int b = gif_color_map->Colors[i].Blue << 8;
8611 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8614 img->colors = colors_in_color_table (&img->ncolors);
8615 free_color_table ();
8617 /* Clear the part of the screen image that are not covered by
8618 the image from the GIF file. Full animated GIF support
8619 requires more than can be done here (see the gif89 spec,
8620 disposal methods). Let's simply assume that the part
8621 not covered by a sub-image is in the frame's background color. */
8622 image_top = gif->SavedImages[ino].ImageDesc.Top;
8623 image_left = gif->SavedImages[ino].ImageDesc.Left;
8624 image_width = gif->SavedImages[ino].ImageDesc.Width;
8625 image_height = gif->SavedImages[ino].ImageDesc.Height;
8627 for (y = 0; y < image_top; ++y)
8628 for (x = 0; x < width; ++x)
8629 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8631 for (y = image_top + image_height; y < height; ++y)
8632 for (x = 0; x < width; ++x)
8633 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8635 for (y = image_top; y < image_top + image_height; ++y)
8637 for (x = 0; x < image_left; ++x)
8638 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8639 for (x = image_left + image_width; x < width; ++x)
8640 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8643 /* Read the GIF image into the X image. We use a local variable
8644 `raster' here because RasterBits below is a char *, and invites
8645 problems with bytes >= 0x80. */
8646 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8648 if (gif->SavedImages[ino].ImageDesc.Interlace)
8650 static int interlace_start[] = {0, 4, 2, 1};
8651 static int interlace_increment[] = {8, 8, 4, 2};
8652 int pass, inc;
8653 int row = interlace_start[0];
8655 pass = 0;
8657 for (y = 0; y < image_height; y++)
8659 if (row >= image_height)
8661 row = interlace_start[++pass];
8662 while (row >= image_height)
8663 row = interlace_start[++pass];
8666 for (x = 0; x < image_width; x++)
8668 int i = raster[(y * image_width) + x];
8669 XPutPixel (ximg, x + image_left, row + image_top,
8670 pixel_colors[i]);
8673 row += interlace_increment[pass];
8676 else
8678 for (y = 0; y < image_height; ++y)
8679 for (x = 0; x < image_width; ++x)
8681 int i = raster[y* image_width + x];
8682 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8686 DGifCloseFile (gif);
8688 /* Put the image into the pixmap, then free the X image and its buffer. */
8689 x_put_x_image (f, ximg, img->pixmap, width, height);
8690 x_destroy_x_image (ximg);
8691 UNBLOCK_INPUT;
8693 UNGCPRO;
8694 return 1;
8697 #endif /* HAVE_GIF != 0 */
8701 /***********************************************************************
8702 Ghostscript
8703 ***********************************************************************/
8705 #ifdef HAVE_GHOSTSCRIPT
8706 static int gs_image_p P_ ((Lisp_Object object));
8707 static int gs_load P_ ((struct frame *f, struct image *img));
8708 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8710 /* The symbol `postscript' identifying images of this type. */
8712 Lisp_Object Qpostscript;
8714 /* Keyword symbols. */
8716 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8718 /* Indices of image specification fields in gs_format, below. */
8720 enum gs_keyword_index
8722 GS_TYPE,
8723 GS_PT_WIDTH,
8724 GS_PT_HEIGHT,
8725 GS_FILE,
8726 GS_LOADER,
8727 GS_BOUNDING_BOX,
8728 GS_ASCENT,
8729 GS_MARGIN,
8730 GS_RELIEF,
8731 GS_ALGORITHM,
8732 GS_HEURISTIC_MASK,
8733 GS_LAST
8736 /* Vector of image_keyword structures describing the format
8737 of valid user-defined image specifications. */
8739 static struct image_keyword gs_format[GS_LAST] =
8741 {":type", IMAGE_SYMBOL_VALUE, 1},
8742 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8743 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8744 {":file", IMAGE_STRING_VALUE, 1},
8745 {":loader", IMAGE_FUNCTION_VALUE, 0},
8746 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8747 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8748 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8749 {":relief", IMAGE_INTEGER_VALUE, 0},
8750 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8751 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8754 /* Structure describing the image type `ghostscript'. */
8756 static struct image_type gs_type =
8758 &Qpostscript,
8759 gs_image_p,
8760 gs_load,
8761 gs_clear_image,
8762 NULL
8766 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8768 static void
8769 gs_clear_image (f, img)
8770 struct frame *f;
8771 struct image *img;
8773 /* IMG->data.ptr_val may contain a recorded colormap. */
8774 xfree (img->data.ptr_val);
8775 x_clear_image (f, img);
8779 /* Return non-zero if OBJECT is a valid Ghostscript image
8780 specification. */
8782 static int
8783 gs_image_p (object)
8784 Lisp_Object object;
8786 struct image_keyword fmt[GS_LAST];
8787 Lisp_Object tem;
8788 int i;
8790 bcopy (gs_format, fmt, sizeof fmt);
8792 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
8793 || (fmt[GS_ASCENT].count
8794 && XFASTINT (fmt[GS_ASCENT].value) > 100))
8795 return 0;
8797 /* Bounding box must be a list or vector containing 4 integers. */
8798 tem = fmt[GS_BOUNDING_BOX].value;
8799 if (CONSP (tem))
8801 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8802 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8803 return 0;
8804 if (!NILP (tem))
8805 return 0;
8807 else if (VECTORP (tem))
8809 if (XVECTOR (tem)->size != 4)
8810 return 0;
8811 for (i = 0; i < 4; ++i)
8812 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8813 return 0;
8815 else
8816 return 0;
8818 return 1;
8822 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8823 if successful. */
8825 static int
8826 gs_load (f, img)
8827 struct frame *f;
8828 struct image *img;
8830 char buffer[100];
8831 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8832 struct gcpro gcpro1, gcpro2;
8833 Lisp_Object frame;
8834 double in_width, in_height;
8835 Lisp_Object pixel_colors = Qnil;
8837 /* Compute pixel size of pixmap needed from the given size in the
8838 image specification. Sizes in the specification are in pt. 1 pt
8839 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8840 info. */
8841 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8842 in_width = XFASTINT (pt_width) / 72.0;
8843 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
8844 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8845 in_height = XFASTINT (pt_height) / 72.0;
8846 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
8848 /* Create the pixmap. */
8849 BLOCK_INPUT;
8850 xassert (img->pixmap == 0);
8851 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
8852 img->width, img->height,
8853 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8854 UNBLOCK_INPUT;
8856 if (!img->pixmap)
8858 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8859 return 0;
8862 /* Call the loader to fill the pixmap. It returns a process object
8863 if successful. We do not record_unwind_protect here because
8864 other places in redisplay like calling window scroll functions
8865 don't either. Let the Lisp loader use `unwind-protect' instead. */
8866 GCPRO2 (window_and_pixmap_id, pixel_colors);
8868 sprintf (buffer, "%lu %lu",
8869 (unsigned long) FRAME_W32_WINDOW (f),
8870 (unsigned long) img->pixmap);
8871 window_and_pixmap_id = build_string (buffer);
8873 sprintf (buffer, "%lu %lu",
8874 FRAME_FOREGROUND_PIXEL (f),
8875 FRAME_BACKGROUND_PIXEL (f));
8876 pixel_colors = build_string (buffer);
8878 XSETFRAME (frame, f);
8879 loader = image_spec_value (img->spec, QCloader, NULL);
8880 if (NILP (loader))
8881 loader = intern ("gs-load-image");
8883 img->data.lisp_val = call6 (loader, frame, img->spec,
8884 make_number (img->width),
8885 make_number (img->height),
8886 window_and_pixmap_id,
8887 pixel_colors);
8888 UNGCPRO;
8889 return PROCESSP (img->data.lisp_val);
8893 /* Kill the Ghostscript process that was started to fill PIXMAP on
8894 frame F. Called from XTread_socket when receiving an event
8895 telling Emacs that Ghostscript has finished drawing. */
8897 void
8898 x_kill_gs_process (pixmap, f)
8899 Pixmap pixmap;
8900 struct frame *f;
8902 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8903 int class, i;
8904 struct image *img;
8906 /* Find the image containing PIXMAP. */
8907 for (i = 0; i < c->used; ++i)
8908 if (c->images[i]->pixmap == pixmap)
8909 break;
8911 /* Kill the GS process. We should have found PIXMAP in the image
8912 cache and its image should contain a process object. */
8913 xassert (i < c->used);
8914 img = c->images[i];
8915 xassert (PROCESSP (img->data.lisp_val));
8916 Fkill_process (img->data.lisp_val, Qnil);
8917 img->data.lisp_val = Qnil;
8919 /* On displays with a mutable colormap, figure out the colors
8920 allocated for the image by looking at the pixels of an XImage for
8921 img->pixmap. */
8922 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
8923 if (class != StaticColor && class != StaticGray && class != TrueColor)
8925 XImage *ximg;
8927 BLOCK_INPUT;
8929 /* Try to get an XImage for img->pixmep. */
8930 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
8931 0, 0, img->width, img->height, ~0, ZPixmap);
8932 if (ximg)
8934 int x, y;
8936 /* Initialize the color table. */
8937 init_color_table ();
8939 /* For each pixel of the image, look its color up in the
8940 color table. After having done so, the color table will
8941 contain an entry for each color used by the image. */
8942 for (y = 0; y < img->height; ++y)
8943 for (x = 0; x < img->width; ++x)
8945 unsigned long pixel = XGetPixel (ximg, x, y);
8946 lookup_pixel_color (f, pixel);
8949 /* Record colors in the image. Free color table and XImage. */
8950 img->colors = colors_in_color_table (&img->ncolors);
8951 free_color_table ();
8952 XDestroyImage (ximg);
8954 #if 0 /* This doesn't seem to be the case. If we free the colors
8955 here, we get a BadAccess later in x_clear_image when
8956 freeing the colors. */
8957 /* We have allocated colors once, but Ghostscript has also
8958 allocated colors on behalf of us. So, to get the
8959 reference counts right, free them once. */
8960 if (img->ncolors)
8962 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
8963 XFreeColors (FRAME_W32_DISPLAY (f), cmap,
8964 img->colors, img->ncolors, 0);
8966 #endif
8968 else
8969 image_error ("Cannot get X image of `%s'; colors will not be freed",
8970 img->spec, Qnil);
8972 UNBLOCK_INPUT;
8976 #endif /* HAVE_GHOSTSCRIPT */
8979 /***********************************************************************
8980 Window properties
8981 ***********************************************************************/
8983 DEFUN ("x-change-window-property", Fx_change_window_property,
8984 Sx_change_window_property, 2, 3, 0,
8985 doc: /* Change window property PROP to VALUE on the X window of FRAME.
8986 PROP and VALUE must be strings. FRAME nil or omitted means use the
8987 selected frame. Value is VALUE. */)
8988 (prop, value, frame)
8989 Lisp_Object frame, prop, value;
8991 #if 0 /* MAC_TODO : port window properties to Mac */
8992 struct frame *f = check_x_frame (frame);
8993 Atom prop_atom;
8995 CHECK_STRING (prop);
8996 CHECK_STRING (value);
8998 BLOCK_INPUT;
8999 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
9000 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9001 prop_atom, XA_STRING, 8, PropModeReplace,
9002 XSTRING (value)->data, XSTRING (value)->size);
9004 /* Make sure the property is set when we return. */
9005 XFlush (FRAME_W32_DISPLAY (f));
9006 UNBLOCK_INPUT;
9008 #endif /* MAC_TODO */
9010 return value;
9014 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9015 Sx_delete_window_property, 1, 2, 0,
9016 doc: /* Remove window property PROP from X window of FRAME.
9017 FRAME nil or omitted means use the selected frame. Value is PROP. */)
9018 (prop, frame)
9019 Lisp_Object prop, frame;
9021 #if 0 /* MAC_TODO : port window properties to Mac */
9023 struct frame *f = check_x_frame (frame);
9024 Atom prop_atom;
9026 CHECK_STRING (prop);
9027 BLOCK_INPUT;
9028 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
9029 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
9031 /* Make sure the property is removed when we return. */
9032 XFlush (FRAME_W32_DISPLAY (f));
9033 UNBLOCK_INPUT;
9034 #endif /* MAC_TODO */
9036 return prop;
9040 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9041 1, 2, 0,
9042 doc: /* Value is the value of window property PROP on FRAME.
9043 If FRAME is nil or omitted, use the selected frame. Value is nil
9044 if FRAME hasn't a property with name PROP or if PROP has no string
9045 value. */)
9046 (prop, frame)
9047 Lisp_Object prop, frame;
9049 #if 0 /* MAC_TODO : port window properties to Mac */
9051 struct frame *f = check_x_frame (frame);
9052 Atom prop_atom;
9053 int rc;
9054 Lisp_Object prop_value = Qnil;
9055 char *tmp_data = NULL;
9056 Atom actual_type;
9057 int actual_format;
9058 unsigned long actual_size, bytes_remaining;
9060 CHECK_STRING (prop);
9061 BLOCK_INPUT;
9062 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
9063 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9064 prop_atom, 0, 0, False, XA_STRING,
9065 &actual_type, &actual_format, &actual_size,
9066 &bytes_remaining, (unsigned char **) &tmp_data);
9067 if (rc == Success)
9069 int size = bytes_remaining;
9071 XFree (tmp_data);
9072 tmp_data = NULL;
9074 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9075 prop_atom, 0, bytes_remaining,
9076 False, XA_STRING,
9077 &actual_type, &actual_format,
9078 &actual_size, &bytes_remaining,
9079 (unsigned char **) &tmp_data);
9080 if (rc == Success)
9081 prop_value = make_string (tmp_data, size);
9083 XFree (tmp_data);
9086 UNBLOCK_INPUT;
9088 return prop_value;
9090 #endif /* MAC_TODO */
9091 return Qnil;
9096 /***********************************************************************
9097 Hourglass cursor
9098 ***********************************************************************/
9100 /* If non-null, an asynchronous timer that, when it expires, displays
9101 an hourglass cursor on all frames. */
9103 static struct atimer *hourglass_atimer;
9105 /* Non-zero means an hourglass cursor is currently shown. */
9107 static int hourglass_shown_p;
9109 /* Number of seconds to wait before displaying an hourglass cursor. */
9111 static Lisp_Object Vhourglass_delay;
9113 /* Default number of seconds to wait before displaying an hourglass
9114 cursor. */
9116 #define DEFAULT_HOURGLASS_DELAY 1
9118 /* Function prototypes. */
9120 static void show_hourglass P_ ((struct atimer *));
9121 static void hide_hourglass P_ ((void));
9124 /* Cancel a currently active hourglass timer, and start a new one. */
9126 void
9127 start_hourglass ()
9129 #if 0 /* MAC_TODO: cursor shape changes. */
9130 EMACS_TIME delay;
9131 int secs, usecs = 0;
9133 cancel_hourglass ();
9135 if (INTEGERP (Vhourglass_delay)
9136 && XINT (Vhourglass_delay) > 0)
9137 secs = XFASTINT (Vhourglass_delay);
9138 else if (FLOATP (Vhourglass_delay)
9139 && XFLOAT_DATA (Vhourglass_delay) > 0)
9141 Lisp_Object tem;
9142 tem = Ftruncate (Vhourglass_delay, Qnil);
9143 secs = XFASTINT (tem);
9144 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
9146 else
9147 secs = DEFAULT_HOURGLASS_DELAY;
9149 EMACS_SET_SECS_USECS (delay, secs, usecs);
9150 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
9151 show_hourglass, NULL);
9152 #endif /* MAC_TODO */
9156 /* Cancel the hourglass cursor timer if active, hide an hourglass
9157 cursor if shown. */
9159 void
9160 cancel_hourglass ()
9162 if (hourglass_atimer)
9164 cancel_atimer (hourglass_atimer);
9165 hourglass_atimer = NULL;
9168 if (hourglass_shown_p)
9169 hide_hourglass ();
9173 /* Timer function of hourglass_atimer. TIMER is equal to
9174 hourglass_atimer.
9176 Display an hourglass cursor on all frames by mapping the frames'
9177 hourglass_window. Set the hourglass_p flag in the frames'
9178 output_data.x structure to indicate that an hourglass cursor is
9179 shown on the frames. */
9181 static void
9182 show_hourglass (timer)
9183 struct atimer *timer;
9185 #if 0 /* MAC_TODO: cursor shape changes. */
9186 /* The timer implementation will cancel this timer automatically
9187 after this function has run. Set hourglass_atimer to null
9188 so that we know the timer doesn't have to be canceled. */
9189 hourglass_atimer = NULL;
9191 if (!hourglass_shown_p)
9193 Lisp_Object rest, frame;
9195 BLOCK_INPUT;
9197 FOR_EACH_FRAME (rest, frame)
9198 if (FRAME_W32_P (XFRAME (frame)))
9200 struct frame *f = XFRAME (frame);
9202 f->output_data.w32->hourglass_p = 1;
9204 if (!f->output_data.w32->hourglass_window)
9206 unsigned long mask = CWCursor;
9207 XSetWindowAttributes attrs;
9209 attrs.cursor = f->output_data.w32->hourglass_cursor;
9211 f->output_data.w32->hourglass_window
9212 = XCreateWindow (FRAME_X_DISPLAY (f),
9213 FRAME_OUTER_WINDOW (f),
9214 0, 0, 32000, 32000, 0, 0,
9215 InputOnly,
9216 CopyFromParent,
9217 mask, &attrs);
9220 XMapRaised (FRAME_X_DISPLAY (f),
9221 f->output_data.w32->hourglass_window);
9222 XFlush (FRAME_X_DISPLAY (f));
9225 hourglass_shown_p = 1;
9226 UNBLOCK_INPUT;
9228 #endif /* MAC_TODO */
9232 /* Hide the hourglass cursor on all frames, if it is currently shown. */
9234 static void
9235 hide_hourglass ()
9237 #if 0 /* MAC_TODO: cursor shape changes. */
9238 if (hourglass_shown_p)
9240 Lisp_Object rest, frame;
9242 BLOCK_INPUT;
9243 FOR_EACH_FRAME (rest, frame)
9245 struct frame *f = XFRAME (frame);
9247 if (FRAME_W32_P (f)
9248 /* Watch out for newly created frames. */
9249 && f->output_data.x->hourglass_window)
9251 XUnmapWindow (FRAME_X_DISPLAY (f),
9252 f->output_data.x->hourglass_window);
9253 /* Sync here because XTread_socket looks at the
9254 hourglass_p flag that is reset to zero below. */
9255 XSync (FRAME_X_DISPLAY (f), False);
9256 f->output_data.x->hourglass_p = 0;
9260 hourglass_shown_p = 0;
9261 UNBLOCK_INPUT;
9263 #endif /* MAC_TODO */
9268 /***********************************************************************
9269 Tool tips
9270 ***********************************************************************/
9272 static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
9273 Lisp_Object));
9275 /* The frame of a currently visible tooltip, or null. */
9277 Lisp_Object tip_frame;
9279 /* If non-nil, a timer started that hides the last tooltip when it
9280 fires. */
9282 Lisp_Object tip_timer;
9283 Window tip_window;
9285 /* If non-nil, a vector of 3 elements containing the last args
9286 with which x-show-tip was called. See there. */
9288 Lisp_Object last_show_tip_args;
9290 /* Create a frame for a tooltip on the display described by DPYINFO.
9291 PARMS is a list of frame parameters. Value is the frame. */
9293 static Lisp_Object
9294 x_create_tip_frame (dpyinfo, parms)
9295 struct mac_display_info *dpyinfo;
9296 Lisp_Object parms;
9298 #if 0 /* MAC_TODO : Mac version */
9299 struct frame *f;
9300 Lisp_Object frame, tem;
9301 Lisp_Object name;
9302 long window_prompting = 0;
9303 int width, height;
9304 int count = specpdl_ptr - specpdl;
9305 struct gcpro gcpro1, gcpro2, gcpro3;
9306 struct kboard *kb;
9308 check_x ();
9310 /* Use this general default value to start with until we know if
9311 this frame has a specified name. */
9312 Vx_resource_name = Vinvocation_name;
9314 #ifdef MULTI_KBOARD
9315 kb = dpyinfo->kboard;
9316 #else
9317 kb = &the_only_kboard;
9318 #endif
9320 /* Get the name of the frame to use for resource lookup. */
9321 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
9322 if (!STRINGP (name)
9323 && !EQ (name, Qunbound)
9324 && !NILP (name))
9325 error ("Invalid frame name--not a string or nil");
9326 Vx_resource_name = name;
9328 frame = Qnil;
9329 GCPRO3 (parms, name, frame);
9330 tip_frame = f = make_frame (1);
9331 XSETFRAME (frame, f);
9332 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9334 f->output_method = output_w32;
9335 f->output_data.w32 =
9336 (struct w32_output *) xmalloc (sizeof (struct w32_output));
9337 bzero (f->output_data.w32, sizeof (struct w32_output));
9338 #if 0
9339 f->output_data.w32->icon_bitmap = -1;
9340 #endif
9341 f->output_data.w32->fontset = -1;
9342 f->icon_name = Qnil;
9344 #ifdef MULTI_KBOARD
9345 FRAME_KBOARD (f) = kb;
9346 #endif
9347 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9348 f->output_data.w32->explicit_parent = 0;
9350 /* Set the name; the functions to which we pass f expect the name to
9351 be set. */
9352 if (EQ (name, Qunbound) || NILP (name))
9354 f->name = build_string (dpyinfo->x_id_name);
9355 f->explicit_name = 0;
9357 else
9359 f->name = name;
9360 f->explicit_name = 1;
9361 /* use the frame's title when getting resources for this frame. */
9362 specbind (Qx_resource_name, name);
9365 /* Extract the window parameters from the supplied values
9366 that are needed to determine window geometry. */
9368 Lisp_Object font;
9370 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
9372 BLOCK_INPUT;
9373 /* First, try whatever font the caller has specified. */
9374 if (STRINGP (font))
9376 tem = Fquery_fontset (font, Qnil);
9377 if (STRINGP (tem))
9378 font = x_new_fontset (f, XSTRING (tem)->data);
9379 else
9380 font = x_new_font (f, XSTRING (font)->data);
9383 /* Try out a font which we hope has bold and italic variations. */
9384 if (!STRINGP (font))
9385 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9386 if (!STRINGP (font))
9387 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9388 if (! STRINGP (font))
9389 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9390 if (! STRINGP (font))
9391 /* This was formerly the first thing tried, but it finds too many fonts
9392 and takes too long. */
9393 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9394 /* If those didn't work, look for something which will at least work. */
9395 if (! STRINGP (font))
9396 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9397 UNBLOCK_INPUT;
9398 if (! STRINGP (font))
9399 font = build_string ("fixed");
9401 x_default_parameter (f, parms, Qfont, font,
9402 "font", "Font", RES_TYPE_STRING);
9405 x_default_parameter (f, parms, Qborder_width, make_number (2),
9406 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9408 /* This defaults to 2 in order to match xterm. We recognize either
9409 internalBorderWidth or internalBorder (which is what xterm calls
9410 it). */
9411 if (NILP (Fassq (Qinternal_border_width, parms)))
9413 Lisp_Object value;
9415 value = w32_get_arg (parms, Qinternal_border_width,
9416 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9417 if (! EQ (value, Qunbound))
9418 parms = Fcons (Fcons (Qinternal_border_width, value),
9419 parms);
9422 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9423 "internalBorderWidth", "internalBorderWidth",
9424 RES_TYPE_NUMBER);
9426 /* Also do the stuff which must be set before the window exists. */
9427 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9428 "foreground", "Foreground", RES_TYPE_STRING);
9429 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9430 "background", "Background", RES_TYPE_STRING);
9431 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9432 "pointerColor", "Foreground", RES_TYPE_STRING);
9433 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9434 "cursorColor", "Foreground", RES_TYPE_STRING);
9435 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9436 "borderColor", "BorderColor", RES_TYPE_STRING);
9438 /* Init faces before x_default_parameter is called for scroll-bar
9439 parameters because that function calls x_set_scroll_bar_width,
9440 which calls change_frame_size, which calls Fset_window_buffer,
9441 which runs hooks, which call Fvertical_motion. At the end, we
9442 end up in init_iterator with a null face cache, which should not
9443 happen. */
9444 init_frame_faces (f);
9446 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9447 window_prompting = x_figure_window_size (f, parms);
9449 if (window_prompting & XNegative)
9451 if (window_prompting & YNegative)
9452 f->output_data.w32->win_gravity = SouthEastGravity;
9453 else
9454 f->output_data.w32->win_gravity = NorthEastGravity;
9456 else
9458 if (window_prompting & YNegative)
9459 f->output_data.w32->win_gravity = SouthWestGravity;
9460 else
9461 f->output_data.w32->win_gravity = NorthWestGravity;
9464 f->output_data.w32->size_hint_flags = window_prompting;
9466 XSetWindowAttributes attrs;
9467 unsigned long mask;
9469 BLOCK_INPUT;
9470 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9471 /* Window managers looks at the override-redirect flag to
9472 determine whether or net to give windows a decoration (Xlib
9473 3.2.8). */
9474 attrs.override_redirect = True;
9475 attrs.save_under = True;
9476 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9477 /* Arrange for getting MapNotify and UnmapNotify events. */
9478 attrs.event_mask = StructureNotifyMask;
9479 tip_window
9480 = FRAME_W32_WINDOW (f)
9481 = XCreateWindow (FRAME_W32_DISPLAY (f),
9482 FRAME_W32_DISPLAY_INFO (f)->root_window,
9483 /* x, y, width, height */
9484 0, 0, 1, 1,
9485 /* Border. */
9487 CopyFromParent, InputOutput, CopyFromParent,
9488 mask, &attrs);
9489 UNBLOCK_INPUT;
9492 x_make_gc (f);
9494 x_default_parameter (f, parms, Qauto_raise, Qnil,
9495 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9496 x_default_parameter (f, parms, Qauto_lower, Qnil,
9497 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9498 x_default_parameter (f, parms, Qcursor_type, Qbox,
9499 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9501 /* Dimensions, especially f->height, must be done via change_frame_size.
9502 Change will not be effected unless different from the current
9503 f->height. */
9504 width = f->width;
9505 height = f->height;
9506 f->height = 0;
9507 SET_FRAME_WIDTH (f, 0);
9508 change_frame_size (f, height, width, 1, 0, 0);
9510 f->no_split = 1;
9512 UNGCPRO;
9514 /* It is now ok to make the frame official even if we get an error
9515 below. And the frame needs to be on Vframe_list or making it
9516 visible won't work. */
9517 Vframe_list = Fcons (frame, Vframe_list);
9519 /* Now that the frame is official, it counts as a reference to
9520 its display. */
9521 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
9523 return unbind_to (count, frame);
9524 #endif /* MAC_TODO */
9525 return Qnil;
9529 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
9530 doc : /* Show STRING in a "tooltip" window on frame FRAME.
9531 A tooltip window is a small window displaying a string.
9533 FRAME nil or omitted means use the selected frame.
9535 PARMS is an optional list of frame parameters which can be used to
9536 change the tooltip's appearance.
9538 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
9539 means use the default timeout of 5 seconds.
9541 If the list of frame parameters PARAMS contains a `left' parameters,
9542 the tooltip is displayed at that x-position. Otherwise it is
9543 displayed at the mouse position, with offset DX added (default is 5 if
9544 DX isn't specified). Likewise for the y-position; if a `top' frame
9545 parameter is specified, it determines the y-position of the tooltip
9546 window, otherwise it is displayed at the mouse position, with offset
9547 DY added (default is 10). */)
9548 (string, frame, parms, timeout, dx, dy)
9549 Lisp_Object string, frame, parms, timeout, dx, dy;
9551 struct frame *f;
9552 struct window *w;
9553 Window root, child;
9554 Lisp_Object buffer, top, left;
9555 struct buffer *old_buffer;
9556 struct text_pos pos;
9557 int i, width, height;
9558 int root_x, root_y, win_x, win_y;
9559 unsigned pmask;
9560 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9561 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9562 int count = specpdl_ptr - specpdl;
9564 specbind (Qinhibit_redisplay, Qt);
9566 GCPRO4 (string, parms, frame, timeout);
9568 CHECK_STRING (string);
9569 f = check_x_frame (frame);
9570 if (NILP (timeout))
9571 timeout = make_number (5);
9572 else
9573 CHECK_NATNUM (timeout);
9575 if (NILP (dx))
9576 dx = make_number (5);
9577 else
9578 CHECK_NUMBER (dx);
9580 if (NILP (dy))
9581 dy = make_number (-10);
9582 else
9583 CHECK_NUMBER (dy);
9585 if (NILP (last_show_tip_args))
9586 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
9588 if (!NILP (tip_frame))
9590 Lisp_Object last_string = AREF (last_show_tip_args, 0);
9591 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
9592 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
9594 if (EQ (frame, last_frame)
9595 && !NILP (Fequal (last_string, string))
9596 && !NILP (Fequal (last_parms, parms)))
9598 struct frame *f = XFRAME (tip_frame);
9600 /* Only DX and DY have changed. */
9601 if (!NILP (tip_timer))
9603 Lisp_Object timer = tip_timer;
9604 tip_timer = Qnil;
9605 call1 (Qcancel_timer, timer);
9608 #if 0 /* MAC_TODO : Mac specifics */
9609 BLOCK_INPUT;
9610 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9611 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9612 root_x, root_y - PIXEL_HEIGHT (f));
9613 UNBLOCK_INPUT;
9614 #endif /* MAC_TODO */
9615 goto start_timer;
9619 /* Hide a previous tip, if any. */
9620 Fx_hide_tip ();
9622 ASET (last_show_tip_args, 0, string);
9623 ASET (last_show_tip_args, 1, frame);
9624 ASET (last_show_tip_args, 2, parms);
9626 /* Add default values to frame parameters. */
9627 if (NILP (Fassq (Qname, parms)))
9628 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9629 if (NILP (Fassq (Qinternal_border_width, parms)))
9630 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9631 if (NILP (Fassq (Qborder_width, parms)))
9632 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9633 if (NILP (Fassq (Qborder_color, parms)))
9634 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9635 if (NILP (Fassq (Qbackground_color, parms)))
9636 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9637 parms);
9639 /* Create a frame for the tooltip, and record it in the global
9640 variable tip_frame. */
9641 frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
9642 f = XFRAME (frame);
9644 /* Set up the frame's root window. Currently we use a size of 80
9645 columns x 40 lines. If someone wants to show a larger tip, he
9646 will loose. I don't think this is a realistic case. */
9647 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9648 w->left = w->top = make_number (0);
9649 w->width = make_number (80);
9650 w->height = make_number (40);
9651 adjust_glyphs (f);
9652 w->pseudo_window_p = 1;
9654 /* Display the tooltip text in a temporary buffer. */
9655 buffer = Fget_buffer_create (build_string (" *tip*"));
9656 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
9657 old_buffer = current_buffer;
9658 set_buffer_internal_1 (XBUFFER (buffer));
9659 Ferase_buffer ();
9660 Finsert (1, &string);
9661 clear_glyph_matrix (w->desired_matrix);
9662 clear_glyph_matrix (w->current_matrix);
9663 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9664 try_window (FRAME_ROOT_WINDOW (f), pos);
9666 /* Compute width and height of the tooltip. */
9667 width = height = 0;
9668 for (i = 0; i < w->desired_matrix->nrows; ++i)
9670 struct glyph_row *row = &w->desired_matrix->rows[i];
9671 struct glyph *last;
9672 int row_width;
9674 /* Stop at the first empty row at the end. */
9675 if (!row->enabled_p || !row->displays_text_p)
9676 break;
9678 /* Let the row go over the full width of the frame. */
9679 row->full_width_p = 1;
9681 /* There's a glyph at the end of rows that is use to place
9682 the cursor there. Don't include the width of this glyph. */
9683 if (row->used[TEXT_AREA])
9685 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
9686 row_width = row->pixel_width - last->pixel_width;
9688 else
9689 row_width = row->pixel_width;
9691 height += row->height;
9692 width = max (width, row_width);
9695 /* Add the frame's internal border to the width and height the X
9696 window should have. */
9697 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9698 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9700 /* Move the tooltip window where the mouse pointer is. Resize and
9701 show it. */
9702 #if 0 /* TODO : Mac specifics */
9703 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9705 BLOCK_INPUT;
9706 XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
9707 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
9708 XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9709 root_x + 5, root_y - height - 5, width, height);
9710 XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
9711 UNBLOCK_INPUT;
9712 #endif /* MAC_TODO */
9714 /* Draw into the window. */
9715 w->must_be_updated_p = 1;
9716 update_single_window (w, 1);
9718 /* Restore original current buffer. */
9719 set_buffer_internal_1 (old_buffer);
9720 windows_or_buffers_changed = old_windows_or_buffers_changed;
9722 start_timer:
9723 /* Let the tip disappear after timeout seconds. */
9724 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
9725 intern ("x-hide-tip"));
9727 UNGCPRO;
9728 return unbind_to (count, Qnil);
9732 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9733 doc: /* Hide the current tooltip window, if there is any.
9734 Value is t is tooltip was open, nil otherwise. */)
9737 int count;
9738 Lisp_Object deleted, frame, timer;
9739 struct gcpro gcpro1, gcpro2;
9741 /* Return quickly if nothing to do. */
9742 if (NILP (tip_timer) && NILP (tip_frame))
9743 return Qnil;
9745 frame = tip_frame;
9746 timer = tip_timer;
9747 GCPRO2 (frame, timer);
9748 tip_frame = tip_timer = deleted = Qnil;
9750 count = BINDING_STACK_SIZE ();
9751 specbind (Qinhibit_redisplay, Qt);
9752 specbind (Qinhibit_quit, Qt);
9754 if (!NILP (timer))
9755 call1 (Qcancel_timer, timer);
9757 if (FRAMEP (frame))
9759 Fdelete_frame (frame, Qnil);
9760 deleted = Qt;
9763 UNGCPRO;
9764 return unbind_to (count, deleted);
9769 /***********************************************************************
9770 File selection dialog
9771 ***********************************************************************/
9773 #if 0 /* MAC_TODO: can standard file dialog */
9774 extern Lisp_Object Qfile_name_history;
9776 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
9777 doc: /* Read file name, prompting with PROMPT in directory DIR.
9778 Use a file selection dialog.
9779 Select DEFAULT-FILENAME in the dialog's file selection box, if
9780 specified. Don't let the user enter a file name in the file
9781 selection dialog's entry field, if MUSTMATCH is non-nil. */)
9782 (prompt, dir, default_filename, mustmatch)
9783 Lisp_Object prompt, dir, default_filename, mustmatch;
9785 struct frame *f = SELECTED_FRAME ();
9786 Lisp_Object file = Qnil;
9787 int count = specpdl_ptr - specpdl;
9788 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
9789 char filename[MAX_PATH + 1];
9790 char init_dir[MAX_PATH + 1];
9791 int use_dialog_p = 1;
9793 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
9794 CHECK_STRING (prompt);
9795 CHECK_STRING (dir);
9797 /* Create the dialog with PROMPT as title, using DIR as initial
9798 directory and using "*" as pattern. */
9799 dir = Fexpand_file_name (dir, Qnil);
9800 strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
9801 init_dir[MAX_PATH] = '\0';
9802 unixtodos_filename (init_dir);
9804 if (STRINGP (default_filename))
9806 char *file_name_only;
9807 char *full_path_name = XSTRING (default_filename)->data;
9809 unixtodos_filename (full_path_name);
9811 file_name_only = strrchr (full_path_name, '\\');
9812 if (!file_name_only)
9813 file_name_only = full_path_name;
9814 else
9816 file_name_only++;
9818 /* If default_file_name is a directory, don't use the open
9819 file dialog, as it does not support selecting
9820 directories. */
9821 if (!(*file_name_only))
9822 use_dialog_p = 0;
9825 strncpy (filename, file_name_only, MAX_PATH);
9826 filename[MAX_PATH] = '\0';
9828 else
9829 filename[0] = '\0';
9831 if (use_dialog_p)
9833 OPENFILENAME file_details;
9834 char *filename_file;
9836 /* Prevent redisplay. */
9837 specbind (Qinhibit_redisplay, Qt);
9838 BLOCK_INPUT;
9840 bzero (&file_details, sizeof (file_details));
9841 file_details.lStructSize = sizeof (file_details);
9842 file_details.hwndOwner = FRAME_W32_WINDOW (f);
9843 file_details.lpstrFile = filename;
9844 file_details.nMaxFile = sizeof (filename);
9845 file_details.lpstrInitialDir = init_dir;
9846 file_details.lpstrTitle = XSTRING (prompt)->data;
9847 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
9849 if (!NILP (mustmatch))
9850 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
9852 if (GetOpenFileName (&file_details))
9854 dostounix_filename (filename);
9855 file = build_string (filename);
9857 else
9858 file = Qnil;
9860 UNBLOCK_INPUT;
9861 file = unbind_to (count, file);
9863 /* Open File dialog will not allow folders to be selected, so resort
9864 to minibuffer completing reads for directories. */
9865 else
9866 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
9867 dir, mustmatch, dir, Qfile_name_history,
9868 default_filename, Qnil);
9870 UNGCPRO;
9872 /* Make "Cancel" equivalent to C-g. */
9873 if (NILP (file))
9874 Fsignal (Qquit, Qnil);
9876 return unbind_to (count, file);
9878 #endif /* MAC_TODO */
9882 /***********************************************************************
9883 Tests
9884 ***********************************************************************/
9886 #if GLYPH_DEBUG
9888 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9889 doc: /* Value is non-nil if SPEC is a valid image specification. */)
9890 (spec)
9891 Lisp_Object spec;
9893 return valid_image_p (spec) ? Qt : Qnil;
9897 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9898 (spec)
9899 Lisp_Object spec;
9901 int id = -1;
9903 if (valid_image_p (spec))
9904 id = lookup_image (SELECTED_FRAME (), spec);
9906 debug_print (spec);
9907 return make_number (id);
9910 #endif /* GLYPH_DEBUG != 0 */
9914 void
9915 syms_of_macfns ()
9917 /* Certainly running on Mac. */
9918 mac_in_use = 1;
9920 /* The section below is built by the lisp expression at the top of the file,
9921 just above where these variables are declared. */
9922 /*&&& init symbols here &&&*/
9923 Qauto_raise = intern ("auto-raise");
9924 staticpro (&Qauto_raise);
9925 Qauto_lower = intern ("auto-lower");
9926 staticpro (&Qauto_lower);
9927 Qbar = intern ("bar");
9928 staticpro (&Qbar);
9929 Qborder_color = intern ("border-color");
9930 staticpro (&Qborder_color);
9931 Qborder_width = intern ("border-width");
9932 staticpro (&Qborder_width);
9933 Qbox = intern ("box");
9934 staticpro (&Qbox);
9935 Qcursor_color = intern ("cursor-color");
9936 staticpro (&Qcursor_color);
9937 Qcursor_type = intern ("cursor-type");
9938 staticpro (&Qcursor_type);
9939 Qgeometry = intern ("geometry");
9940 staticpro (&Qgeometry);
9941 Qicon_left = intern ("icon-left");
9942 staticpro (&Qicon_left);
9943 Qicon_top = intern ("icon-top");
9944 staticpro (&Qicon_top);
9945 Qicon_type = intern ("icon-type");
9946 staticpro (&Qicon_type);
9947 Qicon_name = intern ("icon-name");
9948 staticpro (&Qicon_name);
9949 Qinternal_border_width = intern ("internal-border-width");
9950 staticpro (&Qinternal_border_width);
9951 Qleft = intern ("left");
9952 staticpro (&Qleft);
9953 Qright = intern ("right");
9954 staticpro (&Qright);
9955 Qmouse_color = intern ("mouse-color");
9956 staticpro (&Qmouse_color);
9957 Qnone = intern ("none");
9958 staticpro (&Qnone);
9959 Qparent_id = intern ("parent-id");
9960 staticpro (&Qparent_id);
9961 Qscroll_bar_width = intern ("scroll-bar-width");
9962 staticpro (&Qscroll_bar_width);
9963 Qsuppress_icon = intern ("suppress-icon");
9964 staticpro (&Qsuppress_icon);
9965 Qundefined_color = intern ("undefined-color");
9966 staticpro (&Qundefined_color);
9967 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
9968 staticpro (&Qvertical_scroll_bars);
9969 Qvisibility = intern ("visibility");
9970 staticpro (&Qvisibility);
9971 Qwindow_id = intern ("window-id");
9972 staticpro (&Qwindow_id);
9973 Qx_frame_parameter = intern ("x-frame-parameter");
9974 staticpro (&Qx_frame_parameter);
9975 Qx_resource_name = intern ("x-resource-name");
9976 staticpro (&Qx_resource_name);
9977 Quser_position = intern ("user-position");
9978 staticpro (&Quser_position);
9979 Quser_size = intern ("user-size");
9980 staticpro (&Quser_size);
9981 Qscreen_gamma = intern ("screen-gamma");
9982 staticpro (&Qscreen_gamma);
9983 Qline_spacing = intern ("line-spacing");
9984 staticpro (&Qline_spacing);
9985 Qcenter = intern ("center");
9986 staticpro (&Qcenter);
9987 /* This is the end of symbol initialization. */
9989 Qhyper = intern ("hyper");
9990 staticpro (&Qhyper);
9991 Qsuper = intern ("super");
9992 staticpro (&Qsuper);
9993 Qmeta = intern ("meta");
9994 staticpro (&Qmeta);
9995 Qalt = intern ("alt");
9996 staticpro (&Qalt);
9997 Qctrl = intern ("ctrl");
9998 staticpro (&Qctrl);
9999 Qcontrol = intern ("control");
10000 staticpro (&Qcontrol);
10001 Qshift = intern ("shift");
10002 staticpro (&Qshift);
10004 /* Text property `display' should be nonsticky by default. */
10005 Vtext_property_default_nonsticky
10006 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10009 Qlaplace = intern ("laplace");
10010 staticpro (&Qlaplace);
10012 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10013 staticpro (&Qface_set_after_frame_default);
10015 Fput (Qundefined_color, Qerror_conditions,
10016 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10017 Fput (Qundefined_color, Qerror_message,
10018 build_string ("Undefined color"));
10020 init_x_parm_symbols ();
10022 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10023 doc: /* List of directories to search for bitmap files for w32. */);
10024 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
10026 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10027 doc: /* The shape of the pointer when over text.
10028 Changing the value does not affect existing frames
10029 unless you set the mouse color. */);
10030 Vx_pointer_shape = Qnil;
10032 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
10033 doc: /* The name Emacs uses to look up resources; for internal use only.
10034 `x-get-resource' uses this as the first component of the instance name
10035 when requesting resource values.
10036 Emacs initially sets `x-resource-name' to the name under which Emacs
10037 was invoked, or to the value specified with the `-name' or `-rn'
10038 switches, if present. */);
10039 Vx_resource_name = Qnil;
10041 Vx_nontext_pointer_shape = Qnil;
10043 Vx_mode_pointer_shape = Qnil;
10045 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
10046 doc: /* The shape of the pointer when Emacs is hourglass.
10047 This variable takes effect when you create a new frame
10048 or when you set the mouse color. */);
10049 Vx_hourglass_pointer_shape = Qnil;
10051 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
10052 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10053 display_hourglass_p = 1;
10055 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
10056 doc: /* *Seconds to wait before displaying an hourglass pointer.
10057 Value must be an integer or float. */);
10058 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
10060 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10061 &Vx_sensitive_text_pointer_shape,
10062 doc: /* The shape of the pointer when over mouse-sensitive text.
10063 This variable takes effect when you create a new frame
10064 or when you set the mouse color. */);
10065 Vx_sensitive_text_pointer_shape = Qnil;
10067 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10068 doc: /* A string indicating the foreground color of the cursor box. */);
10069 Vx_cursor_fore_pixel = Qnil;
10071 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10072 doc: /* Non-nil if no window manager is in use.
10073 Emacs doesn't try to figure this out; this is always nil
10074 unless you set it to something else. */);
10075 /* We don't have any way to find this out, so set it to nil
10076 and maybe the user would like to set it to t. */
10077 Vx_no_window_manager = Qnil;
10079 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10080 &Vx_pixel_size_width_font_regexp,
10081 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10083 Since Emacs gets width of a font matching with this regexp from
10084 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10085 such a font. This is especially effective for such large fonts as
10086 Chinese, Japanese, and Korean. */);
10087 Vx_pixel_size_width_font_regexp = Qnil;
10089 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10090 doc: /* Time after which cached images are removed from the cache.
10091 When an image has not been displayed this many seconds, remove it
10092 from the image cache. Value must be an integer or nil with nil
10093 meaning don't clear the cache. */);
10094 Vimage_cache_eviction_delay = make_number (30 * 60);
10096 #if 0 /* MAC_TODO: implement get X resource */
10097 defsubr (&Sx_get_resource);
10098 #endif
10099 defsubr (&Sx_change_window_property);
10100 defsubr (&Sx_delete_window_property);
10101 defsubr (&Sx_window_property);
10102 defsubr (&Sxw_display_color_p);
10103 defsubr (&Sx_display_grayscale_p);
10104 defsubr (&Sxw_color_defined_p);
10105 defsubr (&Sxw_color_values);
10106 defsubr (&Sx_server_max_request_size);
10107 defsubr (&Sx_server_vendor);
10108 defsubr (&Sx_server_version);
10109 defsubr (&Sx_display_pixel_width);
10110 defsubr (&Sx_display_pixel_height);
10111 defsubr (&Sx_display_mm_width);
10112 defsubr (&Sx_display_mm_height);
10113 defsubr (&Sx_display_screens);
10114 defsubr (&Sx_display_planes);
10115 defsubr (&Sx_display_color_cells);
10116 defsubr (&Sx_display_visual_class);
10117 defsubr (&Sx_display_backing_store);
10118 defsubr (&Sx_display_save_under);
10119 #if 0 /* MAC_TODO: implement XParseGeometry */
10120 defsubr (&Sx_parse_geometry);
10121 #endif
10122 defsubr (&Sx_create_frame);
10123 #if 0 /* MAC_TODO: implement network support */
10124 defsubr (&Sx_open_connection);
10125 defsubr (&Sx_close_connection);
10126 #endif
10127 defsubr (&Sx_display_list);
10128 defsubr (&Sx_synchronize);
10130 /* Setting callback functions for fontset handler. */
10131 get_font_info_func = x_get_font_info;
10133 #if 0 /* This function pointer doesn't seem to be used anywhere.
10134 And the pointer assigned has the wrong type, anyway. */
10135 list_fonts_func = x_list_fonts;
10136 #endif
10138 load_font_func = x_load_font;
10139 find_ccl_program_func = x_find_ccl_program;
10140 query_font_func = x_query_font;
10142 set_frame_fontset_func = x_set_font;
10143 check_window_system_func = check_mac;
10145 #if 0 /* MAC_TODO: Image support for Mac Images. */
10146 Qxbm = intern ("xbm");
10147 staticpro (&Qxbm);
10148 QCtype = intern (":type");
10149 staticpro (&QCtype);
10150 QCconversion = intern (":conversion");
10151 staticpro (&QCconversion);
10152 QCheuristic_mask = intern (":heuristic-mask");
10153 staticpro (&QCheuristic_mask);
10154 QCcolor_symbols = intern (":color-symbols");
10155 staticpro (&QCcolor_symbols);
10156 QCascent = intern (":ascent");
10157 staticpro (&QCascent);
10158 QCmargin = intern (":margin");
10159 staticpro (&QCmargin);
10160 QCrelief = intern (":relief");
10161 staticpro (&QCrelief);
10162 Qpostscript = intern ("postscript");
10163 staticpro (&Qpostscript);
10164 QCloader = intern (":loader");
10165 staticpro (&QCloader);
10166 QCbounding_box = intern (":bounding-box");
10167 staticpro (&QCbounding_box);
10168 QCpt_width = intern (":pt-width");
10169 staticpro (&QCpt_width);
10170 QCpt_height = intern (":pt-height");
10171 staticpro (&QCpt_height);
10172 QCindex = intern (":index");
10173 staticpro (&QCindex);
10174 Qpbm = intern ("pbm");
10175 staticpro (&Qpbm);
10177 #if HAVE_XPM
10178 Qxpm = intern ("xpm");
10179 staticpro (&Qxpm);
10180 #endif
10182 #if HAVE_JPEG
10183 Qjpeg = intern ("jpeg");
10184 staticpro (&Qjpeg);
10185 #endif
10187 #if HAVE_TIFF
10188 Qtiff = intern ("tiff");
10189 staticpro (&Qtiff);
10190 #endif
10192 #if HAVE_GIF
10193 Qgif = intern ("gif");
10194 staticpro (&Qgif);
10195 #endif
10197 #if HAVE_PNG
10198 Qpng = intern ("png");
10199 staticpro (&Qpng);
10200 #endif
10202 defsubr (&Sclear_image_cache);
10204 #if GLYPH_DEBUG
10205 defsubr (&Simagep);
10206 defsubr (&Slookup_image);
10207 #endif
10208 #endif /* MAC_TODO */
10210 hourglass_atimer = NULL;
10211 hourglass_shown_p = 0;
10213 defsubr (&Sx_show_tip);
10214 defsubr (&Sx_hide_tip);
10215 staticpro (&tip_timer);
10216 tip_timer = Qnil;
10218 #if 0 /* MAC_TODO */
10219 defsubr (&Sx_file_dialog);
10220 #endif
10224 void
10225 init_xfns ()
10227 image_types = NULL;
10228 Vimage_types = Qnil;
10230 define_image_type (&xbm_type);
10231 #if 0 /* NTEMACS_TODO : Image support for W32 */
10232 define_image_type (&gs_type);
10233 define_image_type (&pbm_type);
10235 #if HAVE_XPM
10236 define_image_type (&xpm_type);
10237 #endif
10239 #if HAVE_JPEG
10240 define_image_type (&jpeg_type);
10241 #endif
10243 #if HAVE_TIFF
10244 define_image_type (&tiff_type);
10245 #endif
10247 #if HAVE_GIF
10248 define_image_type (&gif_type);
10249 #endif
10251 #if HAVE_PNG
10252 define_image_type (&png_type);
10253 #endif
10254 #endif /* NTEMACS_TODO */