1 /* Graphical user interface functions for Mac OS.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
37 #include "dispextern.h"
39 #include "intervals.h"
41 #include "blockinput.h"
43 #include "termhooks.h"
48 /* #include "bitmaps/gray.xbm" */
51 static unsigned char gray_bits
[] = {
54 /*#include <commdlg.h>
55 #include <shellapi.h>*/
71 /* Macros max and min defined in lisp.h conflict with those in
72 precompiled header Carbon.h. */
76 #include <Carbon/Carbon.h>
78 #define Z (current_buffer->text->z)
80 #define free unexec_free
82 #define malloc unexec_malloc
84 #define realloc unexec_realloc
86 #define min(a, b) ((a) < (b) ? (a) : (b))
88 #define max(a, b) ((a) > (b) ? (a) : (b))
90 #define init_process emacs_init_process
91 #else /* not MAC_OSX */
94 #include <TextUtils.h>
95 #endif /* not MAC_OSX */
97 /*extern void free_frame_menubar ();
98 extern double atof ();
99 extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
100 extern int quit_char;*/
102 /* A definition of XColor for non-X frames. */
103 #ifndef HAVE_X_WINDOWS
106 unsigned short red
, green
, blue
;
112 extern char *lispy_function_keys
[];
114 /* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
115 it, and including `bitmaps/gray' more than once is a problem when
116 config.h defines `static' as an empty replacement string. */
118 int gray_bitmap_width
= gray_width
;
119 int gray_bitmap_height
= gray_height
;
120 unsigned char *gray_bitmap_bits
= gray_bits
;
122 /* The name we're using in resource queries. */
124 Lisp_Object Vx_resource_name
;
126 /* Non-zero means we're allowed to display an hourglass cursor. */
128 int display_hourglass_p
;
130 /* The background and shape of the mouse pointer, and shape when not
131 over text or in the modeline. */
133 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
134 Lisp_Object Vx_hourglass_pointer_shape
;
136 /* The shape when over mouse-sensitive text. */
138 Lisp_Object Vx_sensitive_text_pointer_shape
;
140 /* If non-nil, the pointer shape to indicate that windows can be
141 dragged horizontally. */
143 Lisp_Object Vx_window_horizontal_drag_shape
;
145 /* Color of chars displayed in cursor box. */
147 Lisp_Object Vx_cursor_fore_pixel
;
149 /* Nonzero if using Windows. */
151 static int mac_in_use
;
153 /* Non nil if no window manager is in use. */
155 Lisp_Object Vx_no_window_manager
;
157 /* Search path for bitmap files. */
159 Lisp_Object Vx_bitmap_file_path
;
161 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
163 Lisp_Object Vx_pixel_size_width_font_regexp
;
165 /* Evaluate this expression to rebuild the section of syms_of_macfns
166 that initializes and staticpros the symbols declared below. Note
167 that Emacs 18 has a bug that keeps C-x C-e from being able to
168 evaluate this expression.
171 ;; Accumulate a list of the symbols we want to initialize from the
172 ;; declarations at the top of the file.
173 (goto-char (point-min))
174 (search-forward "/\*&&& symbols declared here &&&*\/\n")
176 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
178 (cons (buffer-substring (match-beginning 1) (match-end 1))
181 (setq symbol-list (nreverse symbol-list))
182 ;; Delete the section of syms_of_... where we initialize the symbols.
183 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
184 (let ((start (point)))
185 (while (looking-at "^ Q")
187 (kill-region start (point)))
188 ;; Write a new symbol initialization section.
190 (insert (format " %s = intern (\"" (car symbol-list)))
191 (let ((start (point)))
192 (insert (substring (car symbol-list) 1))
193 (subst-char-in-region start (point) ?_ ?-))
194 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
195 (setq symbol-list (cdr symbol-list)))))
199 /*&&& symbols declared here &&&*/
200 Lisp_Object Qauto_raise
;
201 Lisp_Object Qauto_lower
;
203 Lisp_Object Qborder_color
;
204 Lisp_Object Qborder_width
;
206 Lisp_Object Qcursor_color
;
207 Lisp_Object Qcursor_type
;
208 Lisp_Object Qgeometry
;
209 Lisp_Object Qicon_left
;
210 Lisp_Object Qicon_top
;
211 Lisp_Object Qicon_type
;
212 Lisp_Object Qicon_name
;
213 Lisp_Object Qinternal_border_width
;
216 Lisp_Object Qmouse_color
;
218 Lisp_Object Qparent_id
;
219 Lisp_Object Qscroll_bar_width
;
220 Lisp_Object Qsuppress_icon
;
221 Lisp_Object Qundefined_color
;
222 Lisp_Object Qvertical_scroll_bars
;
223 Lisp_Object Qvisibility
;
224 Lisp_Object Qwindow_id
;
225 Lisp_Object Qx_frame_parameter
;
226 Lisp_Object Qx_resource_name
;
227 Lisp_Object Quser_position
;
228 Lisp_Object Quser_size
;
229 Lisp_Object Qscreen_gamma
;
230 Lisp_Object Qline_spacing
;
232 Lisp_Object Qcancel_timer
;
238 Lisp_Object Qcontrol
;
241 extern Lisp_Object Qtop
;
242 extern Lisp_Object Qdisplay
;
243 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
244 extern Lisp_Object Qtool_bar_lines
;
246 /* These are defined in frame.c. */
247 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
248 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
249 extern Lisp_Object Qtool_bar_lines
;
251 extern Lisp_Object Vwindow_system_version
;
253 Lisp_Object Qface_set_after_frame_default
;
255 extern int mac_initialized
;
257 /* Functions in macterm.c. */
258 extern void x_set_offset (struct frame
*, int, int, int);
259 extern void x_wm_set_icon_position (struct frame
*, int, int);
260 extern void x_display_cursor (struct window
*, int, int, int, int, int);
261 extern void x_set_window_size (struct frame
*, int, int, int);
262 extern void x_make_frame_visible (struct frame
*);
263 extern struct mac_display_info
*mac_term_init (Lisp_Object
, char *, char *);
264 extern struct font_info
*x_get_font_info (FRAME_PTR
, int);
265 extern struct font_info
*x_load_font (struct frame
*, char *, int);
266 extern void x_find_ccl_program (struct font_info
*);
267 extern struct font_info
*x_query_font (struct frame
*, char *);
268 extern void mac_initialize ();
270 /* compare two strings ignoring case */
273 stricmp (const char *s
, const char *t
)
275 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
278 return tolower (*s
) - tolower (*t
);
281 /* compare two strings up to n characters, ignoring case */
284 strnicmp (const char *s
, const char *t
, unsigned int n
)
286 for ( ; n
-- > 0 && tolower (*s
) == tolower (*t
); s
++, t
++)
289 return n
== 0 ? 0 : tolower (*s
) - tolower (*t
);
293 /* Error if we are not running on Mac OS. */
299 error ("Mac OS not in use or not initialized");
302 /* Nonzero if we can use mouse menus.
303 You should not call this unless HAVE_MENUS is defined. */
311 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
312 and checking validity for Mac. */
315 check_x_frame (frame
)
321 frame
= selected_frame
;
322 CHECK_LIVE_FRAME (frame
);
324 if (! FRAME_MAC_P (f
))
325 error ("non-mac frame used");
329 /* Let the user specify an display with a frame.
330 nil stands for the selected frame--or, if that is not a mac frame,
331 the first display on the list. */
333 static struct mac_display_info
*
334 check_x_display_info (frame
)
337 if (!mac_initialized
)
345 struct frame
*sf
= XFRAME (selected_frame
);
347 if (FRAME_MAC_P (sf
) && FRAME_LIVE_P (sf
))
348 return FRAME_MAC_DISPLAY_INFO (sf
);
350 return &one_mac_display_info
;
352 else if (STRINGP (frame
))
353 return x_display_info_for_name (frame
);
358 CHECK_LIVE_FRAME (frame
);
360 if (! FRAME_MAC_P (f
))
361 error ("non-mac frame used");
362 return FRAME_MAC_DISPLAY_INFO (f
);
366 /* Return the Emacs frame-object corresponding to an mac window.
367 It could be the frame's main window or an icon window. */
369 /* This function can be called during GC, so use GC_xxx type test macros. */
372 x_window_to_frame (dpyinfo
, wdesc
)
373 struct mac_display_info
*dpyinfo
;
376 Lisp_Object tail
, frame
;
379 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
382 if (!GC_FRAMEP (frame
))
385 if (!FRAME_W32_P (f
) || FRAME_MAC_DISPLAY_INFO (f
) != dpyinfo
)
387 /*if (f->output_data.w32->hourglass_window == wdesc)
390 /* MAC_TODO: Check tooltips when supported. */
391 if (FRAME_MAC_WINDOW (f
) == wdesc
)
399 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
400 id, which is just an int that this section returns. Bitmaps are
401 reference counted so they can be shared among frames.
403 Bitmap indices are guaranteed to be > 0, so a negative number can
404 be used to indicate no bitmap.
406 If you use x_create_bitmap_from_data, then you must keep track of
407 the bitmaps yourself. That is, creating a bitmap from the same
408 data more than once will not be caught. */
411 /* Functions to access the contents of a bitmap, given an id. */
414 x_bitmap_height (f
, id
)
418 return FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
422 x_bitmap_width (f
, id
)
426 return FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
429 #if 0 /* MAC_TODO : not used anywhere (?) */
431 x_bitmap_pixmap (f
, id
)
435 return (int) FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
439 /* Allocate a new bitmap record. Returns index of new record. */
442 x_allocate_bitmap_record (f
)
445 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
448 if (dpyinfo
->bitmaps
== NULL
)
450 dpyinfo
->bitmaps_size
= 10;
451 dpyinfo
->bitmaps
= (struct mac_bitmap_record
*)
452 xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct mac_bitmap_record
));
453 dpyinfo
->bitmaps_last
= 1;
457 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
458 return ++dpyinfo
->bitmaps_last
;
460 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
461 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
464 dpyinfo
->bitmaps_size
*= 2;
465 dpyinfo
->bitmaps
= (struct mac_bitmap_record
*)
466 xrealloc (dpyinfo
->bitmaps
,
467 dpyinfo
->bitmaps_size
* sizeof (struct mac_bitmap_record
));
468 return ++dpyinfo
->bitmaps_last
;
471 /* Add one reference to the reference count of the bitmap with id
475 x_reference_bitmap (f
, id
)
479 ++FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
482 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
486 x_create_bitmap_from_data (f
, bits
, width
, height
)
489 unsigned int width
, height
;
491 struct x_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
494 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
496 id
= x_allocate_bitmap_record (f
);
501 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
502 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
505 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
507 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
508 dpyinfo
->bitmaps
[id
- 1].height
= height
;
509 dpyinfo
->bitmaps
[id
- 1].width
= width
;
514 /* Create bitmap from file FILE for frame F. */
517 x_create_bitmap_from_file (f
, file
)
522 #if 0 /* MAC_TODO : bitmap support */
523 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
524 unsigned int width
, height
;
526 int xhot
, yhot
, result
, id
;
532 /* Look for an existing bitmap with the same name. */
533 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
535 if (dpyinfo
->bitmaps
[id
].refcount
536 && dpyinfo
->bitmaps
[id
].file
537 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
539 ++dpyinfo
->bitmaps
[id
].refcount
;
544 /* Search bitmap-file-path for the file, if appropriate. */
545 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, Qnil
);
548 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
553 filename
= (char *) SDATA (found
);
555 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
561 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
562 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
563 if (result
!= BitmapSuccess
)
566 id
= x_allocate_bitmap_record (f
);
567 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
568 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
569 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SCHARS (file
) + 1);
570 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
571 dpyinfo
->bitmaps
[id
- 1].height
= height
;
572 dpyinfo
->bitmaps
[id
- 1].width
= width
;
573 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
576 #endif /* MAC_TODO */
579 /* Remove reference to bitmap with id number ID. */
582 x_destroy_bitmap (f
, id
)
586 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
590 --dpyinfo
->bitmaps
[id
- 1].refcount
;
591 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
594 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= NULL
;
600 /* Free all the bitmaps for the display specified by DPYINFO. */
603 x_destroy_all_bitmaps (dpyinfo
)
604 struct mac_display_info
*dpyinfo
;
607 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
608 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
609 xfree (dpyinfo
->bitmaps
[i
].bitmap_data
);
610 dpyinfo
->bitmaps_last
= 0;
613 /* Connect the frame-parameter names for W32 frames
614 to the ways of passing the parameter values to the window system.
616 The name of a parameter, as a Lisp symbol,
617 has an `x-frame-parameter' property which is an integer in Lisp
618 but can be interpreted as an `enum x_frame_parm' in C. */
620 struct x_frame_parm_table
623 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
626 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
627 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
628 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
629 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
630 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
631 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
632 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
633 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
634 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
635 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
636 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
637 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
639 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
640 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
641 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
642 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
644 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
645 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
646 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
647 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
648 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
649 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
650 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
652 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
654 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
659 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
661 static struct x_frame_parm_table x_frame_parms
[] =
663 "auto-raise", x_set_autoraise
,
664 "auto-lower", x_set_autolower
,
665 "background-color", x_set_background_color
,
666 "border-color", x_set_border_color
,
667 "border-width", x_set_border_width
,
668 "cursor-color", x_set_cursor_color
,
669 "cursor-type", x_set_cursor_type
,
671 "foreground-color", x_set_foreground_color
,
672 "icon-name", x_set_icon_name
,
673 #if 0 /* MAC_TODO: no icons for Mac */
674 "icon-type", x_set_icon_type
,
676 "internal-border-width", x_set_internal_border_width
,
677 "menu-bar-lines", x_set_menu_bar_lines
,
678 "mouse-color", x_set_mouse_color
,
679 "name", x_explicitly_set_name
,
680 "scroll-bar-width", x_set_scroll_bar_width
,
681 "title", x_set_title
,
682 "unsplittable", x_set_unsplittable
,
683 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
684 "visibility", x_set_visibility
,
685 "tool-bar-lines", x_set_tool_bar_lines
,
686 #if 0 /* MAC_TODO: cannot set color of scroll bar on the Mac? */
687 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
688 "scroll-bar-background", x_set_scroll_bar_background
,
690 "screen-gamma", x_set_screen_gamma
,
691 "line-spacing", x_set_line_spacing
694 /* Attach the `x-frame-parameter' properties to
695 the Lisp symbol names of parameters relevant to Mac. */
698 init_x_parm_symbols ()
702 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
703 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
707 /* Change the parameters of frame F as specified by ALIST.
708 If a parameter is not specially recognized, do nothing;
709 otherwise call the `x_set_...' function for that parameter. */
712 x_set_frame_parameters (f
, alist
)
718 /* If both of these parameters are present, it's more efficient to
719 set them both at once. So we wait until we've looked at the
720 entire list before we set them. */
724 Lisp_Object left
, top
;
726 /* Same with these. */
727 Lisp_Object icon_left
, icon_top
;
729 /* Record in these vectors all the parms specified. */
733 int left_no_change
= 0, top_no_change
= 0;
734 int icon_left_no_change
= 0, icon_top_no_change
= 0;
736 struct gcpro gcpro1
, gcpro2
;
739 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
742 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
743 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
745 /* Extract parm names and values into those vectors. */
748 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
753 parms
[i
] = Fcar (elt
);
754 values
[i
] = Fcdr (elt
);
757 /* TAIL and ALIST are not used again below here. */
760 GCPRO2 (*parms
, *values
);
764 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
765 because their values appear in VALUES and strings are not valid. */
766 top
= left
= Qunbound
;
767 icon_left
= icon_top
= Qunbound
;
769 /* Provide default values for HEIGHT and WIDTH. */
770 if (FRAME_NEW_WIDTH (f
))
771 width
= FRAME_NEW_WIDTH (f
);
773 width
= FRAME_WIDTH (f
);
775 if (FRAME_NEW_HEIGHT (f
))
776 height
= FRAME_NEW_HEIGHT (f
);
778 height
= FRAME_HEIGHT (f
);
780 /* Process foreground_color and background_color before anything else.
781 They are independent of other properties, but other properties (e.g.,
782 cursor_color) are dependent upon them. */
783 for (p
= 0; p
< i
; p
++)
785 Lisp_Object prop
, val
;
789 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
791 register Lisp_Object param_index
, old_value
;
793 param_index
= Fget (prop
, Qx_frame_parameter
);
794 old_value
= get_frame_param (f
, prop
);
795 store_frame_param (f
, prop
, val
);
796 if (NATNUMP (param_index
)
797 && (XFASTINT (param_index
)
798 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
799 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
803 /* Now process them in reverse of specified order. */
804 for (i
--; i
>= 0; i
--)
806 Lisp_Object prop
, val
;
811 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
812 width
= XFASTINT (val
);
813 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
814 height
= XFASTINT (val
);
815 else if (EQ (prop
, Qtop
))
817 else if (EQ (prop
, Qleft
))
819 else if (EQ (prop
, Qicon_top
))
821 else if (EQ (prop
, Qicon_left
))
823 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
824 /* Processed above. */
828 register Lisp_Object param_index
, old_value
;
830 param_index
= Fget (prop
, Qx_frame_parameter
);
831 old_value
= get_frame_param (f
, prop
);
832 store_frame_param (f
, prop
, val
);
833 if (NATNUMP (param_index
)
834 && (XFASTINT (param_index
)
835 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
836 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
840 /* Don't die if just one of these was set. */
841 if (EQ (left
, Qunbound
))
844 if (f
->output_data
.mac
->left_pos
< 0)
846 Fcons (make_number (f
->output_data
.mac
->left_pos
),
849 XSETINT (left
, f
->output_data
.mac
->left_pos
);
851 if (EQ (top
, Qunbound
))
854 if (f
->output_data
.mac
->top_pos
< 0)
856 Fcons (make_number (f
->output_data
.mac
->top_pos
), Qnil
));
858 XSETINT (top
, f
->output_data
.mac
->top_pos
);
861 /* If one of the icon positions was not set, preserve or default it. */
862 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
864 icon_left_no_change
= 1;
865 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
866 if (NILP (icon_left
))
867 XSETINT (icon_left
, 0);
869 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
871 icon_top_no_change
= 1;
872 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
874 XSETINT (icon_top
, 0);
877 /* Don't set these parameters unless they've been explicitly
878 specified. The window might be mapped or resized while we're in
879 this function, and we don't want to override that unless the lisp
880 code has asked for it.
882 Don't set these parameters unless they actually differ from the
883 window's current parameters; the window may not actually exist
888 check_frame_size (f
, &height
, &width
);
890 XSETFRAME (frame
, f
);
892 if (width
!= FRAME_WIDTH (f
)
893 || height
!= FRAME_HEIGHT (f
)
894 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
895 Fset_frame_size (frame
, make_number (width
), make_number (height
));
897 if ((!NILP (left
) || !NILP (top
))
898 && ! (left_no_change
&& top_no_change
)
899 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.mac
->left_pos
900 && NUMBERP (top
) && XINT (top
) == f
->output_data
.mac
->top_pos
))
905 /* Record the signs. */
906 f
->output_data
.mac
->size_hint_flags
&= ~ (XNegative
| YNegative
);
907 if (EQ (left
, Qminus
))
908 f
->output_data
.mac
->size_hint_flags
|= XNegative
;
909 else if (INTEGERP (left
))
911 leftpos
= XINT (left
);
913 f
->output_data
.mac
->size_hint_flags
|= XNegative
;
915 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
916 && CONSP (XCDR (left
))
917 && INTEGERP (XCAR (XCDR (left
))))
919 leftpos
= - XINT (XCAR (XCDR (left
)));
920 f
->output_data
.mac
->size_hint_flags
|= XNegative
;
922 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
923 && CONSP (XCDR (left
))
924 && INTEGERP (XCAR (XCDR (left
))))
926 leftpos
= XINT (XCAR (XCDR (left
)));
929 if (EQ (top
, Qminus
))
930 f
->output_data
.mac
->size_hint_flags
|= YNegative
;
931 else if (INTEGERP (top
))
935 f
->output_data
.mac
->size_hint_flags
|= YNegative
;
937 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
938 && CONSP (XCDR (top
))
939 && INTEGERP (XCAR (XCDR (top
))))
941 toppos
= - XINT (XCAR (XCDR (top
)));
942 f
->output_data
.mac
->size_hint_flags
|= YNegative
;
944 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
945 && CONSP (XCDR (top
))
946 && INTEGERP (XCAR (XCDR (top
))))
948 toppos
= XINT (XCAR (XCDR (top
)));
952 /* Store the numeric value of the position. */
953 f
->output_data
.mac
->top_pos
= toppos
;
954 f
->output_data
.mac
->left_pos
= leftpos
;
956 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
958 /* Actually set that position, and convert to absolute. */
959 x_set_offset (f
, leftpos
, toppos
, -1);
962 if ((!NILP (icon_left
) || !NILP (icon_top
))
963 && ! (icon_left_no_change
&& icon_top_no_change
))
964 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
970 /* Store the screen positions of frame F into XPTR and YPTR.
971 These are the positions of the containing window manager window,
972 not Emacs's own window. */
975 x_real_positions (f
, xptr
, yptr
)
982 #ifdef TARGET_API_MAC_CARBON
986 GetWindowPortBounds (f
->output_data
.mac
->mWP
, &r
);
987 SetPt (&pt
, r
.left
, r
.top
);
989 #else /* not TARGET_API_MAC_CARBON */
991 f
->output_data
.mac
->mWP
->portRect
.left
,
992 f
->output_data
.mac
->mWP
->portRect
.top
);
993 #endif /* not TARGET_API_MAC_CARBON */
1002 /* Insert a description of internally-recorded parameters of frame X
1003 into the parameter alist *ALISTPTR that is to be given to the user.
1004 Only parameters that are specific to Mac and whose values are not
1005 correctly recorded in the frame's param_alist need to be considered
1009 x_report_frame_params (f
, alistptr
)
1011 Lisp_Object
*alistptr
;
1016 /* Represent negative positions (off the top or left screen edge)
1017 in a way that Fmodify_frame_parameters will understand correctly. */
1018 XSETINT (tem
, f
->output_data
.mac
->left_pos
);
1019 if (f
->output_data
.mac
->left_pos
>= 0)
1020 store_in_alist (alistptr
, Qleft
, tem
);
1022 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1024 XSETINT (tem
, f
->output_data
.mac
->top_pos
);
1025 if (f
->output_data
.mac
->top_pos
>= 0)
1026 store_in_alist (alistptr
, Qtop
, tem
);
1028 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1030 store_in_alist (alistptr
, Qborder_width
,
1031 make_number (f
->output_data
.mac
->border_width
));
1032 store_in_alist (alistptr
, Qinternal_border_width
,
1033 make_number (f
->output_data
.mac
->internal_border_width
));
1034 sprintf (buf
, "%ld", (long) FRAME_MAC_WINDOW (f
));
1035 store_in_alist (alistptr
, Qwindow_id
,
1036 build_string (buf
));
1037 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1038 FRAME_SAMPLE_VISIBILITY (f
);
1039 store_in_alist (alistptr
, Qvisibility
,
1040 (FRAME_VISIBLE_P (f
) ? Qt
1041 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1042 store_in_alist (alistptr
, Qdisplay
,
1043 XCAR (FRAME_MAC_DISPLAY_INFO (f
)->name_list_element
));
1046 /* The default colors for the Mac color map */
1047 typedef struct colormap_t
1049 unsigned long color
;
1053 colormap_t mac_color_map
[] =
1055 { RGB_TO_ULONG(255, 250, 250), "snow" },
1056 { RGB_TO_ULONG(248, 248, 255), "ghost white" },
1057 { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
1058 { RGB_TO_ULONG(245, 245, 245), "white smoke" },
1059 { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
1060 { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
1061 { RGB_TO_ULONG(255, 250, 240), "floral white" },
1062 { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
1063 { RGB_TO_ULONG(253, 245, 230), "old lace" },
1064 { RGB_TO_ULONG(253, 245, 230), "OldLace" },
1065 { RGB_TO_ULONG(250, 240, 230), "linen" },
1066 { RGB_TO_ULONG(250, 235, 215), "antique white" },
1067 { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
1068 { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
1069 { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
1070 { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
1071 { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
1072 { RGB_TO_ULONG(255, 228, 196), "bisque" },
1073 { RGB_TO_ULONG(255, 218, 185), "peach puff" },
1074 { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
1075 { RGB_TO_ULONG(255, 222, 173), "navajo white" },
1076 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
1077 { RGB_TO_ULONG(255, 228, 181), "moccasin" },
1078 { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
1079 { RGB_TO_ULONG(255, 255, 240), "ivory" },
1080 { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
1081 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
1082 { RGB_TO_ULONG(255, 245, 238), "seashell" },
1083 { RGB_TO_ULONG(240, 255, 240), "honeydew" },
1084 { RGB_TO_ULONG(245, 255, 250), "mint cream" },
1085 { RGB_TO_ULONG(245, 255, 250), "MintCream" },
1086 { RGB_TO_ULONG(240, 255, 255), "azure" },
1087 { RGB_TO_ULONG(240, 248, 255), "alice blue" },
1088 { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
1089 { RGB_TO_ULONG(230, 230, 250), "lavender" },
1090 { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
1091 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
1092 { RGB_TO_ULONG(255, 228, 225), "misty rose" },
1093 { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
1094 { RGB_TO_ULONG(255, 255, 255), "white" },
1095 { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
1096 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
1097 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
1098 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
1099 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
1100 { RGB_TO_ULONG(105, 105, 105), "dim gray" },
1101 { RGB_TO_ULONG(105, 105, 105), "DimGray" },
1102 { RGB_TO_ULONG(105, 105, 105), "dim grey" },
1103 { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
1104 { RGB_TO_ULONG(112, 128, 144), "slate gray" },
1105 { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
1106 { RGB_TO_ULONG(112, 128, 144), "slate grey" },
1107 { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
1108 { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
1109 { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
1110 { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
1111 { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
1112 { RGB_TO_ULONG(190, 190, 190), "gray" },
1113 { RGB_TO_ULONG(190, 190, 190), "grey" },
1114 { RGB_TO_ULONG(211, 211, 211), "light grey" },
1115 { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
1116 { RGB_TO_ULONG(211, 211, 211), "light gray" },
1117 { RGB_TO_ULONG(211, 211, 211), "LightGray" },
1118 { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
1119 { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
1120 { RGB_TO_ULONG(0 , 0 , 128), "navy" },
1121 { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
1122 { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
1123 { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
1124 { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
1125 { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
1126 { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
1127 { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
1128 { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
1129 { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
1130 { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
1131 { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
1132 { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
1133 { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
1134 { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
1135 { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
1136 { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
1137 { RGB_TO_ULONG(0 , 0 , 255), "blue" },
1138 { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
1139 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
1140 { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
1141 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
1142 { RGB_TO_ULONG(135, 206, 235), "sky blue" },
1143 { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
1144 { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
1145 { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
1146 { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
1147 { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
1148 { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
1149 { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
1150 { RGB_TO_ULONG(173, 216, 230), "light blue" },
1151 { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
1152 { RGB_TO_ULONG(176, 224, 230), "powder blue" },
1153 { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
1154 { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
1155 { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
1156 { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
1157 { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
1158 { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
1159 { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
1160 { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
1161 { RGB_TO_ULONG(0 , 255, 255), "cyan" },
1162 { RGB_TO_ULONG(224, 255, 255), "light cyan" },
1163 { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
1164 { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
1165 { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
1166 { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
1167 { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
1168 { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
1169 { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
1170 { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
1171 { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
1172 { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
1173 { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
1174 { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
1175 { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
1176 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
1177 { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
1178 { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
1179 { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
1180 { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
1181 { RGB_TO_ULONG(152, 251, 152), "pale green" },
1182 { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
1183 { RGB_TO_ULONG(0 , 255, 127), "spring green" },
1184 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
1185 { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
1186 { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
1187 { RGB_TO_ULONG(0 , 255, 0 ), "green" },
1188 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
1189 { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
1190 { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
1191 { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
1192 { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
1193 { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
1194 { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
1195 { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
1196 { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
1197 { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
1198 { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
1199 { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
1200 { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
1201 { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
1202 { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
1203 { RGB_TO_ULONG(240, 230, 140), "khaki" },
1204 { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
1205 { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
1206 { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
1207 { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
1208 { RGB_TO_ULONG(255, 255, 224), "light yellow" },
1209 { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
1210 { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
1211 { RGB_TO_ULONG(255, 215, 0 ), "gold" },
1212 { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
1213 { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
1214 { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
1215 { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
1216 { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
1217 { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
1218 { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
1219 { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
1220 { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
1221 { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
1222 { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
1223 { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
1224 { RGB_TO_ULONG(205, 133, 63 ), "peru" },
1225 { RGB_TO_ULONG(222, 184, 135), "burlywood" },
1226 { RGB_TO_ULONG(245, 245, 220), "beige" },
1227 { RGB_TO_ULONG(245, 222, 179), "wheat" },
1228 { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
1229 { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
1230 { RGB_TO_ULONG(210, 180, 140), "tan" },
1231 { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
1232 { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
1233 { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
1234 { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
1235 { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
1236 { RGB_TO_ULONG(250, 128, 114), "salmon" },
1237 { RGB_TO_ULONG(255, 160, 122), "light salmon" },
1238 { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
1239 { RGB_TO_ULONG(255, 165, 0 ), "orange" },
1240 { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
1241 { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
1242 { RGB_TO_ULONG(255, 127, 80 ), "coral" },
1243 { RGB_TO_ULONG(240, 128, 128), "light coral" },
1244 { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
1245 { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
1246 { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
1247 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
1248 { RGB_TO_ULONG(255, 0 , 0 ), "red" },
1249 { RGB_TO_ULONG(255, 105, 180), "hot pink" },
1250 { RGB_TO_ULONG(255, 105, 180), "HotPink" },
1251 { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
1252 { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
1253 { RGB_TO_ULONG(255, 192, 203), "pink" },
1254 { RGB_TO_ULONG(255, 182, 193), "light pink" },
1255 { RGB_TO_ULONG(255, 182, 193), "LightPink" },
1256 { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
1257 { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
1258 { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
1259 { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
1260 { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
1261 { RGB_TO_ULONG(208, 32 , 144), "violet red" },
1262 { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
1263 { RGB_TO_ULONG(255, 0 , 255), "magenta" },
1264 { RGB_TO_ULONG(238, 130, 238), "violet" },
1265 { RGB_TO_ULONG(221, 160, 221), "plum" },
1266 { RGB_TO_ULONG(218, 112, 214), "orchid" },
1267 { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
1268 { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
1269 { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
1270 { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
1271 { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
1272 { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
1273 { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
1274 { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
1275 { RGB_TO_ULONG(160, 32 , 240), "purple" },
1276 { RGB_TO_ULONG(147, 112, 219), "medium purple" },
1277 { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
1278 { RGB_TO_ULONG(216, 191, 216), "thistle" },
1279 { RGB_TO_ULONG(255, 250, 250), "snow1" },
1280 { RGB_TO_ULONG(238, 233, 233), "snow2" },
1281 { RGB_TO_ULONG(205, 201, 201), "snow3" },
1282 { RGB_TO_ULONG(139, 137, 137), "snow4" },
1283 { RGB_TO_ULONG(255, 245, 238), "seashell1" },
1284 { RGB_TO_ULONG(238, 229, 222), "seashell2" },
1285 { RGB_TO_ULONG(205, 197, 191), "seashell3" },
1286 { RGB_TO_ULONG(139, 134, 130), "seashell4" },
1287 { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
1288 { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
1289 { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
1290 { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
1291 { RGB_TO_ULONG(255, 228, 196), "bisque1" },
1292 { RGB_TO_ULONG(238, 213, 183), "bisque2" },
1293 { RGB_TO_ULONG(205, 183, 158), "bisque3" },
1294 { RGB_TO_ULONG(139, 125, 107), "bisque4" },
1295 { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
1296 { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
1297 { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
1298 { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
1299 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
1300 { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
1301 { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
1302 { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
1303 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
1304 { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
1305 { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
1306 { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
1307 { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
1308 { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
1309 { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
1310 { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
1311 { RGB_TO_ULONG(255, 255, 240), "ivory1" },
1312 { RGB_TO_ULONG(238, 238, 224), "ivory2" },
1313 { RGB_TO_ULONG(205, 205, 193), "ivory3" },
1314 { RGB_TO_ULONG(139, 139, 131), "ivory4" },
1315 { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
1316 { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
1317 { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
1318 { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
1319 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
1320 { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
1321 { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
1322 { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
1323 { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
1324 { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
1325 { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
1326 { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
1327 { RGB_TO_ULONG(240, 255, 255), "azure1" },
1328 { RGB_TO_ULONG(224, 238, 238), "azure2" },
1329 { RGB_TO_ULONG(193, 205, 205), "azure3" },
1330 { RGB_TO_ULONG(131, 139, 139), "azure4" },
1331 { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
1332 { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
1333 { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
1334 { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
1335 { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
1336 { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
1337 { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
1338 { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
1339 { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
1340 { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
1341 { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
1342 { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
1343 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
1344 { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
1345 { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
1346 { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
1347 { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
1348 { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
1349 { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
1350 { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
1351 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
1352 { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
1353 { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
1354 { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
1355 { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
1356 { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
1357 { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
1358 { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
1359 { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
1360 { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
1361 { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
1362 { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
1363 { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
1364 { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
1365 { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
1366 { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
1367 { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
1368 { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
1369 { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
1370 { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
1371 { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
1372 { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
1373 { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
1374 { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
1375 { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
1376 { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
1377 { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
1378 { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
1379 { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
1380 { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
1381 { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
1382 { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
1383 { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
1384 { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
1385 { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
1386 { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
1387 { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
1388 { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
1389 { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
1390 { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
1391 { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
1392 { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
1393 { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
1394 { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
1395 { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
1396 { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
1397 { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
1398 { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
1399 { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
1400 { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
1401 { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
1402 { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
1403 { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
1404 { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
1405 { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
1406 { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
1407 { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
1408 { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
1409 { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
1410 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
1411 { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
1412 { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
1413 { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
1414 { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
1415 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
1416 { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
1417 { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
1418 { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
1419 { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
1420 { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
1421 { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
1422 { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
1423 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
1424 { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
1425 { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
1426 { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
1427 { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
1428 { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
1429 { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
1430 { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
1431 { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
1432 { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
1433 { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
1434 { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
1435 { RGB_TO_ULONG(255, 246, 143), "khaki1" },
1436 { RGB_TO_ULONG(238, 230, 133), "khaki2" },
1437 { RGB_TO_ULONG(205, 198, 115), "khaki3" },
1438 { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
1439 { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
1440 { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
1441 { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
1442 { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
1443 { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
1444 { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
1445 { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
1446 { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
1447 { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
1448 { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
1449 { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
1450 { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
1451 { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
1452 { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
1453 { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
1454 { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
1455 { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
1456 { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
1457 { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
1458 { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
1459 { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
1460 { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
1461 { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
1462 { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
1463 { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
1464 { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
1465 { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
1466 { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
1467 { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
1468 { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
1469 { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
1470 { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
1471 { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
1472 { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
1473 { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
1474 { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
1475 { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
1476 { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
1477 { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
1478 { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
1479 { RGB_TO_ULONG(255, 231, 186), "wheat1" },
1480 { RGB_TO_ULONG(238, 216, 174), "wheat2" },
1481 { RGB_TO_ULONG(205, 186, 150), "wheat3" },
1482 { RGB_TO_ULONG(139, 126, 102), "wheat4" },
1483 { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
1484 { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
1485 { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
1486 { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
1487 { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
1488 { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
1489 { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
1490 { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
1491 { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
1492 { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
1493 { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
1494 { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
1495 { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
1496 { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
1497 { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
1498 { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
1499 { RGB_TO_ULONG(255, 140, 105), "salmon1" },
1500 { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
1501 { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
1502 { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
1503 { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
1504 { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
1505 { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
1506 { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
1507 { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
1508 { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
1509 { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
1510 { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
1511 { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
1512 { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
1513 { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
1514 { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
1515 { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
1516 { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
1517 { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
1518 { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
1519 { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
1520 { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
1521 { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
1522 { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
1523 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
1524 { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
1525 { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
1526 { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
1527 { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
1528 { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
1529 { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
1530 { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
1531 { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
1532 { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
1533 { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
1534 { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
1535 { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
1536 { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
1537 { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
1538 { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
1539 { RGB_TO_ULONG(255, 181, 197), "pink1" },
1540 { RGB_TO_ULONG(238, 169, 184), "pink2" },
1541 { RGB_TO_ULONG(205, 145, 158), "pink3" },
1542 { RGB_TO_ULONG(139, 99 , 108), "pink4" },
1543 { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
1544 { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
1545 { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
1546 { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
1547 { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
1548 { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
1549 { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
1550 { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
1551 { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
1552 { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
1553 { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
1554 { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
1555 { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
1556 { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
1557 { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
1558 { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
1559 { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
1560 { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
1561 { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
1562 { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
1563 { RGB_TO_ULONG(255, 131, 250), "orchid1" },
1564 { RGB_TO_ULONG(238, 122, 233), "orchid2" },
1565 { RGB_TO_ULONG(205, 105, 201), "orchid3" },
1566 { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
1567 { RGB_TO_ULONG(255, 187, 255), "plum1" },
1568 { RGB_TO_ULONG(238, 174, 238), "plum2" },
1569 { RGB_TO_ULONG(205, 150, 205), "plum3" },
1570 { RGB_TO_ULONG(139, 102, 139), "plum4" },
1571 { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
1572 { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
1573 { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
1574 { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
1575 { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
1576 { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
1577 { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
1578 { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
1579 { RGB_TO_ULONG(155, 48 , 255), "purple1" },
1580 { RGB_TO_ULONG(145, 44 , 238), "purple2" },
1581 { RGB_TO_ULONG(125, 38 , 205), "purple3" },
1582 { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
1583 { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
1584 { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
1585 { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
1586 { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
1587 { RGB_TO_ULONG(255, 225, 255), "thistle1" },
1588 { RGB_TO_ULONG(238, 210, 238), "thistle2" },
1589 { RGB_TO_ULONG(205, 181, 205), "thistle3" },
1590 { RGB_TO_ULONG(139, 123, 139), "thistle4" },
1591 { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
1592 { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
1593 { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
1594 { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
1595 { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
1596 { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
1597 { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
1598 { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
1599 { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
1600 { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
1601 { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
1602 { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
1603 { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
1604 { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
1605 { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
1606 { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
1607 { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
1608 { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
1609 { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
1610 { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
1611 { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
1612 { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
1613 { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
1614 { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
1615 { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
1616 { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
1617 { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
1618 { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
1619 { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
1620 { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
1621 { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
1622 { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
1623 { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
1624 { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
1625 { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
1626 { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
1627 { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
1628 { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
1629 { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
1630 { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
1631 { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
1632 { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
1633 { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
1634 { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
1635 { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
1636 { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
1637 { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
1638 { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
1639 { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
1640 { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
1641 { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
1642 { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
1643 { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
1644 { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
1645 { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
1646 { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
1647 { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
1648 { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
1649 { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
1650 { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
1651 { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
1652 { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
1653 { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
1654 { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
1655 { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
1656 { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
1657 { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
1658 { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
1659 { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
1660 { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
1661 { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
1662 { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
1663 { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
1664 { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
1665 { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
1666 { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
1667 { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
1668 { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
1669 { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
1670 { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
1671 { RGB_TO_ULONG(102, 102, 102), "gray40" },
1672 { RGB_TO_ULONG(102, 102, 102), "grey40" },
1673 { RGB_TO_ULONG(105, 105, 105), "gray41" },
1674 { RGB_TO_ULONG(105, 105, 105), "grey41" },
1675 { RGB_TO_ULONG(107, 107, 107), "gray42" },
1676 { RGB_TO_ULONG(107, 107, 107), "grey42" },
1677 { RGB_TO_ULONG(110, 110, 110), "gray43" },
1678 { RGB_TO_ULONG(110, 110, 110), "grey43" },
1679 { RGB_TO_ULONG(112, 112, 112), "gray44" },
1680 { RGB_TO_ULONG(112, 112, 112), "grey44" },
1681 { RGB_TO_ULONG(115, 115, 115), "gray45" },
1682 { RGB_TO_ULONG(115, 115, 115), "grey45" },
1683 { RGB_TO_ULONG(117, 117, 117), "gray46" },
1684 { RGB_TO_ULONG(117, 117, 117), "grey46" },
1685 { RGB_TO_ULONG(120, 120, 120), "gray47" },
1686 { RGB_TO_ULONG(120, 120, 120), "grey47" },
1687 { RGB_TO_ULONG(122, 122, 122), "gray48" },
1688 { RGB_TO_ULONG(122, 122, 122), "grey48" },
1689 { RGB_TO_ULONG(125, 125, 125), "gray49" },
1690 { RGB_TO_ULONG(125, 125, 125), "grey49" },
1691 { RGB_TO_ULONG(127, 127, 127), "gray50" },
1692 { RGB_TO_ULONG(127, 127, 127), "grey50" },
1693 { RGB_TO_ULONG(130, 130, 130), "gray51" },
1694 { RGB_TO_ULONG(130, 130, 130), "grey51" },
1695 { RGB_TO_ULONG(133, 133, 133), "gray52" },
1696 { RGB_TO_ULONG(133, 133, 133), "grey52" },
1697 { RGB_TO_ULONG(135, 135, 135), "gray53" },
1698 { RGB_TO_ULONG(135, 135, 135), "grey53" },
1699 { RGB_TO_ULONG(138, 138, 138), "gray54" },
1700 { RGB_TO_ULONG(138, 138, 138), "grey54" },
1701 { RGB_TO_ULONG(140, 140, 140), "gray55" },
1702 { RGB_TO_ULONG(140, 140, 140), "grey55" },
1703 { RGB_TO_ULONG(143, 143, 143), "gray56" },
1704 { RGB_TO_ULONG(143, 143, 143), "grey56" },
1705 { RGB_TO_ULONG(145, 145, 145), "gray57" },
1706 { RGB_TO_ULONG(145, 145, 145), "grey57" },
1707 { RGB_TO_ULONG(148, 148, 148), "gray58" },
1708 { RGB_TO_ULONG(148, 148, 148), "grey58" },
1709 { RGB_TO_ULONG(150, 150, 150), "gray59" },
1710 { RGB_TO_ULONG(150, 150, 150), "grey59" },
1711 { RGB_TO_ULONG(153, 153, 153), "gray60" },
1712 { RGB_TO_ULONG(153, 153, 153), "grey60" },
1713 { RGB_TO_ULONG(156, 156, 156), "gray61" },
1714 { RGB_TO_ULONG(156, 156, 156), "grey61" },
1715 { RGB_TO_ULONG(158, 158, 158), "gray62" },
1716 { RGB_TO_ULONG(158, 158, 158), "grey62" },
1717 { RGB_TO_ULONG(161, 161, 161), "gray63" },
1718 { RGB_TO_ULONG(161, 161, 161), "grey63" },
1719 { RGB_TO_ULONG(163, 163, 163), "gray64" },
1720 { RGB_TO_ULONG(163, 163, 163), "grey64" },
1721 { RGB_TO_ULONG(166, 166, 166), "gray65" },
1722 { RGB_TO_ULONG(166, 166, 166), "grey65" },
1723 { RGB_TO_ULONG(168, 168, 168), "gray66" },
1724 { RGB_TO_ULONG(168, 168, 168), "grey66" },
1725 { RGB_TO_ULONG(171, 171, 171), "gray67" },
1726 { RGB_TO_ULONG(171, 171, 171), "grey67" },
1727 { RGB_TO_ULONG(173, 173, 173), "gray68" },
1728 { RGB_TO_ULONG(173, 173, 173), "grey68" },
1729 { RGB_TO_ULONG(176, 176, 176), "gray69" },
1730 { RGB_TO_ULONG(176, 176, 176), "grey69" },
1731 { RGB_TO_ULONG(179, 179, 179), "gray70" },
1732 { RGB_TO_ULONG(179, 179, 179), "grey70" },
1733 { RGB_TO_ULONG(181, 181, 181), "gray71" },
1734 { RGB_TO_ULONG(181, 181, 181), "grey71" },
1735 { RGB_TO_ULONG(184, 184, 184), "gray72" },
1736 { RGB_TO_ULONG(184, 184, 184), "grey72" },
1737 { RGB_TO_ULONG(186, 186, 186), "gray73" },
1738 { RGB_TO_ULONG(186, 186, 186), "grey73" },
1739 { RGB_TO_ULONG(189, 189, 189), "gray74" },
1740 { RGB_TO_ULONG(189, 189, 189), "grey74" },
1741 { RGB_TO_ULONG(191, 191, 191), "gray75" },
1742 { RGB_TO_ULONG(191, 191, 191), "grey75" },
1743 { RGB_TO_ULONG(194, 194, 194), "gray76" },
1744 { RGB_TO_ULONG(194, 194, 194), "grey76" },
1745 { RGB_TO_ULONG(196, 196, 196), "gray77" },
1746 { RGB_TO_ULONG(196, 196, 196), "grey77" },
1747 { RGB_TO_ULONG(199, 199, 199), "gray78" },
1748 { RGB_TO_ULONG(199, 199, 199), "grey78" },
1749 { RGB_TO_ULONG(201, 201, 201), "gray79" },
1750 { RGB_TO_ULONG(201, 201, 201), "grey79" },
1751 { RGB_TO_ULONG(204, 204, 204), "gray80" },
1752 { RGB_TO_ULONG(204, 204, 204), "grey80" },
1753 { RGB_TO_ULONG(207, 207, 207), "gray81" },
1754 { RGB_TO_ULONG(207, 207, 207), "grey81" },
1755 { RGB_TO_ULONG(209, 209, 209), "gray82" },
1756 { RGB_TO_ULONG(209, 209, 209), "grey82" },
1757 { RGB_TO_ULONG(212, 212, 212), "gray83" },
1758 { RGB_TO_ULONG(212, 212, 212), "grey83" },
1759 { RGB_TO_ULONG(214, 214, 214), "gray84" },
1760 { RGB_TO_ULONG(214, 214, 214), "grey84" },
1761 { RGB_TO_ULONG(217, 217, 217), "gray85" },
1762 { RGB_TO_ULONG(217, 217, 217), "grey85" },
1763 { RGB_TO_ULONG(219, 219, 219), "gray86" },
1764 { RGB_TO_ULONG(219, 219, 219), "grey86" },
1765 { RGB_TO_ULONG(222, 222, 222), "gray87" },
1766 { RGB_TO_ULONG(222, 222, 222), "grey87" },
1767 { RGB_TO_ULONG(224, 224, 224), "gray88" },
1768 { RGB_TO_ULONG(224, 224, 224), "grey88" },
1769 { RGB_TO_ULONG(227, 227, 227), "gray89" },
1770 { RGB_TO_ULONG(227, 227, 227), "grey89" },
1771 { RGB_TO_ULONG(229, 229, 229), "gray90" },
1772 { RGB_TO_ULONG(229, 229, 229), "grey90" },
1773 { RGB_TO_ULONG(232, 232, 232), "gray91" },
1774 { RGB_TO_ULONG(232, 232, 232), "grey91" },
1775 { RGB_TO_ULONG(235, 235, 235), "gray92" },
1776 { RGB_TO_ULONG(235, 235, 235), "grey92" },
1777 { RGB_TO_ULONG(237, 237, 237), "gray93" },
1778 { RGB_TO_ULONG(237, 237, 237), "grey93" },
1779 { RGB_TO_ULONG(240, 240, 240), "gray94" },
1780 { RGB_TO_ULONG(240, 240, 240), "grey94" },
1781 { RGB_TO_ULONG(242, 242, 242), "gray95" },
1782 { RGB_TO_ULONG(242, 242, 242), "grey95" },
1783 { RGB_TO_ULONG(245, 245, 245), "gray96" },
1784 { RGB_TO_ULONG(245, 245, 245), "grey96" },
1785 { RGB_TO_ULONG(247, 247, 247), "gray97" },
1786 { RGB_TO_ULONG(247, 247, 247), "grey97" },
1787 { RGB_TO_ULONG(250, 250, 250), "gray98" },
1788 { RGB_TO_ULONG(250, 250, 250), "grey98" },
1789 { RGB_TO_ULONG(252, 252, 252), "gray99" },
1790 { RGB_TO_ULONG(252, 252, 252), "grey99" },
1791 { RGB_TO_ULONG(255, 255, 255), "gray100" },
1792 { RGB_TO_ULONG(255, 255, 255), "grey100" },
1793 { RGB_TO_ULONG(169, 169, 169), "dark grey" },
1794 { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
1795 { RGB_TO_ULONG(169, 169, 169), "dark gray" },
1796 { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
1797 { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
1798 { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
1799 { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
1800 { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
1801 { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
1802 { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
1803 { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
1804 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1805 { RGB_TO_ULONG(144, 238, 144), "light green" },
1806 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1810 mac_color_map_lookup (colorname
)
1813 Lisp_Object ret
= Qnil
;
1818 for (i
= 0; i
< sizeof (mac_color_map
) / sizeof (mac_color_map
[0]); i
++)
1819 if (stricmp (colorname
, mac_color_map
[i
].name
) == 0)
1821 ret
= mac_color_map
[i
].color
;
1831 x_to_mac_color (colorname
)
1834 register Lisp_Object tail
, ret
= Qnil
;
1838 if (colorname
[0] == '#')
1840 /* Could be an old-style RGB Device specification. */
1843 color
= colorname
+ 1;
1845 size
= strlen(color
);
1846 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1848 unsigned long colorval
;
1854 for (i
= 0; i
< 3; i
++)
1858 unsigned long value
;
1860 /* The check for 'x' in the following conditional takes into
1861 account the fact that strtol allows a "0x" in front of
1862 our numbers, and we don't. */
1863 if (!isxdigit(color
[0]) || color
[1] == 'x')
1867 value
= strtoul(color
, &end
, 16);
1869 if (errno
== ERANGE
|| end
- color
!= size
)
1874 value
= value
* 0x10;
1885 colorval
|= (value
<< pos
);
1896 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1899 unsigned long colorval
;
1904 color
= colorname
+ 4;
1905 for (i
= 0; i
< 3; i
++)
1908 unsigned long value
;
1910 /* The check for 'x' in the following conditional takes into
1911 account the fact that strtol allows a "0x" in front of
1912 our numbers, and we don't. */
1913 if (!isxdigit(color
[0]) || color
[1] == 'x')
1915 value
= strtoul(color
, &end
, 16);
1916 if (errno
== ERANGE
)
1918 switch (end
- color
)
1921 value
= value
* 0x10 + value
;
1934 if (value
== ULONG_MAX
)
1936 colorval
|= (value
<< pos
);
1950 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1952 /* This is an RGB Intensity specification. */
1954 unsigned long colorval
;
1959 color
= colorname
+ 5;
1960 for (i
= 0; i
< 3; i
++)
1966 value
= strtod(color
, &end
);
1967 if (errno
== ERANGE
)
1969 if (value
< 0.0 || value
> 1.0)
1971 val
= (unsigned long)(0x100 * value
);
1972 /* We used 0x100 instead of 0xFF to give an continuous
1973 range between 0.0 and 1.0 inclusive. The next statement
1974 fixes the 1.0 case. */
1977 colorval
|= (val
<< pos
);
1992 ret
= mac_color_map_lookup (colorname
);
1998 /* Gamma-correct COLOR on frame F. */
2001 gamma_correct (f
, color
)
2003 unsigned long *color
;
2007 unsigned long red
, green
, blue
;
2009 red
= pow (RED_FROM_ULONG (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5;
2010 green
= pow (GREEN_FROM_ULONG (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5;
2011 blue
= pow (BLUE_FROM_ULONG (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5;
2012 *color
= RGB_TO_ULONG (red
, green
, blue
);
2016 /* Decide if color named COLOR is valid for the display associated
2017 with the selected frame; if so, return the rgb values in COLOR_DEF.
2018 If ALLOC is nonzero, allocate a new colormap cell. */
2021 mac_defined_color (f
, color
, color_def
, alloc
)
2027 register Lisp_Object tem
;
2028 unsigned long mac_color_ref
;
2030 tem
= x_to_mac_color (color
);
2036 /* Apply gamma correction. */
2037 mac_color_ref
= XUINT (tem
);
2038 gamma_correct (f
, &mac_color_ref
);
2039 XSETINT (tem
, mac_color_ref
);
2042 color_def
->pixel
= mac_color_ref
;
2043 color_def
->red
= RED_FROM_ULONG (mac_color_ref
);
2044 color_def
->green
= GREEN_FROM_ULONG (mac_color_ref
);
2045 color_def
->blue
= BLUE_FROM_ULONG (mac_color_ref
);
2055 /* Given a string ARG naming a color, compute a pixel value from it
2056 suitable for screen F.
2057 If F is not a color screen, return DEF (default) regardless of what
2061 x_decode_color (f
, arg
, def
)
2070 if (strcmp (SDATA (arg
), "black") == 0)
2071 return BLACK_PIX_DEFAULT (f
);
2072 else if (strcmp (SDATA (arg
), "white") == 0)
2073 return WHITE_PIX_DEFAULT (f
);
2076 if ((FRAME_MAC_DISPLAY_INFO (f
)->n_planes
2077 * FRAME_MAC_DISPLAY_INFO (f
)->n_cbits
) == 1)
2081 if (mac_defined_color (f
, SDATA (arg
), &cdef
, 1))
2084 /* defined_color failed; return an ultimate default. */
2088 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
2089 the previous value of that parameter, NEW_VALUE is the new value. */
2092 x_set_line_spacing (f
, new_value
, old_value
)
2094 Lisp_Object new_value
, old_value
;
2096 if (NILP (new_value
))
2097 f
->extra_line_spacing
= 0;
2098 else if (NATNUMP (new_value
))
2099 f
->extra_line_spacing
= XFASTINT (new_value
);
2101 Fsignal (Qerror
, Fcons (build_string ("Illegal line-spacing"),
2102 Fcons (new_value
, Qnil
)));
2103 if (FRAME_VISIBLE_P (f
))
2108 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
2109 the previous value of that parameter, NEW_VALUE is the new value. */
2112 x_set_screen_gamma (f
, new_value
, old_value
)
2114 Lisp_Object new_value
, old_value
;
2116 if (NILP (new_value
))
2118 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
2119 /* The value 0.4545 is the normal viewing gamma. */
2120 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
2122 Fsignal (Qerror
, Fcons (build_string ("Illegal screen-gamma"),
2123 Fcons (new_value
, Qnil
)));
2125 clear_face_cache (0);
2129 /* Functions called only from `x_set_frame_param'
2130 to set individual parameters.
2132 If FRAME_MAC_WINDOW (f) is 0,
2133 the frame is being created and its window does not exist yet.
2134 In that case, just record the parameter's new value
2135 in the standard place; do not attempt to change the window. */
2138 x_set_foreground_color (f
, arg
, oldval
)
2140 Lisp_Object arg
, oldval
;
2142 FRAME_FOREGROUND_PIXEL (f
)
2143 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2145 if (FRAME_MAC_WINDOW (f
) != 0)
2147 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
2148 if (FRAME_VISIBLE_P (f
))
2154 x_set_background_color (f
, arg
, oldval
)
2156 Lisp_Object arg
, oldval
;
2158 FRAME_BACKGROUND_PIXEL (f
)
2159 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
2161 if (FRAME_MAC_WINDOW (f
) != 0)
2163 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
2165 if (FRAME_VISIBLE_P (f
))
2171 x_set_mouse_color (f
, arg
, oldval
)
2173 Lisp_Object arg
, oldval
;
2175 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
2179 if (!EQ (Qnil
, arg
))
2180 f
->output_data
.mac
->mouse_pixel
2181 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2182 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
2184 /* Don't let pointers be invisible. */
2185 if (mask_color
== f
->output_data
.mac
->mouse_pixel
2186 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
2187 f
->output_data
.mac
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
2189 #if 0 /* MAC_TODO : cursor changes */
2192 /* It's not okay to crash if the user selects a screwy cursor. */
2193 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
2195 if (!EQ (Qnil
, Vx_pointer_shape
))
2197 CHECK_NUMBER (Vx_pointer_shape
);
2198 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
2201 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
2202 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
2204 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
2206 CHECK_NUMBER (Vx_nontext_pointer_shape
);
2207 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2208 XINT (Vx_nontext_pointer_shape
));
2211 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
2212 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
2214 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
2216 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
2217 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2218 XINT (Vx_hourglass_pointer_shape
));
2221 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
2222 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
2224 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
2225 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
2227 CHECK_NUMBER (Vx_mode_pointer_shape
);
2228 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2229 XINT (Vx_mode_pointer_shape
));
2232 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
2233 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
2235 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
2237 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
2239 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2240 XINT (Vx_sensitive_text_pointer_shape
));
2243 cross_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
2245 if (!NILP (Vx_window_horizontal_drag_shape
))
2247 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
2248 horizontal_drag_cursor
2249 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
2250 XINT (Vx_window_horizontal_drag_shape
));
2253 horizontal_drag_cursor
2254 = XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_sb_h_double_arrow
);
2256 /* Check and report errors with the above calls. */
2257 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
2258 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
2261 XColor fore_color
, back_color
;
2263 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
2264 back_color
.pixel
= mask_color
;
2265 XQueryColor (FRAME_W32_DISPLAY (f
),
2266 DefaultColormap (FRAME_W32_DISPLAY (f
),
2267 DefaultScreen (FRAME_W32_DISPLAY (f
))),
2269 XQueryColor (FRAME_W32_DISPLAY (f
),
2270 DefaultColormap (FRAME_W32_DISPLAY (f
),
2271 DefaultScreen (FRAME_W32_DISPLAY (f
))),
2273 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
2274 &fore_color
, &back_color
);
2275 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
2276 &fore_color
, &back_color
);
2277 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
2278 &fore_color
, &back_color
);
2279 XRecolorCursor (FRAME_W32_DISPLAY (f
), cross_cursor
,
2280 &fore_color
, &back_color
);
2281 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
2282 &fore_color
, &back_color
);
2285 if (FRAME_W32_WINDOW (f
) != 0)
2286 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
2288 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
2289 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
2290 f
->output_data
.w32
->text_cursor
= cursor
;
2292 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
2293 && f
->output_data
.w32
->nontext_cursor
!= 0)
2294 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
2295 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
2297 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
2298 && f
->output_data
.w32
->hourglass_cursor
!= 0)
2299 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
2300 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
2302 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
2303 && f
->output_data
.w32
->modeline_cursor
!= 0)
2304 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
2305 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
2307 if (cross_cursor
!= f
->output_data
.w32
->cross_cursor
2308 && f
->output_data
.w32
->cross_cursor
!= 0)
2309 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->cross_cursor
);
2310 f
->output_data
.w32
->cross_cursor
= cross_cursor
;
2312 XFlush (FRAME_W32_DISPLAY (f
));
2315 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
2316 #endif /* MAC_TODO */
2320 x_set_cursor_color (f
, arg
, oldval
)
2322 Lisp_Object arg
, oldval
;
2324 unsigned long fore_pixel
;
2326 if (!NILP (Vx_cursor_fore_pixel
))
2327 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
2328 WHITE_PIX_DEFAULT (f
));
2330 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
2331 f
->output_data
.mac
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2333 /* Make sure that the cursor color differs from the background color. */
2334 if (f
->output_data
.mac
->cursor_pixel
== FRAME_BACKGROUND_PIXEL (f
))
2336 f
->output_data
.mac
->cursor_pixel
= f
->output_data
.mac
->mouse_pixel
;
2337 if (f
->output_data
.mac
->cursor_pixel
== fore_pixel
)
2338 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
2340 FRAME_FOREGROUND_PIXEL (f
) = fore_pixel
;
2342 #if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
2343 if (FRAME_MAC_WINDOW (f
) != 0)
2345 if (FRAME_VISIBLE_P (f
))
2347 x_display_cursor (f
, 0);
2348 x_display_cursor (f
, 1);
2353 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
2356 /* Set the border-color of frame F to pixel value PIX.
2357 Note that this does not fully take effect if done before
2360 x_set_border_pixel (f
, pix
)
2364 f
->output_data
.mac
->border_pixel
= pix
;
2366 if (FRAME_MAC_WINDOW (f
) != 0 && f
->output_data
.mac
->border_width
> 0)
2368 if (FRAME_VISIBLE_P (f
))
2373 /* Set the border-color of frame F to value described by ARG.
2374 ARG can be a string naming a color.
2375 The border-color is used for the border that is drawn by the server.
2376 Note that this does not fully take effect if done before
2377 F has a window; it must be redone when the window is created. */
2380 x_set_border_color (f
, arg
, oldval
)
2382 Lisp_Object arg
, oldval
;
2387 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2388 x_set_border_pixel (f
, pix
);
2389 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
2392 /* Value is the internal representation of the specified cursor type
2393 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
2394 of the bar cursor. */
2396 enum text_cursor_kinds
2397 x_specified_cursor_type (arg
, width
)
2401 enum text_cursor_kinds type
;
2408 else if (CONSP (arg
)
2409 && EQ (XCAR (arg
), Qbar
)
2410 && INTEGERP (XCDR (arg
))
2411 && XINT (XCDR (arg
)) >= 0)
2414 *width
= XINT (XCDR (arg
));
2416 else if (NILP (arg
))
2419 /* Treat anything unknown as "box cursor".
2420 It was bad to signal an error; people have trouble fixing
2421 .Xdefaults with Emacs, when it has something bad in it. */
2422 type
= FILLED_BOX_CURSOR
;
2428 x_set_cursor_type (f
, arg
, oldval
)
2430 Lisp_Object arg
, oldval
;
2434 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
2435 f
->output_data
.mac
->cursor_width
= width
;
2437 /* Make sure the cursor gets redrawn. This is overkill, but how
2438 often do people change cursor types? */
2439 update_mode_lines
++;
2442 #if 0 /* MAC_TODO: really no icon for Mac */
2444 x_set_icon_type (f
, arg
, oldval
)
2446 Lisp_Object arg
, oldval
;
2450 if (NILP (arg
) && NILP (oldval
))
2453 if (STRINGP (arg
) && STRINGP (oldval
)
2454 && EQ (Fstring_equal (oldval
, arg
), Qt
))
2457 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
2462 result
= x_bitmap_icon (f
, arg
);
2466 error ("No icon window available");
2471 #endif /* MAC_TODO */
2473 /* Return non-nil if frame F wants a bitmap icon. */
2481 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
2489 x_set_icon_name (f
, arg
, oldval
)
2491 Lisp_Object arg
, oldval
;
2497 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2500 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2505 #if 0 /* MAC_TODO */
2506 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2511 result
= x_text_icon (f
,
2512 (char *) SDATA ((!NILP (f
->icon_name
)
2521 error ("No icon window available");
2524 /* If the window was unmapped (and its icon was mapped),
2525 the new icon is not mapped, so map the window in its stead. */
2526 if (FRAME_VISIBLE_P (f
))
2528 #ifdef USE_X_TOOLKIT
2529 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2531 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2534 XFlush (FRAME_W32_DISPLAY (f
));
2536 #endif /* MAC_TODO */
2539 extern Lisp_Object
x_new_font ();
2540 extern Lisp_Object
x_new_fontset();
2543 x_set_font (f
, arg
, oldval
)
2545 Lisp_Object arg
, oldval
;
2548 Lisp_Object fontset_name
;
2550 int old_fontset
= FRAME_FONTSET(f
);
2554 fontset_name
= Fquery_fontset (arg
, Qnil
);
2557 result
= (STRINGP (fontset_name
)
2558 ? x_new_fontset (f
, SDATA (fontset_name
))
2559 : x_new_font (f
, SDATA (arg
)));
2562 if (EQ (result
, Qnil
))
2563 error ("Font `%s' is not defined", SDATA (arg
));
2564 else if (EQ (result
, Qt
))
2565 error ("The characters of the given font have varying widths");
2566 else if (STRINGP (result
))
2568 if (STRINGP (fontset_name
))
2570 /* Fontset names are built from ASCII font names, so the
2571 names may be equal despite there was a change. */
2572 if (old_fontset
== FRAME_FONTSET (f
))
2575 else if (!NILP (Fequal (result
, oldval
)))
2578 store_frame_param (f
, Qfont
, result
);
2579 recompute_basic_faces (f
);
2584 do_pending_window_change (0);
2586 /* Don't call `face-set-after-frame-default' when faces haven't been
2587 initialized yet. This is the case when called from
2588 Fx_create_frame. In that case, the X widget or window doesn't
2589 exist either, and we can end up in x_report_frame_params with a
2590 null widget which gives a segfault. */
2591 if (FRAME_FACE_CACHE (f
))
2593 XSETFRAME (frame
, f
);
2594 call1 (Qface_set_after_frame_default
, frame
);
2599 x_set_border_width (f
, arg
, oldval
)
2601 Lisp_Object arg
, oldval
;
2605 if (XINT (arg
) == f
->output_data
.mac
->border_width
)
2608 #if 0 /* MAC_TODO */
2609 if (FRAME_MAC_WINDOW (f
) != 0)
2610 error ("Cannot change the border width of a window");
2613 f
->output_data
.mac
->border_width
= XINT (arg
);
2617 x_set_internal_border_width (f
, arg
, oldval
)
2619 Lisp_Object arg
, oldval
;
2621 int old
= f
->output_data
.mac
->internal_border_width
;
2624 f
->output_data
.mac
->internal_border_width
= XINT (arg
);
2625 if (f
->output_data
.mac
->internal_border_width
< 0)
2626 f
->output_data
.mac
->internal_border_width
= 0;
2628 if (f
->output_data
.mac
->internal_border_width
== old
)
2631 if (FRAME_MAC_WINDOW (f
) != 0)
2633 x_set_window_size (f
, 0, f
->width
, f
->height
);
2634 SET_FRAME_GARBAGED (f
);
2635 do_pending_window_change (0);
2638 SET_FRAME_GARBAGED (f
);
2642 x_set_visibility (f
, value
, oldval
)
2644 Lisp_Object value
, oldval
;
2647 XSETFRAME (frame
, f
);
2650 Fmake_frame_invisible (frame
, Qt
);
2651 else if (EQ (value
, Qicon
))
2652 Ficonify_frame (frame
);
2654 Fmake_frame_visible (frame
);
2658 /* Change window heights in windows rooted in WINDOW by N lines. */
2661 x_change_window_heights (window
, n
)
2665 struct window
*w
= XWINDOW (window
);
2667 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
2668 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
2670 if (INTEGERP (w
->orig_top
))
2671 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
2672 if (INTEGERP (w
->orig_height
))
2673 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
2675 /* Handle just the top child in a vertical split. */
2676 if (!NILP (w
->vchild
))
2677 x_change_window_heights (w
->vchild
, n
);
2679 /* Adjust all children in a horizontal split. */
2680 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
2682 w
= XWINDOW (window
);
2683 x_change_window_heights (window
, n
);
2688 x_set_menu_bar_lines (f
, value
, oldval
)
2690 Lisp_Object value
, oldval
;
2693 int olines
= FRAME_MENU_BAR_LINES (f
);
2695 /* Right now, menu bars don't work properly in minibuf-only frames;
2696 most of the commands try to apply themselves to the minibuffer
2697 frame itself, and get an error because you can't switch buffers
2698 in or split the minibuffer window. */
2699 if (FRAME_MINIBUF_ONLY_P (f
))
2702 if (INTEGERP (value
))
2703 nlines
= XINT (value
);
2707 FRAME_MENU_BAR_LINES (f
) = 0;
2709 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2712 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2713 free_frame_menubar (f
);
2714 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2716 /* Adjust the frame size so that the client (text) dimensions
2717 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2719 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2720 do_pending_window_change (0);
2726 /* Set the number of lines used for the tool bar of frame F to VALUE.
2727 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2728 is the old number of tool bar lines. This function changes the
2729 height of all windows on frame F to match the new tool bar height.
2730 The frame's height doesn't change. */
2733 x_set_tool_bar_lines (f
, value
, oldval
)
2735 Lisp_Object value
, oldval
;
2737 int delta
, nlines
, root_height
;
2738 Lisp_Object root_window
;
2740 /* Treat tool bars like menu bars. */
2741 if (FRAME_MINIBUF_ONLY_P (f
))
2744 /* Use VALUE only if an integer >= 0. */
2745 if (INTEGERP (value
) && XINT (value
) >= 0)
2746 nlines
= XFASTINT (value
);
2750 /* Make sure we redisplay all windows in this frame. */
2751 ++windows_or_buffers_changed
;
2753 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2755 /* Don't resize the tool-bar to more than we have room for. */
2756 root_window
= FRAME_ROOT_WINDOW (f
);
2757 root_height
= XINT (XWINDOW (root_window
)->height
);
2758 if (root_height
- delta
< 1)
2760 delta
= root_height
- 1;
2761 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2764 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2765 x_change_window_heights (root_window
, delta
);
2768 /* We also have to make sure that the internal border at the top of
2769 the frame, below the menu bar or tool bar, is redrawn when the
2770 tool bar disappears. This is so because the internal border is
2771 below the tool bar if one is displayed, but is below the menu bar
2772 if there isn't a tool bar. The tool bar draws into the area
2773 below the menu bar. */
2774 if (FRAME_MAC_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2778 clear_current_matrices (f
);
2779 updating_frame
= NULL
;
2782 /* If the tool bar gets smaller, the internal border below it
2783 has to be cleared. It was formerly part of the display
2784 of the larger tool bar, and updating windows won't clear it. */
2787 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2788 int width
= PIXEL_WIDTH (f
);
2789 int y
= nlines
* CANON_Y_UNIT (f
);
2792 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
2793 0, y
, width
, height
, 0);
2796 if (WINDOWP (f
->tool_bar_window
))
2797 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
2802 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2805 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2806 name; if NAME is a string, set F's name to NAME and set
2807 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2809 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2810 suggesting a new name, which lisp code should override; if
2811 F->explicit_name is set, ignore the new name; otherwise, set it. */
2814 x_set_name (f
, name
, explicit)
2819 /* Make sure that requests from lisp code override requests from
2820 Emacs redisplay code. */
2823 /* If we're switching from explicit to implicit, we had better
2824 update the mode lines and thereby update the title. */
2825 if (f
->explicit_name
&& NILP (name
))
2826 update_mode_lines
= 1;
2828 f
->explicit_name
= ! NILP (name
);
2830 else if (f
->explicit_name
)
2833 /* If NAME is nil, set the name to the w32_id_name. */
2836 /* Check for no change needed in this very common case
2837 before we do any consing. */
2838 if (!strcmp (FRAME_MAC_DISPLAY_INFO (f
)->mac_id_name
,
2841 name
= build_string (FRAME_MAC_DISPLAY_INFO (f
)->mac_id_name
);
2844 CHECK_STRING (name
);
2846 /* Don't change the name if it's already NAME. */
2847 if (! NILP (Fstring_equal (name
, f
->name
)))
2852 /* For setting the frame title, the title parameter should override
2853 the name parameter. */
2854 if (! NILP (f
->title
))
2857 if (FRAME_MAC_WINDOW (f
))
2859 if (STRING_MULTIBYTE (name
))
2860 #if 0 /* MAC_TODO: encoding title string */
2861 name
= ENCODE_SYSTEM (name
);
2870 if (strlen (SDATA (name
)) < 255)
2872 strcpy (windowTitle
, SDATA (name
));
2873 c2pstr (windowTitle
);
2874 SetWTitle (FRAME_MAC_WINDOW (f
), windowTitle
);
2882 /* This function should be called when the user's lisp code has
2883 specified a name for the frame; the name will override any set by the
2886 x_explicitly_set_name (f
, arg
, oldval
)
2888 Lisp_Object arg
, oldval
;
2890 x_set_name (f
, arg
, 1);
2893 /* This function should be called by Emacs redisplay code to set the
2894 name; names set this way will never override names set by the user's
2897 x_implicitly_set_name (f
, arg
, oldval
)
2899 Lisp_Object arg
, oldval
;
2901 x_set_name (f
, arg
, 0);
2904 /* Change the title of frame F to NAME.
2905 If NAME is nil, use the frame name as the title.
2907 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2908 name; if NAME is a string, set F's name to NAME and set
2909 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2911 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2912 suggesting a new name, which lisp code should override; if
2913 F->explicit_name is set, ignore the new name; otherwise, set it. */
2916 x_set_title (f
, name
, old_name
)
2918 Lisp_Object name
, old_name
;
2920 /* Don't change the title if it's already NAME. */
2921 if (EQ (name
, f
->title
))
2924 update_mode_lines
= 1;
2931 if (FRAME_MAC_WINDOW (f
))
2933 if (STRING_MULTIBYTE (name
))
2934 #if 0 /* MAC_TODO: encoding title string */
2935 name
= ENCODE_SYSTEM (name
);
2944 if (strlen (SDATA (name
)) < 255)
2946 strcpy (windowTitle
, SDATA (name
));
2947 c2pstr (windowTitle
);
2948 SetWTitle (FRAME_MAC_WINDOW (f
), windowTitle
);
2957 x_set_autoraise (f
, arg
, oldval
)
2959 Lisp_Object arg
, oldval
;
2961 f
->auto_raise
= !EQ (Qnil
, arg
);
2965 x_set_autolower (f
, arg
, oldval
)
2967 Lisp_Object arg
, oldval
;
2969 f
->auto_lower
= !EQ (Qnil
, arg
);
2973 x_set_unsplittable (f
, arg
, oldval
)
2975 Lisp_Object arg
, oldval
;
2977 f
->no_split
= !NILP (arg
);
2981 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2983 Lisp_Object arg
, oldval
;
2985 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2986 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2987 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2988 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2990 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2992 ? vertical_scroll_bar_none
2994 ? vertical_scroll_bar_right
2995 : vertical_scroll_bar_left
);
2997 /* We set this parameter before creating the window for the
2998 frame, so we can get the geometry right from the start.
2999 However, if the window hasn't been created yet, we shouldn't
3000 call x_set_window_size. */
3001 if (FRAME_MAC_WINDOW (f
))
3002 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
3003 do_pending_window_change (0);
3008 x_set_scroll_bar_width (f
, arg
, oldval
)
3010 Lisp_Object arg
, oldval
;
3012 /* Imitate X without X Toolkit */
3014 int wid
= FONT_WIDTH (f
->output_data
.mac
->font
);
3019 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 16; /* Aqua scroll bars. */
3020 FRAME_SCROLL_BAR_COLS (f
) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) +
3022 #else /* not MAC_OSX */
3023 /* Make the actual width at least 14 pixels and a multiple of a
3025 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
3027 /* Use all of that space (aside from required margins) for the
3029 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
3030 #endif /* not MAC_OSX */
3031 if (FRAME_MAC_WINDOW (f
))
3032 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
3033 do_pending_window_change (0);
3035 else if (INTEGERP (arg
) && XINT (arg
) > 0
3036 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
3038 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
3039 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
3041 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
3042 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
3043 if (FRAME_MAC_WINDOW (f
))
3044 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
3045 do_pending_window_change (0);
3047 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
3048 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
3049 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
3052 /* Subroutines of creating an frame. */
3054 /* Make sure that Vx_resource_name is set to a reasonable value.
3055 Fix it up, or set it to `emacs' if it is too hopeless. */
3058 validate_x_resource_name ()
3061 /* Number of valid characters in the resource name. */
3063 /* Number of invalid characters in the resource name. */
3068 if (STRINGP (Vx_resource_name
))
3070 unsigned char *p
= SDATA (Vx_resource_name
);
3073 len
= SBYTES (Vx_resource_name
);
3075 /* Only letters, digits, - and _ are valid in resource names.
3076 Count the valid characters and count the invalid ones. */
3077 for (i
= 0; i
< len
; i
++)
3080 if (! ((c
>= 'a' && c
<= 'z')
3081 || (c
>= 'A' && c
<= 'Z')
3082 || (c
>= '0' && c
<= '9')
3083 || c
== '-' || c
== '_'))
3090 /* Not a string => completely invalid. */
3091 bad_count
= 5, good_count
= 0;
3093 /* If name is valid already, return. */
3097 /* If name is entirely invalid, or nearly so, use `emacs'. */
3099 || (good_count
== 1 && bad_count
> 0))
3101 Vx_resource_name
= build_string ("emacs");
3105 /* Name is partly valid. Copy it and replace the invalid characters
3106 with underscores. */
3108 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
3110 for (i
= 0; i
< len
; i
++)
3112 int c
= SREF (new, i
);
3113 if (! ((c
>= 'a' && c
<= 'z')
3114 || (c
>= 'A' && c
<= 'Z')
3115 || (c
>= '0' && c
<= '9')
3116 || c
== '-' || c
== '_'))
3122 #if 0 /* MAC_TODO: implement resource strings */
3123 extern char *x_get_string_resource ();
3125 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
3126 doc
: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
3127 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
3128 class, where INSTANCE is the name under which Emacs was invoked, or
3129 the name specified by the `-name' or `-rn' command-line arguments.
3131 The optional arguments COMPONENT and SUBCLASS add to the key and the
3132 class, respectively. You must specify both of them or neither.
3133 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
3134 and the class is `Emacs.CLASS.SUBCLASS'. */)
3135 (attribute
, class, component
, subclass
)
3136 Lisp_Object attribute
, class, component
, subclass
;
3138 register char *value
;
3142 CHECK_STRING (attribute
);
3143 CHECK_STRING (class);
3145 if (!NILP (component
))
3146 CHECK_STRING (component
);
3147 if (!NILP (subclass
))
3148 CHECK_STRING (subclass
);
3149 if (NILP (component
) != NILP (subclass
))
3150 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3152 validate_x_resource_name ();
3154 /* Allocate space for the components, the dots which separate them,
3155 and the final '\0'. Make them big enough for the worst case. */
3156 name_key
= (char *) alloca (SBYTES (Vx_resource_name
)
3157 + (STRINGP (component
)
3158 ? SBYTES (component
) : 0)
3159 + SBYTES (attribute
)
3162 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
3164 + (STRINGP (subclass
)
3165 ? SBYTES (subclass
) : 0)
3168 /* Start with emacs.FRAMENAME for the name (the specific one)
3169 and with `Emacs' for the class key (the general one). */
3170 strcpy (name_key
, SDATA (Vx_resource_name
));
3171 strcpy (class_key
, EMACS_CLASS
);
3173 strcat (class_key
, ".");
3174 strcat (class_key
, SDATA (class));
3176 if (!NILP (component
))
3178 strcat (class_key
, ".");
3179 strcat (class_key
, SDATA (subclass
));
3181 strcat (name_key
, ".");
3182 strcat (name_key
, SDATA (component
));
3185 strcat (name_key
, ".");
3186 strcat (name_key
, SDATA (attribute
));
3188 value
= x_get_string_resource (Qnil
,
3189 name_key
, class_key
);
3191 if (value
!= (char *) 0)
3192 return build_string (value
);
3197 /* Used when C code wants a resource value. */
3200 x_get_resource_string (attribute
, class)
3201 char *attribute
, *class;
3205 struct frame
*sf
= SELECTED_FRAME ();
3207 /* Allocate space for the components, the dots which separate them,
3208 and the final '\0'. */
3209 name_key
= (char *) alloca (SBYTES (Vinvocation_name
)
3210 + strlen (attribute
) + 2);
3211 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
3212 + strlen (class) + 2);
3214 sprintf (name_key
, "%s.%s",
3215 SDATA (Vinvocation_name
),
3217 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
3219 return x_get_string_resource (sf
, name_key
, class_key
);
3221 #endif /* MAC_TODO */
3223 /* Types we might convert a resource string into. */
3233 /* Return the value of parameter PARAM.
3235 First search ALIST, then Vdefault_frame_alist, then the X defaults
3236 database, using ATTRIBUTE as the attribute name and CLASS as its class.
3238 Convert the resource to the type specified by desired_type.
3240 If no default is specified, return Qunbound. If you call
3241 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
3242 and don't let it get stored in any Lisp-visible variables! */
3245 mac_get_arg (alist
, param
, attribute
, class, type
)
3246 Lisp_Object alist
, param
;
3249 enum resource_types type
;
3251 register Lisp_Object tem
;
3253 tem
= Fassq (param
, alist
);
3255 tem
= Fassq (param
, Vdefault_frame_alist
);
3259 #if 0 /* MAC_TODO: search resource also */
3262 tem
= Fx_get_resource (build_string (attribute
),
3263 build_string (class),
3271 case RES_TYPE_NUMBER
:
3272 return make_number (atoi (SDATA (tem
)));
3274 case RES_TYPE_FLOAT
:
3275 return make_float (atof (SDATA (tem
)));
3277 case RES_TYPE_BOOLEAN
:
3278 tem
= Fdowncase (tem
);
3279 if (!strcmp (SDATA (tem
), "on")
3280 || !strcmp (SDATA (tem
), "true"))
3285 case RES_TYPE_STRING
:
3288 case RES_TYPE_SYMBOL
:
3289 /* As a special case, we map the values `true' and `on'
3290 to Qt, and `false' and `off' to Qnil. */
3293 lower
= Fdowncase (tem
);
3294 if (!strcmp (SDATA (lower
), "on")
3295 || !strcmp (SDATA (lower
), "true"))
3297 else if (!strcmp (SDATA (lower
), "off")
3298 || !strcmp (SDATA (lower
), "false"))
3301 return Fintern (tem
, Qnil
);
3309 #endif /* MAC_TODO */
3315 /* Record in frame F the specified or default value according to ALIST
3316 of the parameter named PROP (a Lisp symbol).
3317 If no value is specified for PROP, look for an X default for XPROP
3318 on the frame named NAME.
3319 If that is not found either, use the value DEFLT. */
3322 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
3329 enum resource_types type
;
3333 tem
= mac_get_arg (alist
, prop
, xprop
, xclass
, type
);
3334 if (EQ (tem
, Qunbound
))
3336 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
3340 /* XParseGeometry copied from w32xfns.c */
3343 * XParseGeometry parses strings of the form
3344 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
3345 * width, height, xoffset, and yoffset are unsigned integers.
3346 * Example: "=80x24+300-49"
3347 * The equal sign is optional.
3348 * It returns a bitmask that indicates which of the four values
3349 * were actually found in the string. For each value found,
3350 * the corresponding argument is updated; for each value
3351 * not found, the corresponding argument is left unchanged.
3355 read_integer (string
, NextString
)
3356 register char *string
;
3359 register int Result
= 0;
3364 else if (*string
== '-')
3369 for (; (*string
>= '0') && (*string
<= '9'); string
++)
3371 Result
= (Result
* 10) + (*string
- '0');
3373 *NextString
= string
;
3381 XParseGeometry (string
, x
, y
, width
, height
)
3384 unsigned int *width
, *height
; /* RETURN */
3387 register char *strind
;
3388 unsigned int tempWidth
, tempHeight
;
3390 char *nextCharacter
;
3392 if ((string
== NULL
) || (*string
== '\0')) return (mask
);
3394 string
++; /* ignore possible '=' at beg of geometry spec */
3396 strind
= (char *)string
;
3397 if (*strind
!= '+' && *strind
!= '-' && *strind
!= 'x')
3399 tempWidth
= read_integer (strind
, &nextCharacter
);
3400 if (strind
== nextCharacter
)
3402 strind
= nextCharacter
;
3406 if (*strind
== 'x' || *strind
== 'X')
3409 tempHeight
= read_integer (strind
, &nextCharacter
);
3410 if (strind
== nextCharacter
)
3412 strind
= nextCharacter
;
3413 mask
|= HeightValue
;
3416 if ((*strind
== '+') || (*strind
== '-'))
3421 tempX
= -read_integer (strind
, &nextCharacter
);
3422 if (strind
== nextCharacter
)
3424 strind
= nextCharacter
;
3431 tempX
= read_integer (strind
, &nextCharacter
);
3432 if (strind
== nextCharacter
)
3434 strind
= nextCharacter
;
3437 if ((*strind
== '+') || (*strind
== '-'))
3442 tempY
= -read_integer (strind
, &nextCharacter
);
3443 if (strind
== nextCharacter
)
3445 strind
= nextCharacter
;
3452 tempY
= read_integer (strind
, &nextCharacter
);
3453 if (strind
== nextCharacter
)
3455 strind
= nextCharacter
;
3461 /* If strind isn't at the end of the string the it's an invalid
3462 geometry specification. */
3464 if (*strind
!= '\0') return (0);
3470 if (mask
& WidthValue
)
3472 if (mask
& HeightValue
)
3473 *height
= tempHeight
;
3477 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
3478 doc
: /* Parse an X-style geometry string STRING.
3479 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3480 The properties returned may include `top', `left', `height', and `width'.
3481 The value of `left' or `top' may be an integer,
3482 or a list (+ N) meaning N pixels relative to top/left corner,
3483 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3488 unsigned int width
, height
;
3491 CHECK_STRING (string
);
3493 geometry
= XParseGeometry ((char *) SDATA (string
),
3494 &x
, &y
, &width
, &height
);
3497 if (geometry
& XValue
)
3499 Lisp_Object element
;
3501 if (x
>= 0 && (geometry
& XNegative
))
3502 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
3503 else if (x
< 0 && ! (geometry
& XNegative
))
3504 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
3506 element
= Fcons (Qleft
, make_number (x
));
3507 result
= Fcons (element
, result
);
3510 if (geometry
& YValue
)
3512 Lisp_Object element
;
3514 if (y
>= 0 && (geometry
& YNegative
))
3515 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
3516 else if (y
< 0 && ! (geometry
& YNegative
))
3517 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
3519 element
= Fcons (Qtop
, make_number (y
));
3520 result
= Fcons (element
, result
);
3523 if (geometry
& WidthValue
)
3524 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
3525 if (geometry
& HeightValue
)
3526 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
3531 /* Calculate the desired size and position of this window,
3532 and return the flags saying which aspects were specified.
3534 This function does not make the coordinates positive. */
3536 #define DEFAULT_ROWS 40
3537 #define DEFAULT_COLS 80
3540 x_figure_window_size (f
, parms
)
3544 register Lisp_Object tem0
, tem1
, tem2
;
3545 long window_prompting
= 0;
3547 /* Default values if we fall through.
3548 Actually, if that happens we should get
3549 window manager prompting. */
3550 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3551 f
->height
= DEFAULT_ROWS
;
3552 /* Window managers expect that if program-specified
3553 positions are not (0,0), they're intentional, not defaults. */
3554 f
->output_data
.mac
->top_pos
= 0;
3555 f
->output_data
.mac
->left_pos
= 0;
3557 tem0
= mac_get_arg (parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3558 tem1
= mac_get_arg (parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3559 tem2
= mac_get_arg (parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3560 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3562 if (!EQ (tem0
, Qunbound
))
3564 CHECK_NUMBER (tem0
);
3565 f
->height
= XINT (tem0
);
3567 if (!EQ (tem1
, Qunbound
))
3569 CHECK_NUMBER (tem1
);
3570 SET_FRAME_WIDTH (f
, XINT (tem1
));
3572 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3573 window_prompting
|= USSize
;
3575 window_prompting
|= PSize
;
3578 f
->output_data
.mac
->vertical_scroll_bar_extra
3579 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3581 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3582 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3583 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.mac
->font
)));
3585 x_compute_fringe_widths (f
, 0);
3587 f
->output_data
.mac
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3588 f
->output_data
.mac
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3590 tem0
= mac_get_arg (parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3591 tem1
= mac_get_arg (parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3592 tem2
= mac_get_arg (parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3593 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3595 if (EQ (tem0
, Qminus
))
3597 f
->output_data
.mac
->top_pos
= 0;
3598 window_prompting
|= YNegative
;
3600 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3601 && CONSP (XCDR (tem0
))
3602 && INTEGERP (XCAR (XCDR (tem0
))))
3604 f
->output_data
.mac
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3605 window_prompting
|= YNegative
;
3607 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3608 && CONSP (XCDR (tem0
))
3609 && INTEGERP (XCAR (XCDR (tem0
))))
3611 f
->output_data
.mac
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3613 else if (EQ (tem0
, Qunbound
))
3614 f
->output_data
.mac
->top_pos
= 0;
3617 CHECK_NUMBER (tem0
);
3618 f
->output_data
.mac
->top_pos
= XINT (tem0
);
3619 if (f
->output_data
.mac
->top_pos
< 0)
3620 window_prompting
|= YNegative
;
3623 if (EQ (tem1
, Qminus
))
3625 f
->output_data
.mac
->left_pos
= 0;
3626 window_prompting
|= XNegative
;
3628 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3629 && CONSP (XCDR (tem1
))
3630 && INTEGERP (XCAR (XCDR (tem1
))))
3632 f
->output_data
.mac
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3633 window_prompting
|= XNegative
;
3635 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3636 && CONSP (XCDR (tem1
))
3637 && INTEGERP (XCAR (XCDR (tem1
))))
3639 f
->output_data
.mac
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3641 else if (EQ (tem1
, Qunbound
))
3642 f
->output_data
.mac
->left_pos
= 0;
3645 CHECK_NUMBER (tem1
);
3646 f
->output_data
.mac
->left_pos
= XINT (tem1
);
3647 if (f
->output_data
.mac
->left_pos
< 0)
3648 window_prompting
|= XNegative
;
3651 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3652 window_prompting
|= USPosition
;
3654 window_prompting
|= PPosition
;
3657 return window_prompting
;
3661 #if 0 /* MAC_TODO */
3662 /* Create and set up the Mac window for frame F. */
3665 mac_window (f
, window_prompting
, minibuffer_only
)
3667 long window_prompting
;
3668 int minibuffer_only
;
3674 /* Use the resource name as the top-level window name
3675 for looking up resources. Make a non-Lisp copy
3676 for the window manager, so GC relocation won't bother it.
3678 Elsewhere we specify the window name for the window manager. */
3681 char *str
= (char *) SDATA (Vx_resource_name
);
3682 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3683 strcpy (f
->namebuf
, str
);
3686 SetRect (&r
, f
->output_data
.mac
->left_pos
, f
->output_data
.mac
->top_pos
,
3687 f
->output_data
.mac
->left_pos
+ PIXEL_WIDTH (f
),
3688 f
->output_data
.mac
->top_pos
+ PIXEL_HEIGHT (f
));
3689 FRAME_MAC_WINDOW (f
)
3690 = NewCWindow (NULL
, &r
, "\p", 1, zoomDocProc
, (WindowPtr
) -1, 1, (long) f
->output_data
.mac
);
3692 validate_x_resource_name ();
3694 /* x_set_name normally ignores requests to set the name if the
3695 requested name is the same as the current name. This is the one
3696 place where that assumption isn't correct; f->name is set, but
3697 the server hasn't been told. */
3700 int explicit = f
->explicit_name
;
3702 f
->explicit_name
= 0;
3705 x_set_name (f
, name
, explicit);
3708 ShowWindow (FRAME_MAC_WINDOW (f
));
3712 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
3713 initialize_frame_menubar (f
);
3715 if (FRAME_MAC_WINDOW (f
) == 0)
3716 error ("Unable to create window");
3718 #endif /* MAC_TODO */
3720 /* Handle the icon stuff for this window. Perhaps later we might
3721 want an x_set_icon_position which can be called interactively as
3729 Lisp_Object icon_x
, icon_y
;
3731 /* Set the position of the icon. Note that Windows 95 groups all
3732 icons in the tray. */
3733 icon_x
= mac_get_arg (parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3734 icon_y
= mac_get_arg (parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3735 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3737 CHECK_NUMBER (icon_x
);
3738 CHECK_NUMBER (icon_y
);
3740 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3741 error ("Both left and top icon corners of icon must be specified");
3745 if (! EQ (icon_x
, Qunbound
))
3746 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3749 /* Start up iconic or window? */
3750 x_wm_set_window_state
3751 (f
, (EQ (w32_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
3755 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
3768 XGCValues gc_values
;
3772 /* Create the GC's of this frame.
3773 Note that many default values are used. */
3776 gc_values
.font
= f
->output_data
.mac
->font
;
3777 gc_values
.foreground
= FRAME_FOREGROUND_PIXEL (f
);
3778 gc_values
.background
= FRAME_BACKGROUND_PIXEL (f
);
3779 f
->output_data
.mac
->normal_gc
= XCreateGC (FRAME_MAC_DISPLAY (f
),
3780 FRAME_MAC_WINDOW (f
),
3781 GCFont
| GCForeground
| GCBackground
,
3784 /* Reverse video style. */
3785 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
3786 gc_values
.background
= FRAME_FOREGROUND_PIXEL (f
);
3787 f
->output_data
.mac
->reverse_gc
= XCreateGC (FRAME_MAC_DISPLAY (f
),
3788 FRAME_MAC_WINDOW (f
),
3789 GCFont
| GCForeground
| GCBackground
,
3792 /* Cursor has cursor-color background, background-color foreground. */
3793 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
3794 gc_values
.background
= f
->output_data
.mac
->cursor_pixel
;
3795 f
->output_data
.mac
->cursor_gc
= XCreateGC (FRAME_MAC_DISPLAY (f
),
3796 FRAME_MAC_WINDOW (f
),
3797 GCFont
| GCForeground
| GCBackground
,
3801 f
->output_data
.mac
->white_relief
.gc
= 0;
3802 f
->output_data
.mac
->black_relief
.gc
= 0;
3808 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3810 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
3811 Returns an Emacs frame object.
3812 ALIST is an alist of frame parameters.
3813 If the parameters specify that the frame should not have a minibuffer,
3814 and do not specify a specific minibuffer window to use,
3815 then `default-minibuffer-frame' must be a frame whose minibuffer can
3816 be shared by the new frame.
3818 This function is an internal primitive--use `make-frame' instead. */)
3823 Lisp_Object frame
, tem
;
3825 int minibuffer_only
= 0;
3826 long window_prompting
= 0;
3828 int count
= SPECPDL_INDEX ();
3829 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3830 Lisp_Object display
;
3831 struct mac_display_info
*dpyinfo
= NULL
;
3834 char x_frame_name
[10];
3835 static int x_frame_count
= 2; /* begins at 2 because terminal frame is F1 */
3839 /* Use this general default value to start with
3840 until we know if this frame has a specified name. */
3841 Vx_resource_name
= Vinvocation_name
;
3843 display
= mac_get_arg (parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3844 if (EQ (display
, Qunbound
))
3846 dpyinfo
= check_x_display_info (display
);
3848 kb
= dpyinfo
->kboard
;
3850 kb
= &the_only_kboard
;
3853 name
= mac_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3855 && ! EQ (name
, Qunbound
)
3857 error ("Invalid frame name--not a string or nil");
3860 Vx_resource_name
= name
;
3862 /* See if parent window is specified. */
3863 parent
= mac_get_arg (parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
3864 if (EQ (parent
, Qunbound
))
3866 if (! NILP (parent
))
3867 CHECK_NUMBER (parent
);
3869 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3870 /* No need to protect DISPLAY because that's not used after passing
3871 it to make_frame_without_minibuffer. */
3873 GCPRO4 (parms
, parent
, name
, frame
);
3874 tem
= mac_get_arg (parms
, Qminibuffer
, "minibuffer", "Minibuffer",
3876 if (EQ (tem
, Qnone
) || NILP (tem
))
3877 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3878 else if (EQ (tem
, Qonly
))
3880 f
= make_minibuffer_frame ();
3881 minibuffer_only
= 1;
3883 else if (WINDOWP (tem
))
3884 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3888 if (EQ (name
, Qunbound
) || NILP (name
))
3890 sprintf (x_frame_name
, "F%d", x_frame_count
++);
3891 f
->name
= build_string (x_frame_name
);
3892 f
->explicit_name
= 0;
3897 f
->explicit_name
= 1;
3900 XSETFRAME (frame
, f
);
3902 /* Note that X Windows does support scroll bars. */
3903 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3905 f
->output_method
= output_mac
;
3906 f
->output_data
.mac
= (struct mac_output
*) xmalloc (sizeof (struct mac_output
));
3907 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
3908 FRAME_FONTSET (f
) = -1;
3909 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
3910 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
3913 FRAME_FONTSET (f
) = -1;
3917 = mac_get_arg (parms
, Qicon_name
, "iconName", "Title", RES_TYPE_STRING
);
3918 if (! STRINGP (f
->icon_name
))
3919 f
->icon_name
= Qnil
;
3921 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
3923 FRAME_KBOARD (f
) = kb
;
3926 /* Specify the parent under which to make this window. */
3930 f
->output_data
.mac
->parent_desc
= (Window
) parent
;
3931 f
->output_data
.mac
->explicit_parent
= 1;
3935 f
->output_data
.mac
->parent_desc
= FRAME_MAC_DISPLAY_INFO (f
)->root_window
;
3936 f
->output_data
.mac
->explicit_parent
= 0;
3939 /* Set the name; the functions to which we pass f expect the name to
3941 if (EQ (name
, Qunbound
) || NILP (name
))
3943 f
->name
= build_string (dpyinfo
->mac_id_name
);
3944 f
->explicit_name
= 0;
3949 f
->explicit_name
= 1;
3950 /* use the frame's title when getting resources for this frame. */
3951 specbind (Qx_resource_name
, name
);
3954 /* Extract the window parameters from the supplied values
3955 that are needed to determine window geometry. */
3959 font
= mac_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
3962 /* First, try whatever font the caller has specified. */
3965 tem
= Fquery_fontset (font
, Qnil
);
3967 font
= x_new_fontset (f
, SDATA (tem
));
3969 font
= x_new_font (f
, SDATA (font
));
3971 /* Try out a font which we hope has bold and italic variations. */
3972 if (! STRINGP (font
))
3973 font
= x_new_font (f
, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
3974 /* If those didn't work, look for something which will at least work. */
3975 if (!STRINGP (font
))
3976 font
= x_new_font (f
, "-*-monaco-*-12-*-mac-roman");
3977 if (! STRINGP (font
))
3978 font
= x_new_font (f
, "-*-courier-*-10-*-mac-roman");
3979 if (! STRINGP (font
))
3980 error ("Cannot find any usable font");
3983 x_default_parameter (f
, parms
, Qfont
, font
,
3984 "font", "Font", RES_TYPE_STRING
);
3987 x_default_parameter (f
, parms
, Qborder_width
, make_number (0),
3988 "borderwidth", "BorderWidth", RES_TYPE_NUMBER
);
3989 /* This defaults to 2 in order to match xterm. We recognize either
3990 internalBorderWidth or internalBorder (which is what xterm calls
3992 if (NILP (Fassq (Qinternal_border_width
, parms
)))
3996 value
= mac_get_arg (parms
, Qinternal_border_width
,
3997 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
3998 if (! EQ (value
, Qunbound
))
3999 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4002 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4003 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (0),
4004 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4005 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qright
,
4006 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4008 /* Also do the stuff which must be set before the window exists. */
4009 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4010 "foreground", "Foreground", RES_TYPE_STRING
);
4011 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4012 "background", "Background", RES_TYPE_STRING
);
4013 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4014 "pointerColor", "Foreground", RES_TYPE_STRING
);
4015 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4016 "cursorColor", "Foreground", RES_TYPE_STRING
);
4017 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4018 "borderColor", "BorderColor", RES_TYPE_STRING
);
4019 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4020 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4021 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4022 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4023 x_default_parameter (f
, parms
, Qleft_fringe
, Qnil
,
4024 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4025 x_default_parameter (f
, parms
, Qright_fringe
, Qnil
,
4026 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4029 /* Init faces before x_default_parameter is called for scroll-bar
4030 parameters because that function calls x_set_scroll_bar_width,
4031 which calls change_frame_size, which calls Fset_window_buffer,
4032 which runs hooks, which call Fvertical_motion. At the end, we
4033 end up in init_iterator with a null face cache, which should not
4035 init_frame_faces (f
);
4037 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4038 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4039 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (0),
4040 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4041 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4042 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
4043 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4044 "title", "Title", RES_TYPE_STRING
);
4046 f
->output_data
.mac
->parent_desc
= FRAME_MAC_DISPLAY_INFO (f
)->root_window
;
4047 window_prompting
= x_figure_window_size (f
, parms
);
4049 if (window_prompting
& XNegative
)
4051 if (window_prompting
& YNegative
)
4052 f
->output_data
.mac
->win_gravity
= SouthEastGravity
;
4054 f
->output_data
.mac
->win_gravity
= NorthEastGravity
;
4058 if (window_prompting
& YNegative
)
4059 f
->output_data
.mac
->win_gravity
= SouthWestGravity
;
4061 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
4064 f
->output_data
.mac
->size_hint_flags
= window_prompting
;
4066 tem
= mac_get_arg (parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4067 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4069 /* Create the window. Add the tool-bar height to the initial frame
4070 height so that the user gets a text display area of the size he
4071 specified with -g or via the registry. Later changes of the
4072 tool-bar height don't change the frame size. This is done so that
4073 users can create tall Emacs frames without having to guess how
4074 tall the tool-bar will get. */
4075 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
4077 /* mac_window (f, window_prompting, minibuffer_only); */
4084 /* Now consider the frame official. */
4085 FRAME_MAC_DISPLAY_INFO (f
)->reference_count
++;
4086 Vframe_list
= Fcons (frame
, Vframe_list
);
4088 /* We need to do this after creating the window, so that the
4089 icon-creation functions can say whose icon they're describing. */
4090 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4091 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4093 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4094 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4095 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4096 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4097 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4098 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4099 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4100 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4102 /* Dimensions, especially f->height, must be done via change_frame_size.
4103 Change will not be effected unless different from the current
4109 SET_FRAME_WIDTH (f
, 0);
4110 change_frame_size (f
, height
, width
, 1, 0, 0);
4112 /* Set up faces after all frame parameters are known. */
4113 call1 (Qface_set_after_frame_default
, frame
);
4115 #if 0 /* MAC_TODO: when we have window manager hints */
4116 /* Tell the server what size and position, etc, we want, and how
4117 badly we want them. This should be done after we have the menu
4118 bar so that its size can be taken into account. */
4120 x_wm_set_size_hint (f
, window_prompting
, 0);
4124 /* Make the window appear on the frame and enable display, unless
4125 the caller says not to. However, with explicit parent, Emacs
4126 cannot control visibility, so don't try. */
4127 if (! f
->output_data
.mac
->explicit_parent
)
4129 Lisp_Object visibility
;
4131 visibility
= mac_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4132 if (EQ (visibility
, Qunbound
))
4135 #if 0 /* MAC_TODO: really no iconify on Mac */
4136 if (EQ (visibility
, Qicon
))
4137 x_iconify_frame (f
);
4140 if (! NILP (visibility
))
4141 x_make_frame_visible (f
);
4143 /* Must have been Qnil. */
4148 /* Make sure windows on this frame appear in calls to next-window
4149 and similar functions. */
4150 Vwindow_list
= Qnil
;
4152 return unbind_to (count
, frame
);
4155 /* FRAME is used only to get a handle on the X display. We don't pass the
4156 display info directly because we're called from frame.c, which doesn't
4157 know about that structure. */
4159 x_get_focus_frame (frame
)
4160 struct frame
*frame
;
4162 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4164 if (! dpyinfo
->x_focus_frame
)
4167 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4171 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4172 doc
: /* Internal function called by `color-defined-p', which see. */)
4174 Lisp_Object color
, frame
;
4177 FRAME_PTR f
= check_x_frame (frame
);
4179 CHECK_STRING (color
);
4181 if (mac_defined_color (f
, SDATA (color
), &foo
, 0))
4187 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4188 doc
: /* Internal function called by `color-values', which see. */)
4190 Lisp_Object color
, frame
;
4193 FRAME_PTR f
= check_x_frame (frame
);
4195 CHECK_STRING (color
);
4197 if (mac_defined_color (f
, SDATA (color
), &foo
, 0))
4201 rgb
[0] = make_number ((RED_FROM_ULONG (foo
.pixel
) << 8)
4202 | RED_FROM_ULONG (foo
.pixel
));
4203 rgb
[1] = make_number ((GREEN_FROM_ULONG (foo
.pixel
) << 8)
4204 | GREEN_FROM_ULONG (foo
.pixel
));
4205 rgb
[2] = make_number ((BLUE_FROM_ULONG (foo
.pixel
) << 8)
4206 | BLUE_FROM_ULONG (foo
.pixel
));
4207 return Flist (3, rgb
);
4213 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4214 doc
: /* Internal function called by `display-color-p', which see. */)
4216 Lisp_Object display
;
4218 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4220 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
4226 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4228 doc
: /* Return t if the X display supports shades of gray.
4229 Note that color displays do support shades of gray.
4230 The optional argument DISPLAY specifies which display to ask about.
4231 DISPLAY should be either a frame or a display name (a string).
4232 If omitted or nil, that stands for the selected frame's display. */)
4234 Lisp_Object display
;
4236 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4238 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
4244 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4246 doc
: /* Returns the width in pixels of the X display DISPLAY.
4247 The optional argument DISPLAY specifies which display to ask about.
4248 DISPLAY should be either a frame or a display name (a string).
4249 If omitted or nil, that stands for the selected frame's display. */)
4251 Lisp_Object display
;
4253 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4255 return make_number (dpyinfo
->width
);
4258 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4259 Sx_display_pixel_height
, 0, 1, 0,
4260 doc
: /* Returns the height in pixels of the X display DISPLAY.
4261 The optional argument DISPLAY specifies which display to ask about.
4262 DISPLAY should be either a frame or a display name (a string).
4263 If omitted or nil, that stands for the selected frame's display. */)
4265 Lisp_Object display
;
4267 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4269 return make_number (dpyinfo
->height
);
4272 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4274 doc
: /* Returns the number of bitplanes of the display DISPLAY.
4275 The optional argument DISPLAY specifies which display to ask about.
4276 DISPLAY should be either a frame or a display name (a string).
4277 If omitted or nil, that stands for the selected frame's display. */)
4279 Lisp_Object display
;
4281 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4283 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
4286 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4288 doc
: /* Returns the number of color cells of the display DISPLAY.
4289 The optional argument DISPLAY specifies which display to ask about.
4290 DISPLAY should be either a frame or a display name (a string).
4291 If omitted or nil, that stands for the selected frame's display. */)
4293 Lisp_Object display
;
4295 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4297 /* MAC_TODO: check whether this is right */
4298 return make_number ((unsigned long) (pow (2, dpyinfo
->n_cbits
)));
4301 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4302 Sx_server_max_request_size
,
4304 doc
: /* Returns the maximum request size of the server of display DISPLAY.
4305 The optional argument DISPLAY specifies which display to ask about.
4306 DISPLAY should be either a frame or a display name (a string).
4307 If omitted or nil, that stands for the selected frame's display. */)
4309 Lisp_Object display
;
4311 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4313 return make_number (1);
4316 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4317 doc
: /* Returns the vendor ID string of the Mac OS system (Apple).
4318 The optional argument DISPLAY specifies which display to ask about.
4319 DISPLAY should be either a frame or a display name (a string).
4320 If omitted or nil, that stands for the selected frame's display. */)
4322 Lisp_Object display
;
4324 return build_string ("Apple Computers");
4327 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4328 doc
: /* Returns the version numbers of the server of display DISPLAY.
4329 The value is a list of three integers: the major and minor
4330 version numbers, and the vendor-specific release
4331 number. See also the function `x-server-vendor'.
4333 The optional argument DISPLAY specifies which display to ask about.
4334 DISPLAY should be either a frame or a display name (a string).
4335 If omitted or nil, that stands for the selected frame's display. */)
4337 Lisp_Object display
;
4339 int mac_major_version
, mac_minor_version
;
4342 if (Gestalt (gestaltSystemVersion
, &response
) != noErr
)
4343 error ("Cannot get Mac OS version");
4345 mac_major_version
= (response
>> 8) & 0xf;
4346 mac_minor_version
= (response
>> 4) & 0xf;
4348 return Fcons (make_number (mac_major_version
),
4349 Fcons (make_number (mac_minor_version
), Qnil
));
4352 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4353 doc
: /* Return the number of screens on the server of display DISPLAY.
4354 The optional argument DISPLAY specifies which display to ask about.
4355 DISPLAY should be either a frame or a display name (a string).
4356 If omitted or nil, that stands for the selected frame's display. */)
4358 Lisp_Object display
;
4360 return make_number (1);
4363 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4364 doc
: /* Return the height in millimeters of the X display DISPLAY.
4365 The optional argument DISPLAY specifies which display to ask about.
4366 DISPLAY should be either a frame or a display name (a string).
4367 If omitted or nil, that stands for the selected frame's display. */)
4369 Lisp_Object display
;
4371 /* MAC_TODO: this is an approximation, and only of the main display */
4373 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4378 return make_number ((int) (v
/ 72.0 * 25.4));
4381 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4382 doc
: /* Return the width in millimeters of the X display DISPLAY.
4383 The optional argument DISPLAY specifies which display to ask about.
4384 DISPLAY should be either a frame or a display name (a string).
4385 If omitted or nil, that stands for the selected frame's display. */)
4387 Lisp_Object display
;
4389 /* MAC_TODO: this is an approximation, and only of the main display */
4391 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4396 return make_number ((int) (h
/ 72.0 * 25.4));
4399 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4400 Sx_display_backing_store
, 0, 1, 0,
4401 doc
: /* Returns an indication of whether display DISPLAY does backing store.
4402 The value may be `always', `when-mapped', or `not-useful'.
4403 The optional argument DISPLAY specifies which display to ask about.
4404 DISPLAY should be either a frame or a display name (a string).
4405 If omitted or nil, that stands for the selected frame's display. */)
4407 Lisp_Object display
;
4409 return intern ("not-useful");
4412 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4413 Sx_display_visual_class
, 0, 1, 0,
4414 doc
: /* Returns the visual class of the display DISPLAY.
4415 The value is one of the symbols `static-gray', `gray-scale',
4416 `static-color', `pseudo-color', `true-color', or `direct-color'.
4418 The optional argument DISPLAY specifies which display to ask about.
4419 DISPLAY should be either a frame or a display name (a string).
4420 If omitted or nil, that stands for the selected frame's display. */)
4422 Lisp_Object display
;
4424 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4427 switch (dpyinfo
->visual
->class)
4429 case StaticGray
: return (intern ("static-gray"));
4430 case GrayScale
: return (intern ("gray-scale"));
4431 case StaticColor
: return (intern ("static-color"));
4432 case PseudoColor
: return (intern ("pseudo-color"));
4433 case TrueColor
: return (intern ("true-color"));
4434 case DirectColor
: return (intern ("direct-color"));
4436 error ("Display has an unknown visual class");
4440 return (intern ("true-color"));
4443 DEFUN ("x-display-save-under", Fx_display_save_under
,
4444 Sx_display_save_under
, 0, 1, 0,
4445 doc
: /* Returns t if the display DISPLAY supports the save-under feature.
4446 The optional argument DISPLAY specifies which display to ask about.
4447 DISPLAY should be either a frame or a display name (a string).
4448 If omitted or nil, that stands for the selected frame's display. */)
4450 Lisp_Object display
;
4457 register struct frame
*f
;
4459 return PIXEL_WIDTH (f
);
4464 register struct frame
*f
;
4466 return PIXEL_HEIGHT (f
);
4471 register struct frame
*f
;
4473 return FONT_WIDTH (f
->output_data
.mac
->font
);
4478 register struct frame
*f
;
4480 return f
->output_data
.mac
->line_height
;
4485 register struct frame
*f
;
4487 return FRAME_MAC_DISPLAY_INFO (f
)->n_planes
;
4490 /* Return the display structure for the display named NAME.
4491 Open a new connection if necessary. */
4493 struct mac_display_info
*
4494 x_display_info_for_name (name
)
4498 struct mac_display_info
*dpyinfo
;
4500 CHECK_STRING (name
);
4502 for (dpyinfo
= &one_mac_display_info
, names
= x_display_name_list
;
4504 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4507 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4512 /* Use this general default value to start with. */
4513 Vx_resource_name
= Vinvocation_name
;
4515 validate_x_resource_name ();
4517 dpyinfo
= mac_term_init (name
, (unsigned char *) 0,
4518 (char *) SDATA (Vx_resource_name
));
4521 error ("Cannot connect to server %s", SDATA (name
));
4524 XSETFASTINT (Vwindow_system_version
, 3);
4529 #if 0 /* MAC_TODO: implement network support */
4530 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4532 doc
: /* Open a connection to a server.
4533 DISPLAY is the name of the display to connect to.
4534 Optional second arg XRM-STRING is a string of resources in xrdb format.
4535 If the optional third arg MUST-SUCCEED is non-nil,
4536 terminate Emacs if we can't open the connection. */)
4537 (display
, xrm_string
, must_succeed
)
4538 Lisp_Object display
, xrm_string
, must_succeed
;
4540 unsigned char *xrm_option
;
4541 struct mac_display_info
*dpyinfo
;
4543 CHECK_STRING (display
);
4544 if (! NILP (xrm_string
))
4545 CHECK_STRING (xrm_string
);
4547 if (! EQ (Vwindow_system
, intern ("mac")))
4548 error ("Not using Mac OS");
4550 if (! NILP (xrm_string
))
4551 xrm_option
= (unsigned char *) SDATA (xrm_string
);
4553 xrm_option
= (unsigned char *) 0;
4555 validate_x_resource_name ();
4557 /* This is what opens the connection and sets x_current_display.
4558 This also initializes many symbols, such as those used for input. */
4559 dpyinfo
= mac_term_init (display
, xrm_option
,
4560 (char *) SDATA (Vx_resource_name
));
4564 if (!NILP (must_succeed
))
4565 fatal ("Cannot connect to server %s.\n",
4568 error ("Cannot connect to server %s", SDATA (display
));
4573 XSETFASTINT (Vwindow_system_version
, 3);
4577 DEFUN ("x-close-connection", Fx_close_connection
,
4578 Sx_close_connection
, 1, 1, 0,
4579 doc
: /* Close the connection to DISPLAY's server.
4580 For DISPLAY, specify either a frame or a display name (a string).
4581 If DISPLAY is nil, that stands for the selected frame's display. */)
4583 Lisp_Object display
;
4585 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
4588 if (dpyinfo
->reference_count
> 0)
4589 error ("Display still has frames on it");
4592 /* Free the fonts in the font table. */
4593 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4594 if (dpyinfo
->font_table
[i
].name
)
4596 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
4597 xfree (dpyinfo
->font_table
[i
].full_name
);
4598 xfree (dpyinfo
->font_table
[i
].name
);
4599 x_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
4601 x_destroy_all_bitmaps (dpyinfo
);
4603 x_delete_display (dpyinfo
);
4610 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
4611 doc
: /* Return the list of display names that Emacs has connections to. */)
4614 Lisp_Object tail
, result
;
4617 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
4618 result
= Fcons (XCAR (XCAR (tail
)), result
);
4623 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
4624 doc
: /* If ON is non-nil, report errors as soon as the erring request is made.
4625 If ON is nil, allow buffering of requests.
4626 This is a noop on Mac OS systems.
4627 The optional second argument DISPLAY specifies which display to act on.
4628 DISPLAY should be either a frame or a display name (a string).
4629 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4631 Lisp_Object display
, on
;
4637 /***********************************************************************
4639 ***********************************************************************/
4641 /* Value is the number of elements of vector VECTOR. */
4643 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4645 /* List of supported image types. Use define_image_type to add new
4646 types. Use lookup_image_type to find a type for a given symbol. */
4648 static struct image_type
*image_types
;
4650 /* The symbol `image' which is the car of the lists used to represent
4653 extern Lisp_Object Qimage
;
4655 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4661 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
4662 extern Lisp_Object QCdata
, QCtype
;
4663 Lisp_Object QCascent
, QCmargin
, QCrelief
;
4664 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
4665 Lisp_Object QCindex
;
4667 /* Other symbols. */
4669 Lisp_Object Qlaplace
;
4671 /* Time in seconds after which images should be removed from the cache
4672 if not displayed. */
4674 Lisp_Object Vimage_cache_eviction_delay
;
4676 /* Function prototypes. */
4678 static void define_image_type
P_ ((struct image_type
*type
));
4679 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
4680 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
4681 static void x_laplace
P_ ((struct frame
*, struct image
*));
4682 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
4686 /* Define a new image type from TYPE. This adds a copy of TYPE to
4687 image_types and adds the symbol *TYPE->type to Vimage_types. */
4690 define_image_type (type
)
4691 struct image_type
*type
;
4693 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4694 The initialized data segment is read-only. */
4695 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
4696 bcopy (type
, p
, sizeof *p
);
4697 p
->next
= image_types
;
4699 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
4703 /* Look up image type SYMBOL, and return a pointer to its image_type
4704 structure. Value is null if SYMBOL is not a known image type. */
4706 static INLINE
struct image_type
*
4707 lookup_image_type (symbol
)
4710 struct image_type
*type
;
4712 for (type
= image_types
; type
; type
= type
->next
)
4713 if (EQ (symbol
, *type
->type
))
4720 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4721 valid image specification is a list whose car is the symbol
4722 `image', and whose rest is a property list. The property list must
4723 contain a value for key `:type'. That value must be the name of a
4724 supported image type. The rest of the property list depends on the
4728 valid_image_p (object
)
4733 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
4735 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
4736 struct image_type
*type
= lookup_image_type (symbol
);
4739 valid_p
= type
->valid_p (object
);
4746 /* Log error message with format string FORMAT and argument ARG.
4747 Signaling an error, e.g. when an image cannot be loaded, is not a
4748 good idea because this would interrupt redisplay, and the error
4749 message display would lead to another redisplay. This function
4750 therefore simply displays a message. */
4753 image_error (format
, arg1
, arg2
)
4755 Lisp_Object arg1
, arg2
;
4757 add_to_log (format
, arg1
, arg2
);
4762 /***********************************************************************
4763 Image specifications
4764 ***********************************************************************/
4766 enum image_value_type
4768 IMAGE_DONT_CHECK_VALUE_TYPE
,
4771 IMAGE_POSITIVE_INTEGER_VALUE
,
4772 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
4773 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
4775 IMAGE_INTEGER_VALUE
,
4776 IMAGE_FUNCTION_VALUE
,
4781 /* Structure used when parsing image specifications. */
4783 struct image_keyword
4785 /* Name of keyword. */
4788 /* The type of value allowed. */
4789 enum image_value_type type
;
4791 /* Non-zero means key must be present. */
4794 /* Used to recognize duplicate keywords in a property list. */
4797 /* The value that was found. */
4802 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
4804 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
4807 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
4808 has the format (image KEYWORD VALUE ...). One of the keyword/
4809 value pairs must be `:type TYPE'. KEYWORDS is a vector of
4810 image_keywords structures of size NKEYWORDS describing other
4811 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
4814 parse_image_spec (spec
, keywords
, nkeywords
, type
)
4816 struct image_keyword
*keywords
;
4823 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
4826 plist
= XCDR (spec
);
4827 while (CONSP (plist
))
4829 Lisp_Object key
, value
;
4831 /* First element of a pair must be a symbol. */
4833 plist
= XCDR (plist
);
4837 /* There must follow a value. */
4840 value
= XCAR (plist
);
4841 plist
= XCDR (plist
);
4843 /* Find key in KEYWORDS. Error if not found. */
4844 for (i
= 0; i
< nkeywords
; ++i
)
4845 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
4851 /* Record that we recognized the keyword. If a keywords
4852 was found more than once, it's an error. */
4853 keywords
[i
].value
= value
;
4854 ++keywords
[i
].count
;
4856 if (keywords
[i
].count
> 1)
4859 /* Check type of value against allowed type. */
4860 switch (keywords
[i
].type
)
4862 case IMAGE_STRING_VALUE
:
4863 if (!STRINGP (value
))
4867 case IMAGE_SYMBOL_VALUE
:
4868 if (!SYMBOLP (value
))
4872 case IMAGE_POSITIVE_INTEGER_VALUE
:
4873 if (!INTEGERP (value
) || XINT (value
) <= 0)
4877 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
4878 if (INTEGERP (value
) && XINT (value
) >= 0)
4881 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
4882 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
4886 case IMAGE_ASCENT_VALUE
:
4887 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
4889 else if (INTEGERP (value
)
4890 && XINT (value
) >= 0
4891 && XINT (value
) <= 100)
4895 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
4896 if (!INTEGERP (value
) || XINT (value
) < 0)
4900 case IMAGE_DONT_CHECK_VALUE_TYPE
:
4903 case IMAGE_FUNCTION_VALUE
:
4904 value
= indirect_function (value
);
4906 || COMPILEDP (value
)
4907 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
4911 case IMAGE_NUMBER_VALUE
:
4912 if (!INTEGERP (value
) && !FLOATP (value
))
4916 case IMAGE_INTEGER_VALUE
:
4917 if (!INTEGERP (value
))
4921 case IMAGE_BOOL_VALUE
:
4922 if (!NILP (value
) && !EQ (value
, Qt
))
4931 if (EQ (key
, QCtype
) && !EQ (type
, value
))
4935 /* Check that all mandatory fields are present. */
4936 for (i
= 0; i
< nkeywords
; ++i
)
4937 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
4940 return NILP (plist
);
4944 /* Return the value of KEY in image specification SPEC. Value is nil
4945 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
4946 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
4949 image_spec_value (spec
, key
, found
)
4950 Lisp_Object spec
, key
;
4955 xassert (valid_image_p (spec
));
4957 for (tail
= XCDR (spec
);
4958 CONSP (tail
) && CONSP (XCDR (tail
));
4959 tail
= XCDR (XCDR (tail
)))
4961 if (EQ (XCAR (tail
), key
))
4965 return XCAR (XCDR (tail
));
4977 /***********************************************************************
4978 Image type independent image structures
4979 ***********************************************************************/
4981 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
4982 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
4985 /* Allocate and return a new image structure for image specification
4986 SPEC. SPEC has a hash value of HASH. */
4988 static struct image
*
4989 make_image (spec
, hash
)
4993 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
4995 xassert (valid_image_p (spec
));
4996 bzero (img
, sizeof *img
);
4997 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
4998 xassert (img
->type
!= NULL
);
5000 img
->data
.lisp_val
= Qnil
;
5001 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5007 /* Free image IMG which was used on frame F, including its resources. */
5016 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5018 /* Remove IMG from the hash table of its cache. */
5020 img
->prev
->next
= img
->next
;
5022 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5025 img
->next
->prev
= img
->prev
;
5027 c
->images
[img
->id
] = NULL
;
5029 /* Free resources, then free IMG. */
5030 img
->type
->free (f
, img
);
5036 /* Prepare image IMG for display on frame F. Must be called before
5037 drawing an image. */
5040 prepare_image_for_display (f
, img
)
5046 /* We're about to display IMG, so set its timestamp to `now'. */
5048 img
->timestamp
= EMACS_SECS (t
);
5050 /* If IMG doesn't have a pixmap yet, load it now, using the image
5051 type dependent loader function. */
5052 if (img
->pixmap
== 0 && !img
->load_failed_p
)
5053 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5057 /* Value is the number of pixels for the ascent of image IMG when
5058 drawn in face FACE. */
5061 image_ascent (img
, face
)
5065 int height
= img
->height
+ img
->vmargin
;
5068 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5071 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
5072 - FONT_BASE(face
->font
)) / 2;
5074 ascent
= height
/ 2;
5077 ascent
= height
* img
->ascent
/ 100.0;
5084 /***********************************************************************
5085 Helper functions for X image types
5086 ***********************************************************************/
5088 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5089 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5091 Lisp_Object color_name
,
5092 unsigned long dflt
));
5094 /* Free X resources of image IMG which is used on frame F. */
5097 x_clear_image (f
, img
)
5101 #if 0 /* MAC_TODO: W32 image support */
5106 XFreePixmap (NULL
, img
->pixmap
);
5113 int class = FRAME_W32_DISPLAY_INFO (f
)->visual
->class;
5115 /* If display has an immutable color map, freeing colors is not
5116 necessary and some servers don't allow it. So don't do it. */
5117 if (class != StaticColor
5118 && class != StaticGray
5119 && class != TrueColor
)
5123 cmap
= DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f
)->screen
);
5124 XFreeColors (FRAME_W32_DISPLAY (f
), cmap
, img
->colors
,
5129 xfree (img
->colors
);
5133 #endif /* MAC_TODO */
5137 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5138 cannot be allocated, use DFLT. Add a newly allocated color to
5139 IMG->colors, so that it can be freed again. Value is the pixel
5142 static unsigned long
5143 x_alloc_image_color (f
, img
, color_name
, dflt
)
5146 Lisp_Object color_name
;
5149 #if 0 /* MAC_TODO: allocing colors. */
5151 unsigned long result
;
5153 xassert (STRINGP (color_name
));
5155 if (w32_defined_color (f
, SDATA (color_name
), &color
, 1))
5157 /* This isn't called frequently so we get away with simply
5158 reallocating the color vector to the needed size, here. */
5161 (unsigned long *) xrealloc (img
->colors
,
5162 img
->ncolors
* sizeof *img
->colors
);
5163 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5164 result
= color
.pixel
;
5169 #endif /* MAC_TODO */
5175 /***********************************************************************
5177 ***********************************************************************/
5179 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5182 /* Return a new, initialized image cache that is allocated from the
5183 heap. Call free_image_cache to free an image cache. */
5185 struct image_cache
*
5188 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5191 bzero (c
, sizeof *c
);
5193 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5194 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5195 c
->buckets
= (struct image
**) xmalloc (size
);
5196 bzero (c
->buckets
, size
);
5201 /* Free image cache of frame F. Be aware that X frames share images
5205 free_image_cache (f
)
5208 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5213 /* Cache should not be referenced by any frame when freed. */
5214 xassert (c
->refcount
== 0);
5216 for (i
= 0; i
< c
->used
; ++i
)
5217 free_image (f
, c
->images
[i
]);
5221 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5226 /* Clear image cache of frame F. FORCE_P non-zero means free all
5227 images. FORCE_P zero means clear only images that haven't been
5228 displayed for some time. Should be called from time to time to
5229 reduce the number of loaded images. If image-eviction-seconds is
5230 non-nil, this frees images in the cache which weren't displayed for
5231 at least that many seconds. */
5234 clear_image_cache (f
, force_p
)
5238 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5240 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5244 int i
, any_freed_p
= 0;
5247 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5249 for (i
= 0; i
< c
->used
; ++i
)
5251 struct image
*img
= c
->images
[i
];
5254 || (img
->timestamp
> old
)))
5256 free_image (f
, img
);
5261 /* We may be clearing the image cache because, for example,
5262 Emacs was iconified for a longer period of time. In that
5263 case, current matrices may still contain references to
5264 images freed above. So, clear these matrices. */
5267 clear_current_matrices (f
);
5268 ++windows_or_buffers_changed
;
5274 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5276 doc
: /* Clear the image cache of FRAME.
5277 FRAME nil or omitted means use the selected frame.
5278 FRAME t means clear the image caches of all frames. */)
5286 FOR_EACH_FRAME (tail
, frame
)
5287 if (FRAME_MAC_P (XFRAME (frame
)))
5288 clear_image_cache (XFRAME (frame
), 1);
5291 clear_image_cache (check_x_frame (frame
), 1);
5297 /* Return the id of image with Lisp specification SPEC on frame F.
5298 SPEC must be a valid Lisp image specification (see valid_image_p). */
5301 lookup_image (f
, spec
)
5305 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5309 struct gcpro gcpro1
;
5312 /* F must be a window-system frame, and SPEC must be a valid image
5314 xassert (FRAME_WINDOW_P (f
));
5315 xassert (valid_image_p (spec
));
5319 /* Look up SPEC in the hash table of the image cache. */
5320 hash
= sxhash (spec
, 0);
5321 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5323 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
5324 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
5327 /* If not found, create a new image and cache it. */
5331 img
= make_image (spec
, hash
);
5332 cache_image (f
, img
);
5333 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5334 xassert (!interrupt_input_blocked
);
5336 /* If we can't load the image, and we don't have a width and
5337 height, use some arbitrary width and height so that we can
5338 draw a rectangle for it. */
5339 if (img
->load_failed_p
)
5343 value
= image_spec_value (spec
, QCwidth
, NULL
);
5344 img
->width
= (INTEGERP (value
)
5345 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
5346 value
= image_spec_value (spec
, QCheight
, NULL
);
5347 img
->height
= (INTEGERP (value
)
5348 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
5352 /* Handle image type independent image attributes
5353 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
5354 Lisp_Object ascent
, margin
, relief
;
5356 ascent
= image_spec_value (spec
, QCascent
, NULL
);
5357 if (INTEGERP (ascent
))
5358 img
->ascent
= XFASTINT (ascent
);
5359 else if (EQ (ascent
, Qcenter
))
5360 img
->ascent
= CENTERED_IMAGE_ASCENT
;
5362 margin
= image_spec_value (spec
, QCmargin
, NULL
);
5363 if (INTEGERP (margin
) && XINT (margin
) >= 0)
5364 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
5365 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
5366 && INTEGERP (XCDR (margin
)))
5368 if (XINT (XCAR (margin
)) > 0)
5369 img
->hmargin
= XFASTINT (XCAR (margin
));
5370 if (XINT (XCDR (margin
)) > 0)
5371 img
->vmargin
= XFASTINT (XCDR (margin
));
5374 relief
= image_spec_value (spec
, QCrelief
, NULL
);
5375 if (INTEGERP (relief
))
5377 img
->relief
= XINT (relief
);
5378 img
->hmargin
+= abs (img
->relief
);
5379 img
->vmargin
+= abs (img
->relief
);
5384 /* We're using IMG, so set its timestamp to `now'. */
5385 EMACS_GET_TIME (now
);
5386 img
->timestamp
= EMACS_SECS (now
);
5390 /* Value is the image id. */
5395 /* Cache image IMG in the image cache of frame F. */
5398 cache_image (f
, img
)
5402 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5405 /* Find a free slot in c->images. */
5406 for (i
= 0; i
< c
->used
; ++i
)
5407 if (c
->images
[i
] == NULL
)
5410 /* If no free slot found, maybe enlarge c->images. */
5411 if (i
== c
->used
&& c
->used
== c
->size
)
5414 c
->images
= (struct image
**) xrealloc (c
->images
,
5415 c
->size
* sizeof *c
->images
);
5418 /* Add IMG to c->images, and assign IMG an id. */
5424 /* Add IMG to the cache's hash table. */
5425 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5426 img
->next
= c
->buckets
[i
];
5428 img
->next
->prev
= img
;
5430 c
->buckets
[i
] = img
;
5434 /* Call FN on every image in the image cache of frame F. Used to mark
5435 Lisp Objects in the image cache. */
5438 forall_images_in_image_cache (f
, fn
)
5440 void (*fn
) P_ ((struct image
*img
));
5442 if (FRAME_LIVE_P (f
) && FRAME_MAC_P (f
))
5444 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5448 for (i
= 0; i
< c
->used
; ++i
)
5457 /***********************************************************************
5459 ***********************************************************************/
5461 #if 0 /* MAC_TODO: Mac specific image code. */
5463 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
5464 XImage
**, Pixmap
*));
5465 static void x_destroy_x_image
P_ ((XImage
*));
5466 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
5469 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5470 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5471 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5472 via xmalloc. Print error messages via image_error if an error
5473 occurs. Value is non-zero if successful. */
5476 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
5478 int width
, height
, depth
;
5482 #if 0 /* MAC_TODO: Image support for Mac */
5483 Display
*display
= FRAME_W32_DISPLAY (f
);
5484 Screen
*screen
= FRAME_X_SCREEN (f
);
5485 Window window
= FRAME_W32_WINDOW (f
);
5487 xassert (interrupt_input_blocked
);
5490 depth
= DefaultDepthOfScreen (screen
);
5491 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
5492 depth
, ZPixmap
, 0, NULL
, width
, height
,
5493 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
5496 image_error ("Unable to allocate X image", Qnil
, Qnil
);
5500 /* Allocate image raster. */
5501 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
5503 /* Allocate a pixmap of the same size. */
5504 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
5507 x_destroy_x_image (*ximg
);
5509 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
5512 #endif /* MAC_TODO */
5517 /* Destroy XImage XIMG. Free XIMG->data. */
5520 x_destroy_x_image (ximg
)
5523 xassert (interrupt_input_blocked
);
5528 XDestroyImage (ximg
);
5533 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5534 are width and height of both the image and pixmap. */
5537 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
5544 xassert (interrupt_input_blocked
);
5545 gc
= XCreateGC (NULL
, pixmap
, 0, NULL
);
5546 XPutImage (NULL
, pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
5550 #endif /* MAC_TODO */
5553 /***********************************************************************
5555 ***********************************************************************/
5557 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
5559 /* Find image file FILE. Look in data-directory, then
5560 x-bitmap-file-path. Value is the full name of the file found, or
5561 nil if not found. */
5564 x_find_image_file (file
)
5567 Lisp_Object file_found
, search_path
;
5568 struct gcpro gcpro1
, gcpro2
;
5572 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
5573 GCPRO2 (file_found
, search_path
);
5575 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5576 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
5588 /***********************************************************************
5590 ***********************************************************************/
5592 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
5593 static int xbm_load_image_from_file
P_ ((struct frame
*f
, struct image
*img
,
5595 static int xbm_image_p
P_ ((Lisp_Object object
));
5596 static int xbm_read_bitmap_file_data
P_ ((char *, int *, int *,
5600 /* Indices of image specification fields in xbm_format, below. */
5602 enum xbm_keyword_index
5619 /* Vector of image_keyword structures describing the format
5620 of valid XBM image specifications. */
5622 static struct image_keyword xbm_format
[XBM_LAST
] =
5624 {":type", IMAGE_SYMBOL_VALUE
, 1},
5625 {":file", IMAGE_STRING_VALUE
, 0},
5626 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
5627 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
5628 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5629 {":foreground", IMAGE_STRING_VALUE
, 0},
5630 {":background", IMAGE_STRING_VALUE
, 0},
5631 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
5632 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5633 {":relief", IMAGE_INTEGER_VALUE
, 0},
5634 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5635 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
5638 /* Structure describing the image type XBM. */
5640 static struct image_type xbm_type
=
5649 /* Tokens returned from xbm_scan. */
5658 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5659 A valid specification is a list starting with the symbol `image'
5660 The rest of the list is a property list which must contain an
5663 If the specification specifies a file to load, it must contain
5664 an entry `:file FILENAME' where FILENAME is a string.
5666 If the specification is for a bitmap loaded from memory it must
5667 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5668 WIDTH and HEIGHT are integers > 0. DATA may be:
5670 1. a string large enough to hold the bitmap data, i.e. it must
5671 have a size >= (WIDTH + 7) / 8 * HEIGHT
5673 2. a bool-vector of size >= WIDTH * HEIGHT
5675 3. a vector of strings or bool-vectors, one for each line of the
5678 Both the file and data forms may contain the additional entries
5679 `:background COLOR' and `:foreground COLOR'. If not present,
5680 foreground and background of the frame on which the image is
5681 displayed, is used. */
5684 xbm_image_p (object
)
5687 struct image_keyword kw
[XBM_LAST
];
5689 bcopy (xbm_format
, kw
, sizeof kw
);
5690 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
5693 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
5695 if (kw
[XBM_FILE
].count
)
5697 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
5705 /* Entries for `:width', `:height' and `:data' must be present. */
5706 if (!kw
[XBM_WIDTH
].count
5707 || !kw
[XBM_HEIGHT
].count
5708 || !kw
[XBM_DATA
].count
)
5711 data
= kw
[XBM_DATA
].value
;
5712 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
5713 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
5715 /* Check type of data, and width and height against contents of
5721 /* Number of elements of the vector must be >= height. */
5722 if (XVECTOR (data
)->size
< height
)
5725 /* Each string or bool-vector in data must be large enough
5726 for one line of the image. */
5727 for (i
= 0; i
< height
; ++i
)
5729 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
5734 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
5737 else if (BOOL_VECTOR_P (elt
))
5739 if (XBOOL_VECTOR (elt
)->size
< width
)
5746 else if (STRINGP (data
))
5749 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
5752 else if (BOOL_VECTOR_P (data
))
5754 if (XBOOL_VECTOR (data
)->size
< width
* height
)
5761 /* Baseline must be a value between 0 and 100 (a percentage). */
5762 if (kw
[XBM_ASCENT
].count
5763 && XFASTINT (kw
[XBM_ASCENT
].value
) > 100)
5770 /* Scan a bitmap file. FP is the stream to read from. Value is
5771 either an enumerator from enum xbm_token, or a character for a
5772 single-character token, or 0 at end of file. If scanning an
5773 identifier, store the lexeme of the identifier in SVAL. If
5774 scanning a number, store its value in *IVAL. */
5777 xbm_scan (fp
, sval
, ival
)
5784 /* Skip white space. */
5785 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
5790 else if (isdigit (c
))
5792 int value
= 0, digit
;
5797 if (c
== 'x' || c
== 'X')
5799 while ((c
= fgetc (fp
)) != EOF
)
5803 else if (c
>= 'a' && c
<= 'f')
5804 digit
= c
- 'a' + 10;
5805 else if (c
>= 'A' && c
<= 'F')
5806 digit
= c
- 'A' + 10;
5809 value
= 16 * value
+ digit
;
5812 else if (isdigit (c
))
5815 while ((c
= fgetc (fp
)) != EOF
5817 value
= 8 * value
+ c
- '0';
5823 while ((c
= fgetc (fp
)) != EOF
5825 value
= 10 * value
+ c
- '0';
5833 else if (isalpha (c
) || c
== '_')
5836 while ((c
= fgetc (fp
)) != EOF
5837 && (isalnum (c
) || c
== '_'))
5849 /* Replacement for XReadBitmapFileData which isn't available under old
5850 X versions. FILE is the name of the bitmap file to read. Set
5851 *WIDTH and *HEIGHT to the width and height of the image. Return in
5852 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
5856 xbm_read_bitmap_file_data (file
, width
, height
, data
)
5858 int *width
, *height
;
5859 unsigned char **data
;
5862 char buffer
[BUFSIZ
];
5865 int bytes_per_line
, i
, nbytes
;
5871 LA1 = xbm_scan (fp, buffer, &value)
5873 #define expect(TOKEN) \
5874 if (LA1 != (TOKEN)) \
5879 #define expect_ident(IDENT) \
5880 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5885 fp
= fopen (file
, "r");
5889 *width
= *height
= -1;
5891 LA1
= xbm_scan (fp
, buffer
, &value
);
5893 /* Parse defines for width, height and hot-spots. */
5897 expect_ident ("define");
5898 expect (XBM_TK_IDENT
);
5900 if (LA1
== XBM_TK_NUMBER
);
5902 char *p
= strrchr (buffer
, '_');
5903 p
= p
? p
+ 1 : buffer
;
5904 if (strcmp (p
, "width") == 0)
5906 else if (strcmp (p
, "height") == 0)
5909 expect (XBM_TK_NUMBER
);
5912 if (*width
< 0 || *height
< 0)
5915 /* Parse bits. Must start with `static'. */
5916 expect_ident ("static");
5917 if (LA1
== XBM_TK_IDENT
)
5919 if (strcmp (buffer
, "unsigned") == 0)
5922 expect_ident ("char");
5924 else if (strcmp (buffer
, "short") == 0)
5928 if (*width
% 16 && *width
% 16 < 9)
5931 else if (strcmp (buffer
, "char") == 0)
5939 expect (XBM_TK_IDENT
);
5945 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
5946 nbytes
= bytes_per_line
* *height
;
5947 p
= *data
= (char *) xmalloc (nbytes
);
5952 for (i
= 0; i
< nbytes
; i
+= 2)
5955 expect (XBM_TK_NUMBER
);
5958 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
5961 if (LA1
== ',' || LA1
== '}')
5969 for (i
= 0; i
< nbytes
; ++i
)
5972 expect (XBM_TK_NUMBER
);
5976 if (LA1
== ',' || LA1
== '}')
6002 /* Load XBM image IMG which will be displayed on frame F from file
6003 SPECIFIED_FILE. Value is non-zero if successful. */
6006 xbm_load_image_from_file (f
, img
, specified_file
)
6009 Lisp_Object specified_file
;
6012 unsigned char *data
;
6015 struct gcpro gcpro1
;
6017 xassert (STRINGP (specified_file
));
6021 file
= x_find_image_file (specified_file
);
6022 if (!STRINGP (file
))
6024 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6029 rc
= xbm_read_bitmap_file_data (SDATA (file
), &img
->width
,
6030 &img
->height
, &data
);
6033 int depth
= one_mac_display_info
.n_cbits
;
6034 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6035 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6038 xassert (img
->width
> 0 && img
->height
> 0);
6040 /* Get foreground and background colors, maybe allocate colors. */
6041 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6043 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6045 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6047 background
= x_alloc_image_color (f
, img
, value
, background
);
6049 #if 0 /* MAC_TODO : Port image display to Mac */
6052 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f
),
6053 FRAME_W32_WINDOW (f
),
6055 img
->width
, img
->height
,
6056 foreground
, background
,
6060 if (img
->pixmap
== 0)
6062 x_clear_image (f
, img
);
6063 image_error ("Unable to create X pixmap for `%s'", file
, Qnil
);
6069 #endif /* MAC_TODO */
6072 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6079 /* Fill image IMG which is used on frame F with pixmap data. Value is
6080 non-zero if successful. */
6088 Lisp_Object file_name
;
6090 xassert (xbm_image_p (img
->spec
));
6092 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6093 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6094 if (STRINGP (file_name
))
6095 success_p
= xbm_load_image_from_file (f
, img
, file_name
);
6098 struct image_keyword fmt
[XBM_LAST
];
6101 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6102 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6106 /* Parse the list specification. */
6107 bcopy (xbm_format
, fmt
, sizeof fmt
);
6108 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6111 /* Get specified width, and height. */
6112 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6113 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6114 xassert (img
->width
> 0 && img
->height
> 0);
6118 if (fmt
[XBM_ASCENT
].count
)
6119 img
->ascent
= XFASTINT (fmt
[XBM_ASCENT
].value
);
6121 /* Get foreground and background colors, maybe allocate colors. */
6122 if (fmt
[XBM_FOREGROUND
].count
)
6123 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6125 if (fmt
[XBM_BACKGROUND
].count
)
6126 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6129 /* Set bits to the bitmap image data. */
6130 data
= fmt
[XBM_DATA
].value
;
6135 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6137 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6138 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6140 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6142 bcopy (SDATA (line
), p
, nbytes
);
6144 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6147 else if (STRINGP (data
))
6148 bits
= SDATA (data
);
6150 bits
= XBOOL_VECTOR (data
)->data
;
6152 #if 0 /* MAC_TODO : port Mac display code */
6153 /* Create the pixmap. */
6154 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6156 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f
),
6157 FRAME_W32_WINDOW (f
),
6159 img
->width
, img
->height
,
6160 foreground
, background
,
6162 #endif /* MAC_TODO */
6168 image_error ("Unable to create pixmap for XBM image `%s'",
6170 x_clear_image (f
, img
);
6181 /***********************************************************************
6183 ***********************************************************************/
6187 static int xpm_image_p
P_ ((Lisp_Object object
));
6188 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6189 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6191 #include "X11/xpm.h"
6193 /* The symbol `xpm' identifying XPM-format images. */
6197 /* Indices of image specification fields in xpm_format, below. */
6199 enum xpm_keyword_index
6213 /* Vector of image_keyword structures describing the format
6214 of valid XPM image specifications. */
6216 static struct image_keyword xpm_format
[XPM_LAST
] =
6218 {":type", IMAGE_SYMBOL_VALUE
, 1},
6219 {":file", IMAGE_STRING_VALUE
, 0},
6220 {":data", IMAGE_STRING_VALUE
, 0},
6221 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6222 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6223 {":relief", IMAGE_INTEGER_VALUE
, 0},
6224 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6225 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6226 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6229 /* Structure describing the image type XBM. */
6231 static struct image_type xpm_type
=
6241 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6242 for XPM images. Such a list must consist of conses whose car and
6246 xpm_valid_color_symbols_p (color_symbols
)
6247 Lisp_Object color_symbols
;
6249 while (CONSP (color_symbols
))
6251 Lisp_Object sym
= XCAR (color_symbols
);
6253 || !STRINGP (XCAR (sym
))
6254 || !STRINGP (XCDR (sym
)))
6256 color_symbols
= XCDR (color_symbols
);
6259 return NILP (color_symbols
);
6263 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6266 xpm_image_p (object
)
6269 struct image_keyword fmt
[XPM_LAST
];
6270 bcopy (xpm_format
, fmt
, sizeof fmt
);
6271 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
6272 /* Either `:file' or `:data' must be present. */
6273 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
6274 /* Either no `:color-symbols' or it's a list of conses
6275 whose car and cdr are strings. */
6276 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
6277 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
))
6278 && (fmt
[XPM_ASCENT
].count
== 0
6279 || XFASTINT (fmt
[XPM_ASCENT
].value
) < 100));
6283 /* Load image IMG which will be displayed on frame F. Value is
6284 non-zero if successful. */
6292 XpmAttributes attrs
;
6293 Lisp_Object specified_file
, color_symbols
;
6295 /* Configure the XPM lib. Use the visual of frame F. Allocate
6296 close colors. Return colors allocated. */
6297 bzero (&attrs
, sizeof attrs
);
6298 attrs
.visual
= FRAME_X_VISUAL (f
);
6299 attrs
.colormap
= FRAME_X_COLORMAP (f
);
6300 attrs
.valuemask
|= XpmVisual
;
6301 attrs
.valuemask
|= XpmColormap
;
6302 attrs
.valuemask
|= XpmReturnAllocPixels
;
6303 #ifdef XpmAllocCloseColors
6304 attrs
.alloc_close_colors
= 1;
6305 attrs
.valuemask
|= XpmAllocCloseColors
;
6307 attrs
.closeness
= 600;
6308 attrs
.valuemask
|= XpmCloseness
;
6311 /* If image specification contains symbolic color definitions, add
6312 these to `attrs'. */
6313 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
6314 if (CONSP (color_symbols
))
6317 XpmColorSymbol
*xpm_syms
;
6320 attrs
.valuemask
|= XpmColorSymbols
;
6322 /* Count number of symbols. */
6323 attrs
.numsymbols
= 0;
6324 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
6327 /* Allocate an XpmColorSymbol array. */
6328 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
6329 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
6330 bzero (xpm_syms
, size
);
6331 attrs
.colorsymbols
= xpm_syms
;
6333 /* Fill the color symbol array. */
6334 for (tail
= color_symbols
, i
= 0;
6336 ++i
, tail
= XCDR (tail
))
6338 Lisp_Object name
= XCAR (XCAR (tail
));
6339 Lisp_Object color
= XCDR (XCAR (tail
));
6340 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
6341 strcpy (xpm_syms
[i
].name
, SDATA (name
));
6342 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
6343 strcpy (xpm_syms
[i
].value
, SDATA (color
));
6347 /* Create a pixmap for the image, either from a file, or from a
6348 string buffer containing data in the same format as an XPM file. */
6350 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6351 if (STRINGP (specified_file
))
6353 Lisp_Object file
= x_find_image_file (specified_file
);
6354 if (!STRINGP (file
))
6356 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6361 rc
= XpmReadFileToPixmap (NULL
, FRAME_W32_WINDOW (f
),
6362 SDATA (file
), &img
->pixmap
, &img
->mask
,
6367 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
6368 rc
= XpmCreatePixmapFromBuffer (NULL
, FRAME_W32_WINDOW (f
),
6370 &img
->pixmap
, &img
->mask
,
6375 if (rc
== XpmSuccess
)
6377 /* Remember allocated colors. */
6378 img
->ncolors
= attrs
.nalloc_pixels
;
6379 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
6380 * sizeof *img
->colors
);
6381 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
6382 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
6384 img
->width
= attrs
.width
;
6385 img
->height
= attrs
.height
;
6386 xassert (img
->width
> 0 && img
->height
> 0);
6388 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6390 XpmFreeAttributes (&attrs
);
6398 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
6401 case XpmFileInvalid
:
6402 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
6406 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
6409 case XpmColorFailed
:
6410 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
6414 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
6419 return rc
== XpmSuccess
;
6422 #endif /* HAVE_XPM != 0 */
6425 #if 0 /* MAC_TODO : Color tables on Mac. */
6426 /***********************************************************************
6428 ***********************************************************************/
6430 /* An entry in the color table mapping an RGB color to a pixel color. */
6435 unsigned long pixel
;
6437 /* Next in color table collision list. */
6438 struct ct_color
*next
;
6441 /* The bucket vector size to use. Must be prime. */
6445 /* Value is a hash of the RGB color given by R, G, and B. */
6447 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6449 /* The color hash table. */
6451 struct ct_color
**ct_table
;
6453 /* Number of entries in the color table. */
6455 int ct_colors_allocated
;
6457 /* Function prototypes. */
6459 static void init_color_table
P_ ((void));
6460 static void free_color_table
P_ ((void));
6461 static unsigned long *colors_in_color_table
P_ ((int *n
));
6462 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
6463 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
6466 /* Initialize the color table. */
6471 int size
= CT_SIZE
* sizeof (*ct_table
);
6472 ct_table
= (struct ct_color
**) xmalloc (size
);
6473 bzero (ct_table
, size
);
6474 ct_colors_allocated
= 0;
6478 /* Free memory associated with the color table. */
6484 struct ct_color
*p
, *next
;
6486 for (i
= 0; i
< CT_SIZE
; ++i
)
6487 for (p
= ct_table
[i
]; p
; p
= next
)
6498 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6499 entry for that color already is in the color table, return the
6500 pixel color of that entry. Otherwise, allocate a new color for R,
6501 G, B, and make an entry in the color table. */
6503 static unsigned long
6504 lookup_rgb_color (f
, r
, g
, b
)
6508 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
6509 int i
= hash
% CT_SIZE
;
6512 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6513 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
6522 color
= RGB_TO_ULONG (r
, g
, b
);
6524 ++ct_colors_allocated
;
6526 p
= (struct ct_color
*) xmalloc (sizeof *p
);
6531 p
->next
= ct_table
[i
];
6539 /* Look up pixel color PIXEL which is used on frame F in the color
6540 table. If not already present, allocate it. Value is PIXEL. */
6542 static unsigned long
6543 lookup_pixel_color (f
, pixel
)
6545 unsigned long pixel
;
6547 int i
= pixel
% CT_SIZE
;
6550 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6551 if (p
->pixel
== pixel
)
6562 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
6563 color
.pixel
= pixel
;
6564 XQueryColor (NULL
, cmap
, &color
);
6565 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
6570 ++ct_colors_allocated
;
6572 p
= (struct ct_color
*) xmalloc (sizeof *p
);
6577 p
->next
= ct_table
[i
];
6581 return FRAME_FOREGROUND_PIXEL (f
);
6587 /* Value is a vector of all pixel colors contained in the color table,
6588 allocated via xmalloc. Set *N to the number of colors. */
6590 static unsigned long *
6591 colors_in_color_table (n
)
6596 unsigned long *colors
;
6598 if (ct_colors_allocated
== 0)
6605 colors
= (unsigned long *) xmalloc (ct_colors_allocated
6607 *n
= ct_colors_allocated
;
6609 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
6610 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6611 colors
[j
++] = p
->pixel
;
6617 #endif /* MAC_TODO */
6620 /***********************************************************************
6622 ***********************************************************************/
6624 #if 0 /* MAC_TODO : Mac versions of low level algorithms */
6625 static void x_laplace_write_row
P_ ((struct frame
*, long *,
6626 int, XImage
*, int));
6627 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
6628 XColor
*, int, XImage
*, int));
6631 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
6632 frame we operate on, CMAP is the color-map in effect, and WIDTH is
6633 the width of one row in the image. */
6636 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
6646 for (x
= 0; x
< width
; ++x
)
6647 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
6649 XQueryColors (NULL
, cmap
, colors
, width
);
6653 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
6654 containing the pixel colors to write. F is the frame we are
6658 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
6667 for (x
= 0; x
< width
; ++x
)
6668 XPutPixel (ximg
, x
, y
, pixels
[x
]);
6670 #endif /* MAC_TODO */
6672 /* Transform image IMG which is used on frame F with a Laplace
6673 edge-detection algorithm. The result is an image that can be used
6674 to draw disabled buttons, for example. */
6681 #if 0 /* MAC_TODO : Mac version */
6682 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
6683 XImage
*ximg
, *oimg
;
6689 int in_y
, out_y
, rc
;
6694 /* Get the X image IMG->pixmap. */
6695 ximg
= XGetImage (NULL
, img
->pixmap
,
6696 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
6698 /* Allocate 3 input rows, and one output row of colors. */
6699 for (i
= 0; i
< 3; ++i
)
6700 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
6701 out
= (long *) alloca (img
->width
* sizeof (long));
6703 /* Create an X image for output. */
6704 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
6707 /* Fill first two rows. */
6708 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
6709 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
6712 /* Write first row, all zeros. */
6713 init_color_table ();
6714 pixel
= lookup_rgb_color (f
, 0, 0, 0);
6715 for (x
= 0; x
< img
->width
; ++x
)
6717 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
6720 for (y
= 2; y
< img
->height
; ++y
)
6723 int rowb
= (y
+ 2) % 3;
6725 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
6727 for (x
= 0; x
< img
->width
- 2; ++x
)
6729 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
6730 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
6731 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
6733 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
6737 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
6740 /* Write last line, all zeros. */
6741 for (x
= 0; x
< img
->width
; ++x
)
6743 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
6745 /* Free the input image, and free resources of IMG. */
6746 XDestroyImage (ximg
);
6747 x_clear_image (f
, img
);
6749 /* Put the output image into pixmap, and destroy it. */
6750 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
6751 x_destroy_x_image (oimg
);
6753 /* Remember new pixmap and colors in IMG. */
6754 img
->pixmap
= pixmap
;
6755 img
->colors
= colors_in_color_table (&img
->ncolors
);
6756 free_color_table ();
6759 #endif /* MAC_TODO */
6763 /* Build a mask for image IMG which is used on frame F. FILE is the
6764 name of an image file, for error messages. HOW determines how to
6765 determine the background color of IMG. If it is a list '(R G B)',
6766 with R, G, and B being integers >= 0, take that as the color of the
6767 background. Otherwise, determine the background color of IMG
6768 heuristically. Value is non-zero if successful. */
6771 x_build_heuristic_mask (f
, img
, how
)
6776 #if 0 /* MAC_TODO : Mac version */
6777 Display
*dpy
= FRAME_W32_DISPLAY (f
);
6778 XImage
*ximg
, *mask_img
;
6779 int x
, y
, rc
, look_at_corners_p
;
6784 /* Create an image and pixmap serving as mask. */
6785 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
6786 &mask_img
, &img
->mask
);
6793 /* Get the X image of IMG->pixmap. */
6794 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
6797 /* Determine the background color of ximg. If HOW is `(R G B)'
6798 take that as color. Otherwise, try to determine the color
6800 look_at_corners_p
= 1;
6808 && NATNUMP (XCAR (how
)))
6810 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
6814 if (i
== 3 && NILP (how
))
6816 char color_name
[30];
6817 XColor exact
, color
;
6820 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
6822 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
6823 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
6826 look_at_corners_p
= 0;
6831 if (look_at_corners_p
)
6833 unsigned long corners
[4];
6836 /* Get the colors at the corners of ximg. */
6837 corners
[0] = XGetPixel (ximg
, 0, 0);
6838 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
6839 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
6840 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
6842 /* Choose the most frequently found color as background. */
6843 for (i
= best_count
= 0; i
< 4; ++i
)
6847 for (j
= n
= 0; j
< 4; ++j
)
6848 if (corners
[i
] == corners
[j
])
6852 bg
= corners
[i
], best_count
= n
;
6856 /* Set all bits in mask_img to 1 whose color in ximg is different
6857 from the background color bg. */
6858 for (y
= 0; y
< img
->height
; ++y
)
6859 for (x
= 0; x
< img
->width
; ++x
)
6860 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
6862 /* Put mask_img into img->mask. */
6863 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6864 x_destroy_x_image (mask_img
);
6865 XDestroyImage (ximg
);
6868 #endif /* MAC_TODO */
6875 /***********************************************************************
6876 PBM (mono, gray, color)
6877 ***********************************************************************/
6880 static int pbm_image_p
P_ ((Lisp_Object object
));
6881 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
6882 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
6884 /* The symbol `pbm' identifying images of this type. */
6888 /* Indices of image specification fields in gs_format, below. */
6890 enum pbm_keyword_index
6903 /* Vector of image_keyword structures describing the format
6904 of valid user-defined image specifications. */
6906 static struct image_keyword pbm_format
[PBM_LAST
] =
6908 {":type", IMAGE_SYMBOL_VALUE
, 1},
6909 {":file", IMAGE_STRING_VALUE
, 0},
6910 {":data", IMAGE_STRING_VALUE
, 0},
6911 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6912 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6913 {":relief", IMAGE_INTEGER_VALUE
, 0},
6914 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6915 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6918 /* Structure describing the image type `pbm'. */
6920 static struct image_type pbm_type
=
6930 /* Return non-zero if OBJECT is a valid PBM image specification. */
6933 pbm_image_p (object
)
6936 struct image_keyword fmt
[PBM_LAST
];
6938 bcopy (pbm_format
, fmt
, sizeof fmt
);
6940 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
)
6941 || (fmt
[PBM_ASCENT
].count
6942 && XFASTINT (fmt
[PBM_ASCENT
].value
) > 100))
6945 /* Must specify either :data or :file. */
6946 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
6950 /* Scan a decimal number from *S and return it. Advance *S while
6951 reading the number. END is the end of the string. Value is -1 at
6955 pbm_scan_number (s
, end
)
6956 unsigned char **s
, *end
;
6962 /* Skip white-space. */
6963 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6968 /* Skip comment to end of line. */
6969 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
6972 else if (isdigit (c
))
6974 /* Read decimal number. */
6976 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
6977 val
= 10 * val
+ c
- '0';
6988 /* Read FILE into memory. Value is a pointer to a buffer allocated
6989 with xmalloc holding FILE's contents. Value is null if an error
6990 occurred. *SIZE is set to the size of the file. */
6993 pbm_read_file (file
, size
)
7001 if (stat (SDATA (file
), &st
) == 0
7002 && (fp
= fopen (SDATA (file
), "r")) != NULL
7003 && (buf
= (char *) xmalloc (st
.st_size
),
7004 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
7024 /* Load PBM image IMG for use on frame F. */
7032 int width
, height
, max_color_idx
= 0;
7034 Lisp_Object file
, specified_file
;
7035 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
7036 struct gcpro gcpro1
;
7037 unsigned char *contents
= NULL
;
7038 unsigned char *end
, *p
;
7041 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7045 if (STRINGP (specified_file
))
7047 file
= x_find_image_file (specified_file
);
7048 if (!STRINGP (file
))
7050 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7055 contents
= pbm_read_file (file
, &size
);
7056 if (contents
== NULL
)
7058 image_error ("Error reading `%s'", file
, Qnil
);
7064 end
= contents
+ size
;
7069 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7071 end
= p
+ SBYTES (data
);
7074 /* Check magic number. */
7075 if (end
- p
< 2 || *p
++ != 'P')
7077 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
7087 raw_p
= 0, type
= PBM_MONO
;
7091 raw_p
= 0, type
= PBM_GRAY
;
7095 raw_p
= 0, type
= PBM_COLOR
;
7099 raw_p
= 1, type
= PBM_MONO
;
7103 raw_p
= 1, type
= PBM_GRAY
;
7107 raw_p
= 1, type
= PBM_COLOR
;
7111 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
7115 /* Read width, height, maximum color-component. Characters
7116 starting with `#' up to the end of a line are ignored. */
7117 width
= pbm_scan_number (&p
, end
);
7118 height
= pbm_scan_number (&p
, end
);
7120 if (type
!= PBM_MONO
)
7122 max_color_idx
= pbm_scan_number (&p
, end
);
7123 if (raw_p
&& max_color_idx
> 255)
7124 max_color_idx
= 255;
7129 || (type
!= PBM_MONO
&& max_color_idx
< 0))
7133 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
7134 &ximg
, &img
->pixmap
))
7140 /* Initialize the color hash table. */
7141 init_color_table ();
7143 if (type
== PBM_MONO
)
7147 for (y
= 0; y
< height
; ++y
)
7148 for (x
= 0; x
< width
; ++x
)
7158 g
= pbm_scan_number (&p
, end
);
7160 XPutPixel (ximg
, x
, y
, (g
7161 ? FRAME_FOREGROUND_PIXEL (f
)
7162 : FRAME_BACKGROUND_PIXEL (f
)));
7167 for (y
= 0; y
< height
; ++y
)
7168 for (x
= 0; x
< width
; ++x
)
7172 if (type
== PBM_GRAY
)
7173 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
7182 r
= pbm_scan_number (&p
, end
);
7183 g
= pbm_scan_number (&p
, end
);
7184 b
= pbm_scan_number (&p
, end
);
7187 if (r
< 0 || g
< 0 || b
< 0)
7191 XDestroyImage (ximg
);
7193 image_error ("Invalid pixel value in image `%s'",
7198 /* RGB values are now in the range 0..max_color_idx.
7199 Scale this to the range 0..0xffff supported by X. */
7200 r
= (double) r
* 65535 / max_color_idx
;
7201 g
= (double) g
* 65535 / max_color_idx
;
7202 b
= (double) b
* 65535 / max_color_idx
;
7203 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
7207 /* Store in IMG->colors the colors allocated for the image, and
7208 free the color table. */
7209 img
->colors
= colors_in_color_table (&img
->ncolors
);
7210 free_color_table ();
7212 /* Put the image into a pixmap. */
7213 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7214 x_destroy_x_image (ximg
);
7218 img
->height
= height
;
7224 #endif /* HAVE_PBM */
7227 /***********************************************************************
7229 ***********************************************************************/
7235 /* Function prototypes. */
7237 static int png_image_p
P_ ((Lisp_Object object
));
7238 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
7240 /* The symbol `png' identifying images of this type. */
7244 /* Indices of image specification fields in png_format, below. */
7246 enum png_keyword_index
7259 /* Vector of image_keyword structures describing the format
7260 of valid user-defined image specifications. */
7262 static struct image_keyword png_format
[PNG_LAST
] =
7264 {":type", IMAGE_SYMBOL_VALUE
, 1},
7265 {":data", IMAGE_STRING_VALUE
, 0},
7266 {":file", IMAGE_STRING_VALUE
, 0},
7267 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7268 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7269 {":relief", IMAGE_INTEGER_VALUE
, 0},
7270 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7271 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7274 /* Structure describing the image type `png'. */
7276 static struct image_type png_type
=
7286 /* Return non-zero if OBJECT is a valid PNG image specification. */
7289 png_image_p (object
)
7292 struct image_keyword fmt
[PNG_LAST
];
7293 bcopy (png_format
, fmt
, sizeof fmt
);
7295 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
)
7296 || (fmt
[PNG_ASCENT
].count
7297 && XFASTINT (fmt
[PNG_ASCENT
].value
) > 100))
7300 /* Must specify either the :data or :file keyword. */
7301 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
7305 /* Error and warning handlers installed when the PNG library
7309 my_png_error (png_ptr
, msg
)
7310 png_struct
*png_ptr
;
7313 xassert (png_ptr
!= NULL
);
7314 image_error ("PNG error: %s", build_string (msg
), Qnil
);
7315 longjmp (png_ptr
->jmpbuf
, 1);
7320 my_png_warning (png_ptr
, msg
)
7321 png_struct
*png_ptr
;
7324 xassert (png_ptr
!= NULL
);
7325 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
7328 /* Memory source for PNG decoding. */
7330 struct png_memory_storage
7332 unsigned char *bytes
; /* The data */
7333 size_t len
; /* How big is it? */
7334 int index
; /* Where are we? */
7338 /* Function set as reader function when reading PNG image from memory.
7339 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7340 bytes from the input to DATA. */
7343 png_read_from_memory (png_ptr
, data
, length
)
7344 png_structp png_ptr
;
7348 struct png_memory_storage
*tbr
7349 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
7351 if (length
> tbr
->len
- tbr
->index
)
7352 png_error (png_ptr
, "Read error");
7354 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
7355 tbr
->index
= tbr
->index
+ length
;
7358 /* Load PNG image IMG for use on frame F. Value is non-zero if
7366 Lisp_Object file
, specified_file
;
7367 Lisp_Object specified_data
;
7369 XImage
*ximg
, *mask_img
= NULL
;
7370 struct gcpro gcpro1
;
7371 png_struct
*png_ptr
= NULL
;
7372 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
7375 png_byte
*pixels
= NULL
;
7376 png_byte
**rows
= NULL
;
7377 png_uint_32 width
, height
;
7378 int bit_depth
, color_type
, interlace_type
;
7380 png_uint_32 row_bytes
;
7383 double screen_gamma
, image_gamma
;
7385 struct png_memory_storage tbr
; /* Data to be read */
7387 /* Find out what file to load. */
7388 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7389 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7393 if (NILP (specified_data
))
7395 file
= x_find_image_file (specified_file
);
7396 if (!STRINGP (file
))
7398 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7403 /* Open the image file. */
7404 fp
= fopen (SDATA (file
), "rb");
7407 image_error ("Cannot open image file `%s'", file
, Qnil
);
7413 /* Check PNG signature. */
7414 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
7415 || !png_check_sig (sig
, sizeof sig
))
7417 image_error ("Not a PNG file:` %s'", file
, Qnil
);
7425 /* Read from memory. */
7426 tbr
.bytes
= SDATA (specified_data
);
7427 tbr
.len
= SBYTES (specified_data
);
7430 /* Check PNG signature. */
7431 if (tbr
.len
< sizeof sig
7432 || !png_check_sig (tbr
.bytes
, sizeof sig
))
7434 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
7439 /* Need to skip past the signature. */
7440 tbr
.bytes
+= sizeof (sig
);
7443 /* Initialize read and info structs for PNG lib. */
7444 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
7445 my_png_error
, my_png_warning
);
7448 if (fp
) fclose (fp
);
7453 info_ptr
= png_create_info_struct (png_ptr
);
7456 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
7457 if (fp
) fclose (fp
);
7462 end_info
= png_create_info_struct (png_ptr
);
7465 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
7466 if (fp
) fclose (fp
);
7471 /* Set error jump-back. We come back here when the PNG library
7472 detects an error. */
7473 if (setjmp (png_ptr
->jmpbuf
))
7477 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
7480 if (fp
) fclose (fp
);
7485 /* Read image info. */
7486 if (!NILP (specified_data
))
7487 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
7489 png_init_io (png_ptr
, fp
);
7491 png_set_sig_bytes (png_ptr
, sizeof sig
);
7492 png_read_info (png_ptr
, info_ptr
);
7493 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
7494 &interlace_type
, NULL
, NULL
);
7496 /* If image contains simply transparency data, we prefer to
7497 construct a clipping mask. */
7498 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
7503 /* This function is easier to write if we only have to handle
7504 one data format: RGB or RGBA with 8 bits per channel. Let's
7505 transform other formats into that format. */
7507 /* Strip more than 8 bits per channel. */
7508 if (bit_depth
== 16)
7509 png_set_strip_16 (png_ptr
);
7511 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7513 png_set_expand (png_ptr
);
7515 /* Convert grayscale images to RGB. */
7516 if (color_type
== PNG_COLOR_TYPE_GRAY
7517 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
7518 png_set_gray_to_rgb (png_ptr
);
7520 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7521 gamma_str
= getenv ("SCREEN_GAMMA");
7522 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
7524 /* Tell the PNG lib to handle gamma correction for us. */
7526 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7527 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
7528 /* There is a special chunk in the image specifying the gamma. */
7529 png_set_sRGB (png_ptr
, info_ptr
, intent
);
7532 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
7533 /* Image contains gamma information. */
7534 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
7536 /* Use a default of 0.5 for the image gamma. */
7537 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
7539 /* Handle alpha channel by combining the image with a background
7540 color. Do this only if a real alpha channel is supplied. For
7541 simple transparency, we prefer a clipping mask. */
7544 png_color_16
*image_background
;
7546 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
7547 /* Image contains a background color with which to
7548 combine the image. */
7549 png_set_background (png_ptr
, image_background
,
7550 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
7553 /* Image does not contain a background color with which
7554 to combine the image data via an alpha channel. Use
7555 the frame's background instead. */
7558 png_color_16 frame_background
;
7561 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7562 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7563 XQueryColor (FRAME_W32_DISPLAY (f
), cmap
, &color
);
7566 bzero (&frame_background
, sizeof frame_background
);
7567 frame_background
.red
= color
.red
;
7568 frame_background
.green
= color
.green
;
7569 frame_background
.blue
= color
.blue
;
7571 png_set_background (png_ptr
, &frame_background
,
7572 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
7576 /* Update info structure. */
7577 png_read_update_info (png_ptr
, info_ptr
);
7579 /* Get number of channels. Valid values are 1 for grayscale images
7580 and images with a palette, 2 for grayscale images with transparency
7581 information (alpha channel), 3 for RGB images, and 4 for RGB
7582 images with alpha channel, i.e. RGBA. If conversions above were
7583 sufficient we should only have 3 or 4 channels here. */
7584 channels
= png_get_channels (png_ptr
, info_ptr
);
7585 xassert (channels
== 3 || channels
== 4);
7587 /* Number of bytes needed for one row of the image. */
7588 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
7590 /* Allocate memory for the image. */
7591 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
7592 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
7593 for (i
= 0; i
< height
; ++i
)
7594 rows
[i
] = pixels
+ i
* row_bytes
;
7596 /* Read the entire image. */
7597 png_read_image (png_ptr
, rows
);
7598 png_read_end (png_ptr
, info_ptr
);
7607 /* Create the X image and pixmap. */
7608 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
7615 /* Create an image and pixmap serving as mask if the PNG image
7616 contains an alpha channel. */
7619 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
7620 &mask_img
, &img
->mask
))
7622 x_destroy_x_image (ximg
);
7623 XFreePixmap (FRAME_W32_DISPLAY (f
), img
->pixmap
);
7629 /* Fill the X image and mask from PNG data. */
7630 init_color_table ();
7632 for (y
= 0; y
< height
; ++y
)
7634 png_byte
*p
= rows
[y
];
7636 for (x
= 0; x
< width
; ++x
)
7643 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
7645 /* An alpha channel, aka mask channel, associates variable
7646 transparency with an image. Where other image formats
7647 support binary transparency---fully transparent or fully
7648 opaque---PNG allows up to 254 levels of partial transparency.
7649 The PNG library implements partial transparency by combining
7650 the image with a specified background color.
7652 I'm not sure how to handle this here nicely: because the
7653 background on which the image is displayed may change, for
7654 real alpha channel support, it would be necessary to create
7655 a new image for each possible background.
7657 What I'm doing now is that a mask is created if we have
7658 boolean transparency information. Otherwise I'm using
7659 the frame's background color to combine the image with. */
7664 XPutPixel (mask_img
, x
, y
, *p
> 0);
7670 /* Remember colors allocated for this image. */
7671 img
->colors
= colors_in_color_table (&img
->ncolors
);
7672 free_color_table ();
7675 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
7680 img
->height
= height
;
7682 /* Put the image into the pixmap, then free the X image and its buffer. */
7683 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7684 x_destroy_x_image (ximg
);
7686 /* Same for the mask. */
7689 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7690 x_destroy_x_image (mask_img
);
7698 #endif /* HAVE_PNG != 0 */
7702 /***********************************************************************
7704 ***********************************************************************/
7708 /* Work around a warning about HAVE_STDLIB_H being redefined in
7710 #ifdef HAVE_STDLIB_H
7711 #define HAVE_STDLIB_H_1
7712 #undef HAVE_STDLIB_H
7713 #endif /* HAVE_STLIB_H */
7715 #include <jpeglib.h>
7719 #ifdef HAVE_STLIB_H_1
7720 #define HAVE_STDLIB_H 1
7723 static int jpeg_image_p
P_ ((Lisp_Object object
));
7724 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
7726 /* The symbol `jpeg' identifying images of this type. */
7730 /* Indices of image specification fields in gs_format, below. */
7732 enum jpeg_keyword_index
7741 JPEG_HEURISTIC_MASK
,
7745 /* Vector of image_keyword structures describing the format
7746 of valid user-defined image specifications. */
7748 static struct image_keyword jpeg_format
[JPEG_LAST
] =
7750 {":type", IMAGE_SYMBOL_VALUE
, 1},
7751 {":data", IMAGE_STRING_VALUE
, 0},
7752 {":file", IMAGE_STRING_VALUE
, 0},
7753 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7754 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7755 {":relief", IMAGE_INTEGER_VALUE
, 0},
7756 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7757 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7760 /* Structure describing the image type `jpeg'. */
7762 static struct image_type jpeg_type
=
7772 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7775 jpeg_image_p (object
)
7778 struct image_keyword fmt
[JPEG_LAST
];
7780 bcopy (jpeg_format
, fmt
, sizeof fmt
);
7782 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
)
7783 || (fmt
[JPEG_ASCENT
].count
7784 && XFASTINT (fmt
[JPEG_ASCENT
].value
) > 100))
7787 /* Must specify either the :data or :file keyword. */
7788 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
7792 struct my_jpeg_error_mgr
7794 struct jpeg_error_mgr pub
;
7795 jmp_buf setjmp_buffer
;
7799 my_error_exit (cinfo
)
7802 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
7803 longjmp (mgr
->setjmp_buffer
, 1);
7806 /* Init source method for JPEG data source manager. Called by
7807 jpeg_read_header() before any data is actually read. See
7808 libjpeg.doc from the JPEG lib distribution. */
7811 our_init_source (cinfo
)
7812 j_decompress_ptr cinfo
;
7817 /* Fill input buffer method for JPEG data source manager. Called
7818 whenever more data is needed. We read the whole image in one step,
7819 so this only adds a fake end of input marker at the end. */
7822 our_fill_input_buffer (cinfo
)
7823 j_decompress_ptr cinfo
;
7825 /* Insert a fake EOI marker. */
7826 struct jpeg_source_mgr
*src
= cinfo
->src
;
7827 static JOCTET buffer
[2];
7829 buffer
[0] = (JOCTET
) 0xFF;
7830 buffer
[1] = (JOCTET
) JPEG_EOI
;
7832 src
->next_input_byte
= buffer
;
7833 src
->bytes_in_buffer
= 2;
7838 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7839 is the JPEG data source manager. */
7842 our_skip_input_data (cinfo
, num_bytes
)
7843 j_decompress_ptr cinfo
;
7846 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7850 if (num_bytes
> src
->bytes_in_buffer
)
7851 ERREXIT (cinfo
, JERR_INPUT_EOF
);
7853 src
->bytes_in_buffer
-= num_bytes
;
7854 src
->next_input_byte
+= num_bytes
;
7859 /* Method to terminate data source. Called by
7860 jpeg_finish_decompress() after all data has been processed. */
7863 our_term_source (cinfo
)
7864 j_decompress_ptr cinfo
;
7869 /* Set up the JPEG lib for reading an image from DATA which contains
7870 LEN bytes. CINFO is the decompression info structure created for
7871 reading the image. */
7874 jpeg_memory_src (cinfo
, data
, len
)
7875 j_decompress_ptr cinfo
;
7879 struct jpeg_source_mgr
*src
;
7881 if (cinfo
->src
== NULL
)
7883 /* First time for this JPEG object? */
7884 cinfo
->src
= (struct jpeg_source_mgr
*)
7885 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7886 sizeof (struct jpeg_source_mgr
));
7887 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7888 src
->next_input_byte
= data
;
7891 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7892 src
->init_source
= our_init_source
;
7893 src
->fill_input_buffer
= our_fill_input_buffer
;
7894 src
->skip_input_data
= our_skip_input_data
;
7895 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
7896 src
->term_source
= our_term_source
;
7897 src
->bytes_in_buffer
= len
;
7898 src
->next_input_byte
= data
;
7902 /* Load image IMG for use on frame F. Patterned after example.c
7903 from the JPEG lib. */
7910 struct jpeg_decompress_struct cinfo
;
7911 struct my_jpeg_error_mgr mgr
;
7912 Lisp_Object file
, specified_file
;
7913 Lisp_Object specified_data
;
7916 int row_stride
, x
, y
;
7917 XImage
*ximg
= NULL
;
7919 unsigned long *colors
;
7921 struct gcpro gcpro1
;
7923 /* Open the JPEG file. */
7924 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7925 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7929 if (NILP (specified_data
))
7931 file
= x_find_image_file (specified_file
);
7932 if (!STRINGP (file
))
7934 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7939 fp
= fopen (SDATA (file
), "r");
7942 image_error ("Cannot open `%s'", file
, Qnil
);
7948 /* Customize libjpeg's error handling to call my_error_exit when an
7949 error is detected. This function will perform a longjmp. */
7950 mgr
.pub
.error_exit
= my_error_exit
;
7951 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
7953 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7957 /* Called from my_error_exit. Display a JPEG error. */
7958 char buffer
[JMSG_LENGTH_MAX
];
7959 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7960 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7961 build_string (buffer
));
7964 /* Close the input file and destroy the JPEG object. */
7967 jpeg_destroy_decompress (&cinfo
);
7971 /* If we already have an XImage, free that. */
7972 x_destroy_x_image (ximg
);
7974 /* Free pixmap and colors. */
7975 x_clear_image (f
, img
);
7982 /* Create the JPEG decompression object. Let it read from fp.
7983 Read the JPEG image header. */
7984 jpeg_create_decompress (&cinfo
);
7986 if (NILP (specified_data
))
7987 jpeg_stdio_src (&cinfo
, fp
);
7989 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7990 SBYTES (specified_data
));
7992 jpeg_read_header (&cinfo
, TRUE
);
7994 /* Customize decompression so that color quantization will be used.
7995 Start decompression. */
7996 cinfo
.quantize_colors
= TRUE
;
7997 jpeg_start_decompress (&cinfo
);
7998 width
= img
->width
= cinfo
.output_width
;
7999 height
= img
->height
= cinfo
.output_height
;
8003 /* Create X image and pixmap. */
8004 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8008 longjmp (mgr
.setjmp_buffer
, 2);
8011 /* Allocate colors. When color quantization is used,
8012 cinfo.actual_number_of_colors has been set with the number of
8013 colors generated, and cinfo.colormap is a two-dimensional array
8014 of color indices in the range 0..cinfo.actual_number_of_colors.
8015 No more than 255 colors will be generated. */
8019 if (cinfo
.out_color_components
> 2)
8020 ir
= 0, ig
= 1, ib
= 2;
8021 else if (cinfo
.out_color_components
> 1)
8022 ir
= 0, ig
= 1, ib
= 0;
8024 ir
= 0, ig
= 0, ib
= 0;
8026 /* Use the color table mechanism because it handles colors that
8027 cannot be allocated nicely. Such colors will be replaced with
8028 a default color, and we don't have to care about which colors
8029 can be freed safely, and which can't. */
8030 init_color_table ();
8031 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8034 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8036 /* Multiply RGB values with 255 because X expects RGB values
8037 in the range 0..0xffff. */
8038 int r
= cinfo
.colormap
[ir
][i
] << 8;
8039 int g
= cinfo
.colormap
[ig
][i
] << 8;
8040 int b
= cinfo
.colormap
[ib
][i
] << 8;
8041 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8044 /* Remember those colors actually allocated. */
8045 img
->colors
= colors_in_color_table (&img
->ncolors
);
8046 free_color_table ();
8050 row_stride
= width
* cinfo
.output_components
;
8051 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
8053 for (y
= 0; y
< height
; ++y
)
8055 jpeg_read_scanlines (&cinfo
, buffer
, 1);
8056 for (x
= 0; x
< cinfo
.output_width
; ++x
)
8057 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
8061 jpeg_finish_decompress (&cinfo
);
8062 jpeg_destroy_decompress (&cinfo
);
8066 /* Put the image into the pixmap. */
8067 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8068 x_destroy_x_image (ximg
);
8074 #endif /* HAVE_JPEG */
8078 /***********************************************************************
8080 ***********************************************************************/
8086 static int tiff_image_p
P_ ((Lisp_Object object
));
8087 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
8089 /* The symbol `tiff' identifying images of this type. */
8093 /* Indices of image specification fields in tiff_format, below. */
8095 enum tiff_keyword_index
8104 TIFF_HEURISTIC_MASK
,
8108 /* Vector of image_keyword structures describing the format
8109 of valid user-defined image specifications. */
8111 static struct image_keyword tiff_format
[TIFF_LAST
] =
8113 {":type", IMAGE_SYMBOL_VALUE
, 1},
8114 {":data", IMAGE_STRING_VALUE
, 0},
8115 {":file", IMAGE_STRING_VALUE
, 0},
8116 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8117 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8118 {":relief", IMAGE_INTEGER_VALUE
, 0},
8119 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8120 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8123 /* Structure describing the image type `tiff'. */
8125 static struct image_type tiff_type
=
8135 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8138 tiff_image_p (object
)
8141 struct image_keyword fmt
[TIFF_LAST
];
8142 bcopy (tiff_format
, fmt
, sizeof fmt
);
8144 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
)
8145 || (fmt
[TIFF_ASCENT
].count
8146 && XFASTINT (fmt
[TIFF_ASCENT
].value
) > 100))
8149 /* Must specify either the :data or :file keyword. */
8150 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
8154 /* Reading from a memory buffer for TIFF images Based on the PNG
8155 memory source, but we have to provide a lot of extra functions.
8158 We really only need to implement read and seek, but I am not
8159 convinced that the TIFF library is smart enough not to destroy
8160 itself if we only hand it the function pointers we need to
8165 unsigned char *bytes
;
8172 tiff_read_from_memory (data
, buf
, size
)
8177 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8179 if (size
> src
->len
- src
->index
)
8181 bcopy (src
->bytes
+ src
->index
, buf
, size
);
8187 tiff_write_from_memory (data
, buf
, size
)
8196 tiff_seek_in_memory (data
, off
, whence
)
8201 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8206 case SEEK_SET
: /* Go from beginning of source. */
8210 case SEEK_END
: /* Go from end of source. */
8211 idx
= src
->len
+ off
;
8214 case SEEK_CUR
: /* Go from current position. */
8215 idx
= src
->index
+ off
;
8218 default: /* Invalid `whence'. */
8222 if (idx
> src
->len
|| idx
< 0)
8230 tiff_close_memory (data
)
8238 tiff_mmap_memory (data
, pbase
, psize
)
8243 /* It is already _IN_ memory. */
8248 tiff_unmap_memory (data
, base
, size
)
8253 /* We don't need to do this. */
8257 tiff_size_of_memory (data
)
8260 return ((tiff_memory_source
*) data
)->len
;
8263 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8271 Lisp_Object file
, specified_file
;
8272 Lisp_Object specified_data
;
8274 int width
, height
, x
, y
;
8278 struct gcpro gcpro1
;
8279 tiff_memory_source memsrc
;
8281 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8282 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8286 if (NILP (specified_data
))
8288 /* Read from a file */
8289 file
= x_find_image_file (specified_file
);
8290 if (!STRINGP (file
))
8292 image_error ("Cannot find image file `%s'", file
, Qnil
);
8297 /* Try to open the image file. */
8298 tiff
= TIFFOpen (SDATA (file
), "r");
8301 image_error ("Cannot open `%s'", file
, Qnil
);
8308 /* Memory source! */
8309 memsrc
.bytes
= SDATA (specified_data
);
8310 memsrc
.len
= SBYTES (specified_data
);
8313 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
8314 (TIFFReadWriteProc
) tiff_read_from_memory
,
8315 (TIFFReadWriteProc
) tiff_write_from_memory
,
8316 tiff_seek_in_memory
,
8318 tiff_size_of_memory
,
8324 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
8330 /* Get width and height of the image, and allocate a raster buffer
8331 of width x height 32-bit values. */
8332 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
8333 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
8334 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8336 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8340 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
8348 /* Create the X image and pixmap. */
8349 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8357 /* Initialize the color table. */
8358 init_color_table ();
8360 /* Process the pixel raster. Origin is in the lower-left corner. */
8361 for (y
= 0; y
< height
; ++y
)
8363 uint32
*row
= buf
+ y
* width
;
8365 for (x
= 0; x
< width
; ++x
)
8367 uint32 abgr
= row
[x
];
8368 int r
= TIFFGetR (abgr
) << 8;
8369 int g
= TIFFGetG (abgr
) << 8;
8370 int b
= TIFFGetB (abgr
) << 8;
8371 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
8375 /* Remember the colors allocated for the image. Free the color table. */
8376 img
->colors
= colors_in_color_table (&img
->ncolors
);
8377 free_color_table ();
8379 /* Put the image into the pixmap, then free the X image and its buffer. */
8380 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8381 x_destroy_x_image (ximg
);
8386 img
->height
= height
;
8392 #endif /* HAVE_TIFF != 0 */
8396 /***********************************************************************
8398 ***********************************************************************/
8402 #include <gif_lib.h>
8404 static int gif_image_p
P_ ((Lisp_Object object
));
8405 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
8407 /* The symbol `gif' identifying images of this type. */
8411 /* Indices of image specification fields in gif_format, below. */
8413 enum gif_keyword_index
8427 /* Vector of image_keyword structures describing the format
8428 of valid user-defined image specifications. */
8430 static struct image_keyword gif_format
[GIF_LAST
] =
8432 {":type", IMAGE_SYMBOL_VALUE
, 1},
8433 {":data", IMAGE_STRING_VALUE
, 0},
8434 {":file", IMAGE_STRING_VALUE
, 0},
8435 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8436 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8437 {":relief", IMAGE_INTEGER_VALUE
, 0},
8438 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8439 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8440 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
8443 /* Structure describing the image type `gif'. */
8445 static struct image_type gif_type
=
8454 /* Return non-zero if OBJECT is a valid GIF image specification. */
8457 gif_image_p (object
)
8460 struct image_keyword fmt
[GIF_LAST
];
8461 bcopy (gif_format
, fmt
, sizeof fmt
);
8463 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
)
8464 || (fmt
[GIF_ASCENT
].count
8465 && XFASTINT (fmt
[GIF_ASCENT
].value
) > 100))
8468 /* Must specify either the :data or :file keyword. */
8469 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8472 /* Reading a GIF image from memory
8473 Based on the PNG memory stuff to a certain extent. */
8477 unsigned char *bytes
;
8483 /* Make the current memory source available to gif_read_from_memory.
8484 It's done this way because not all versions of libungif support
8485 a UserData field in the GifFileType structure. */
8486 static gif_memory_source
*current_gif_memory_src
;
8489 gif_read_from_memory (file
, buf
, len
)
8494 gif_memory_source
*src
= current_gif_memory_src
;
8496 if (len
> src
->len
- src
->index
)
8499 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8505 /* Load GIF image IMG for use on frame F. Value is non-zero if
8513 Lisp_Object file
, specified_file
;
8514 Lisp_Object specified_data
;
8515 int rc
, width
, height
, x
, y
, i
;
8517 ColorMapObject
*gif_color_map
;
8518 unsigned long pixel_colors
[256];
8520 struct gcpro gcpro1
;
8522 int ino
, image_left
, image_top
, image_width
, image_height
;
8523 gif_memory_source memsrc
;
8524 unsigned char *raster
;
8526 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8527 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8531 if (NILP (specified_data
))
8533 file
= x_find_image_file (specified_file
);
8534 if (!STRINGP (file
))
8536 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8541 /* Open the GIF file. */
8542 gif
= DGifOpenFileName (SDATA (file
));
8545 image_error ("Cannot open `%s'", file
, Qnil
);
8552 /* Read from memory! */
8553 current_gif_memory_src
= &memsrc
;
8554 memsrc
.bytes
= SDATA (specified_data
);
8555 memsrc
.len
= SBYTES (specified_data
);
8558 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
8561 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8567 /* Read entire contents. */
8568 rc
= DGifSlurp (gif
);
8569 if (rc
== GIF_ERROR
)
8571 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8572 DGifCloseFile (gif
);
8577 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8578 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8579 if (ino
>= gif
->ImageCount
)
8581 image_error ("Invalid image number `%s' in image `%s'",
8583 DGifCloseFile (gif
);
8588 width
= img
->width
= gif
->SWidth
;
8589 height
= img
->height
= gif
->SHeight
;
8593 /* Create the X image and pixmap. */
8594 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8597 DGifCloseFile (gif
);
8602 /* Allocate colors. */
8603 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8605 gif_color_map
= gif
->SColorMap
;
8606 init_color_table ();
8607 bzero (pixel_colors
, sizeof pixel_colors
);
8609 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8611 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8612 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8613 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8614 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8617 img
->colors
= colors_in_color_table (&img
->ncolors
);
8618 free_color_table ();
8620 /* Clear the part of the screen image that are not covered by
8621 the image from the GIF file. Full animated GIF support
8622 requires more than can be done here (see the gif89 spec,
8623 disposal methods). Let's simply assume that the part
8624 not covered by a sub-image is in the frame's background color. */
8625 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
8626 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
8627 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8628 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8630 for (y
= 0; y
< image_top
; ++y
)
8631 for (x
= 0; x
< width
; ++x
)
8632 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8634 for (y
= image_top
+ image_height
; y
< height
; ++y
)
8635 for (x
= 0; x
< width
; ++x
)
8636 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8638 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
8640 for (x
= 0; x
< image_left
; ++x
)
8641 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8642 for (x
= image_left
+ image_width
; x
< width
; ++x
)
8643 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8646 /* Read the GIF image into the X image. We use a local variable
8647 `raster' here because RasterBits below is a char *, and invites
8648 problems with bytes >= 0x80. */
8649 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
8651 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8653 static int interlace_start
[] = {0, 4, 2, 1};
8654 static int interlace_increment
[] = {8, 8, 4, 2};
8656 int row
= interlace_start
[0];
8660 for (y
= 0; y
< image_height
; y
++)
8662 if (row
>= image_height
)
8664 row
= interlace_start
[++pass
];
8665 while (row
>= image_height
)
8666 row
= interlace_start
[++pass
];
8669 for (x
= 0; x
< image_width
; x
++)
8671 int i
= raster
[(y
* image_width
) + x
];
8672 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
8676 row
+= interlace_increment
[pass
];
8681 for (y
= 0; y
< image_height
; ++y
)
8682 for (x
= 0; x
< image_width
; ++x
)
8684 int i
= raster
[y
* image_width
+ x
];
8685 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
8689 DGifCloseFile (gif
);
8691 /* Put the image into the pixmap, then free the X image and its buffer. */
8692 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8693 x_destroy_x_image (ximg
);
8700 #endif /* HAVE_GIF != 0 */
8704 /***********************************************************************
8706 ***********************************************************************/
8708 #ifdef HAVE_GHOSTSCRIPT
8709 static int gs_image_p
P_ ((Lisp_Object object
));
8710 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8711 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8713 /* The symbol `postscript' identifying images of this type. */
8715 Lisp_Object Qpostscript
;
8717 /* Keyword symbols. */
8719 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8721 /* Indices of image specification fields in gs_format, below. */
8723 enum gs_keyword_index
8739 /* Vector of image_keyword structures describing the format
8740 of valid user-defined image specifications. */
8742 static struct image_keyword gs_format
[GS_LAST
] =
8744 {":type", IMAGE_SYMBOL_VALUE
, 1},
8745 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8746 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8747 {":file", IMAGE_STRING_VALUE
, 1},
8748 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8749 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8750 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8751 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8752 {":relief", IMAGE_INTEGER_VALUE
, 0},
8753 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8754 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8757 /* Structure describing the image type `ghostscript'. */
8759 static struct image_type gs_type
=
8769 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8772 gs_clear_image (f
, img
)
8776 /* IMG->data.ptr_val may contain a recorded colormap. */
8777 xfree (img
->data
.ptr_val
);
8778 x_clear_image (f
, img
);
8782 /* Return non-zero if OBJECT is a valid Ghostscript image
8789 struct image_keyword fmt
[GS_LAST
];
8793 bcopy (gs_format
, fmt
, sizeof fmt
);
8795 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
)
8796 || (fmt
[GS_ASCENT
].count
8797 && XFASTINT (fmt
[GS_ASCENT
].value
) > 100))
8800 /* Bounding box must be a list or vector containing 4 integers. */
8801 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8804 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8805 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8810 else if (VECTORP (tem
))
8812 if (XVECTOR (tem
)->size
!= 4)
8814 for (i
= 0; i
< 4; ++i
)
8815 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8825 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8834 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8835 struct gcpro gcpro1
, gcpro2
;
8837 double in_width
, in_height
;
8838 Lisp_Object pixel_colors
= Qnil
;
8840 /* Compute pixel size of pixmap needed from the given size in the
8841 image specification. Sizes in the specification are in pt. 1 pt
8842 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8844 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8845 in_width
= XFASTINT (pt_width
) / 72.0;
8846 img
->width
= in_width
* FRAME_W32_DISPLAY_INFO (f
)->resx
;
8847 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8848 in_height
= XFASTINT (pt_height
) / 72.0;
8849 img
->height
= in_height
* FRAME_W32_DISPLAY_INFO (f
)->resy
;
8851 /* Create the pixmap. */
8853 xassert (img
->pixmap
== 0);
8854 img
->pixmap
= XCreatePixmap (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
8855 img
->width
, img
->height
,
8856 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8861 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8865 /* Call the loader to fill the pixmap. It returns a process object
8866 if successful. We do not record_unwind_protect here because
8867 other places in redisplay like calling window scroll functions
8868 don't either. Let the Lisp loader use `unwind-protect' instead. */
8869 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8871 sprintf (buffer
, "%lu %lu",
8872 (unsigned long) FRAME_W32_WINDOW (f
),
8873 (unsigned long) img
->pixmap
);
8874 window_and_pixmap_id
= build_string (buffer
);
8876 sprintf (buffer
, "%lu %lu",
8877 FRAME_FOREGROUND_PIXEL (f
),
8878 FRAME_BACKGROUND_PIXEL (f
));
8879 pixel_colors
= build_string (buffer
);
8881 XSETFRAME (frame
, f
);
8882 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8884 loader
= intern ("gs-load-image");
8886 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8887 make_number (img
->width
),
8888 make_number (img
->height
),
8889 window_and_pixmap_id
,
8892 return PROCESSP (img
->data
.lisp_val
);
8896 /* Kill the Ghostscript process that was started to fill PIXMAP on
8897 frame F. Called from XTread_socket when receiving an event
8898 telling Emacs that Ghostscript has finished drawing. */
8901 x_kill_gs_process (pixmap
, f
)
8905 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8909 /* Find the image containing PIXMAP. */
8910 for (i
= 0; i
< c
->used
; ++i
)
8911 if (c
->images
[i
]->pixmap
== pixmap
)
8914 /* Kill the GS process. We should have found PIXMAP in the image
8915 cache and its image should contain a process object. */
8916 xassert (i
< c
->used
);
8918 xassert (PROCESSP (img
->data
.lisp_val
));
8919 Fkill_process (img
->data
.lisp_val
, Qnil
);
8920 img
->data
.lisp_val
= Qnil
;
8922 /* On displays with a mutable colormap, figure out the colors
8923 allocated for the image by looking at the pixels of an XImage for
8925 class = FRAME_W32_DISPLAY_INFO (f
)->visual
->class;
8926 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8932 /* Try to get an XImage for img->pixmep. */
8933 ximg
= XGetImage (FRAME_W32_DISPLAY (f
), img
->pixmap
,
8934 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8939 /* Initialize the color table. */
8940 init_color_table ();
8942 /* For each pixel of the image, look its color up in the
8943 color table. After having done so, the color table will
8944 contain an entry for each color used by the image. */
8945 for (y
= 0; y
< img
->height
; ++y
)
8946 for (x
= 0; x
< img
->width
; ++x
)
8948 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8949 lookup_pixel_color (f
, pixel
);
8952 /* Record colors in the image. Free color table and XImage. */
8953 img
->colors
= colors_in_color_table (&img
->ncolors
);
8954 free_color_table ();
8955 XDestroyImage (ximg
);
8957 #if 0 /* This doesn't seem to be the case. If we free the colors
8958 here, we get a BadAccess later in x_clear_image when
8959 freeing the colors. */
8960 /* We have allocated colors once, but Ghostscript has also
8961 allocated colors on behalf of us. So, to get the
8962 reference counts right, free them once. */
8965 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
8966 XFreeColors (FRAME_W32_DISPLAY (f
), cmap
,
8967 img
->colors
, img
->ncolors
, 0);
8972 image_error ("Cannot get X image of `%s'; colors will not be freed",
8979 #endif /* HAVE_GHOSTSCRIPT */
8982 /***********************************************************************
8984 ***********************************************************************/
8986 DEFUN ("x-change-window-property", Fx_change_window_property
,
8987 Sx_change_window_property
, 2, 3, 0,
8988 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
8989 PROP and VALUE must be strings. FRAME nil or omitted means use the
8990 selected frame. Value is VALUE. */)
8991 (prop
, value
, frame
)
8992 Lisp_Object frame
, prop
, value
;
8994 #if 0 /* MAC_TODO : port window properties to Mac */
8995 struct frame
*f
= check_x_frame (frame
);
8998 CHECK_STRING (prop
);
8999 CHECK_STRING (value
);
9002 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
9003 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
9004 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9005 SDATA (value
), SCHARS (value
));
9007 /* Make sure the property is set when we return. */
9008 XFlush (FRAME_W32_DISPLAY (f
));
9011 #endif /* MAC_TODO */
9017 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9018 Sx_delete_window_property
, 1, 2, 0,
9019 doc
: /* Remove window property PROP from X window of FRAME.
9020 FRAME nil or omitted means use the selected frame. Value is PROP. */)
9022 Lisp_Object prop
, frame
;
9024 #if 0 /* MAC_TODO : port window properties to Mac */
9026 struct frame
*f
= check_x_frame (frame
);
9029 CHECK_STRING (prop
);
9031 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
9032 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
9034 /* Make sure the property is removed when we return. */
9035 XFlush (FRAME_W32_DISPLAY (f
));
9037 #endif /* MAC_TODO */
9043 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9045 doc
: /* Value is the value of window property PROP on FRAME.
9046 If FRAME is nil or omitted, use the selected frame. Value is nil
9047 if FRAME hasn't a property with name PROP or if PROP has no string
9050 Lisp_Object prop
, frame
;
9052 #if 0 /* MAC_TODO : port window properties to Mac */
9054 struct frame
*f
= check_x_frame (frame
);
9057 Lisp_Object prop_value
= Qnil
;
9058 char *tmp_data
= NULL
;
9061 unsigned long actual_size
, bytes_remaining
;
9063 CHECK_STRING (prop
);
9065 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
9066 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
9067 prop_atom
, 0, 0, False
, XA_STRING
,
9068 &actual_type
, &actual_format
, &actual_size
,
9069 &bytes_remaining
, (unsigned char **) &tmp_data
);
9072 int size
= bytes_remaining
;
9077 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
9078 prop_atom
, 0, bytes_remaining
,
9080 &actual_type
, &actual_format
,
9081 &actual_size
, &bytes_remaining
,
9082 (unsigned char **) &tmp_data
);
9084 prop_value
= make_string (tmp_data
, size
);
9093 #endif /* MAC_TODO */
9099 /***********************************************************************
9101 ***********************************************************************/
9103 /* If non-null, an asynchronous timer that, when it expires, displays
9104 an hourglass cursor on all frames. */
9106 static struct atimer
*hourglass_atimer
;
9108 /* Non-zero means an hourglass cursor is currently shown. */
9110 static int hourglass_shown_p
;
9112 /* Number of seconds to wait before displaying an hourglass cursor. */
9114 static Lisp_Object Vhourglass_delay
;
9116 /* Default number of seconds to wait before displaying an hourglass
9119 #define DEFAULT_HOURGLASS_DELAY 1
9121 /* Function prototypes. */
9123 static void show_hourglass
P_ ((struct atimer
*));
9124 static void hide_hourglass
P_ ((void));
9127 /* Cancel a currently active hourglass timer, and start a new one. */
9132 #if 0 /* MAC_TODO: cursor shape changes. */
9134 int secs
, usecs
= 0;
9136 cancel_hourglass ();
9138 if (INTEGERP (Vhourglass_delay
)
9139 && XINT (Vhourglass_delay
) > 0)
9140 secs
= XFASTINT (Vhourglass_delay
);
9141 else if (FLOATP (Vhourglass_delay
)
9142 && XFLOAT_DATA (Vhourglass_delay
) > 0)
9145 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
9146 secs
= XFASTINT (tem
);
9147 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
9150 secs
= DEFAULT_HOURGLASS_DELAY
;
9152 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
9153 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
9154 show_hourglass
, NULL
);
9155 #endif /* MAC_TODO */
9159 /* Cancel the hourglass cursor timer if active, hide an hourglass
9165 if (hourglass_atimer
)
9167 cancel_atimer (hourglass_atimer
);
9168 hourglass_atimer
= NULL
;
9171 if (hourglass_shown_p
)
9176 /* Timer function of hourglass_atimer. TIMER is equal to
9179 Display an hourglass cursor on all frames by mapping the frames'
9180 hourglass_window. Set the hourglass_p flag in the frames'
9181 output_data.x structure to indicate that an hourglass cursor is
9182 shown on the frames. */
9185 show_hourglass (timer
)
9186 struct atimer
*timer
;
9188 #if 0 /* MAC_TODO: cursor shape changes. */
9189 /* The timer implementation will cancel this timer automatically
9190 after this function has run. Set hourglass_atimer to null
9191 so that we know the timer doesn't have to be canceled. */
9192 hourglass_atimer
= NULL
;
9194 if (!hourglass_shown_p
)
9196 Lisp_Object rest
, frame
;
9200 FOR_EACH_FRAME (rest
, frame
)
9201 if (FRAME_W32_P (XFRAME (frame
)))
9203 struct frame
*f
= XFRAME (frame
);
9205 f
->output_data
.w32
->hourglass_p
= 1;
9207 if (!f
->output_data
.w32
->hourglass_window
)
9209 unsigned long mask
= CWCursor
;
9210 XSetWindowAttributes attrs
;
9212 attrs
.cursor
= f
->output_data
.w32
->hourglass_cursor
;
9214 f
->output_data
.w32
->hourglass_window
9215 = XCreateWindow (FRAME_X_DISPLAY (f
),
9216 FRAME_OUTER_WINDOW (f
),
9217 0, 0, 32000, 32000, 0, 0,
9223 XMapRaised (FRAME_X_DISPLAY (f
),
9224 f
->output_data
.w32
->hourglass_window
);
9225 XFlush (FRAME_X_DISPLAY (f
));
9228 hourglass_shown_p
= 1;
9231 #endif /* MAC_TODO */
9235 /* Hide the hourglass cursor on all frames, if it is currently shown. */
9240 #if 0 /* MAC_TODO: cursor shape changes. */
9241 if (hourglass_shown_p
)
9243 Lisp_Object rest
, frame
;
9246 FOR_EACH_FRAME (rest
, frame
)
9248 struct frame
*f
= XFRAME (frame
);
9251 /* Watch out for newly created frames. */
9252 && f
->output_data
.x
->hourglass_window
)
9254 XUnmapWindow (FRAME_X_DISPLAY (f
),
9255 f
->output_data
.x
->hourglass_window
);
9256 /* Sync here because XTread_socket looks at the
9257 hourglass_p flag that is reset to zero below. */
9258 XSync (FRAME_X_DISPLAY (f
), False
);
9259 f
->output_data
.x
->hourglass_p
= 0;
9263 hourglass_shown_p
= 0;
9266 #endif /* MAC_TODO */
9271 /***********************************************************************
9273 ***********************************************************************/
9275 static Lisp_Object x_create_tip_frame
P_ ((struct mac_display_info
*,
9278 /* The frame of a currently visible tooltip, or null. */
9280 Lisp_Object tip_frame
;
9282 /* If non-nil, a timer started that hides the last tooltip when it
9285 Lisp_Object tip_timer
;
9288 /* If non-nil, a vector of 3 elements containing the last args
9289 with which x-show-tip was called. See there. */
9291 Lisp_Object last_show_tip_args
;
9293 /* Create a frame for a tooltip on the display described by DPYINFO.
9294 PARMS is a list of frame parameters. Value is the frame. */
9297 x_create_tip_frame (dpyinfo
, parms
)
9298 struct mac_display_info
*dpyinfo
;
9301 #if 0 /* MAC_TODO : Mac version */
9303 Lisp_Object frame
, tem
;
9305 long window_prompting
= 0;
9307 int count
= SPECPDL_INDEX ();
9308 struct gcpro gcpro1
, gcpro2
, gcpro3
;
9313 /* Use this general default value to start with until we know if
9314 this frame has a specified name. */
9315 Vx_resource_name
= Vinvocation_name
;
9318 kb
= dpyinfo
->kboard
;
9320 kb
= &the_only_kboard
;
9323 /* Get the name of the frame to use for resource lookup. */
9324 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
9326 && !EQ (name
, Qunbound
)
9328 error ("Invalid frame name--not a string or nil");
9329 Vx_resource_name
= name
;
9332 GCPRO3 (parms
, name
, frame
);
9333 tip_frame
= f
= make_frame (1);
9334 XSETFRAME (frame
, f
);
9335 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
9337 f
->output_method
= output_w32
;
9338 f
->output_data
.w32
=
9339 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
9340 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
9342 f
->output_data
.w32
->icon_bitmap
= -1;
9344 f
->output_data
.w32
->fontset
= -1;
9345 f
->icon_name
= Qnil
;
9348 FRAME_KBOARD (f
) = kb
;
9350 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
9351 f
->output_data
.w32
->explicit_parent
= 0;
9353 /* Set the name; the functions to which we pass f expect the name to
9355 if (EQ (name
, Qunbound
) || NILP (name
))
9357 f
->name
= build_string (dpyinfo
->x_id_name
);
9358 f
->explicit_name
= 0;
9363 f
->explicit_name
= 1;
9364 /* use the frame's title when getting resources for this frame. */
9365 specbind (Qx_resource_name
, name
);
9368 /* Extract the window parameters from the supplied values
9369 that are needed to determine window geometry. */
9373 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
9376 /* First, try whatever font the caller has specified. */
9379 tem
= Fquery_fontset (font
, Qnil
);
9381 font
= x_new_fontset (f
, SDATA (tem
));
9383 font
= x_new_font (f
, SDATA (font
));
9386 /* Try out a font which we hope has bold and italic variations. */
9387 if (!STRINGP (font
))
9388 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9389 if (!STRINGP (font
))
9390 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9391 if (! STRINGP (font
))
9392 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9393 if (! STRINGP (font
))
9394 /* This was formerly the first thing tried, but it finds too many fonts
9395 and takes too long. */
9396 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9397 /* If those didn't work, look for something which will at least work. */
9398 if (! STRINGP (font
))
9399 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9401 if (! STRINGP (font
))
9402 font
= build_string ("fixed");
9404 x_default_parameter (f
, parms
, Qfont
, font
,
9405 "font", "Font", RES_TYPE_STRING
);
9408 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
9409 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
9411 /* This defaults to 2 in order to match xterm. We recognize either
9412 internalBorderWidth or internalBorder (which is what xterm calls
9414 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9418 value
= w32_get_arg (parms
, Qinternal_border_width
,
9419 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
9420 if (! EQ (value
, Qunbound
))
9421 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
9425 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
9426 "internalBorderWidth", "internalBorderWidth",
9429 /* Also do the stuff which must be set before the window exists. */
9430 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
9431 "foreground", "Foreground", RES_TYPE_STRING
);
9432 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
9433 "background", "Background", RES_TYPE_STRING
);
9434 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
9435 "pointerColor", "Foreground", RES_TYPE_STRING
);
9436 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
9437 "cursorColor", "Foreground", RES_TYPE_STRING
);
9438 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
9439 "borderColor", "BorderColor", RES_TYPE_STRING
);
9441 /* Init faces before x_default_parameter is called for scroll-bar
9442 parameters because that function calls x_set_scroll_bar_width,
9443 which calls change_frame_size, which calls Fset_window_buffer,
9444 which runs hooks, which call Fvertical_motion. At the end, we
9445 end up in init_iterator with a null face cache, which should not
9447 init_frame_faces (f
);
9449 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
9450 window_prompting
= x_figure_window_size (f
, parms
);
9452 if (window_prompting
& XNegative
)
9454 if (window_prompting
& YNegative
)
9455 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
9457 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
9461 if (window_prompting
& YNegative
)
9462 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
9464 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
9467 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
9469 XSetWindowAttributes attrs
;
9473 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
9474 /* Window managers looks at the override-redirect flag to
9475 determine whether or net to give windows a decoration (Xlib
9477 attrs
.override_redirect
= True
;
9478 attrs
.save_under
= True
;
9479 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
9480 /* Arrange for getting MapNotify and UnmapNotify events. */
9481 attrs
.event_mask
= StructureNotifyMask
;
9483 = FRAME_W32_WINDOW (f
)
9484 = XCreateWindow (FRAME_W32_DISPLAY (f
),
9485 FRAME_W32_DISPLAY_INFO (f
)->root_window
,
9486 /* x, y, width, height */
9490 CopyFromParent
, InputOutput
, CopyFromParent
,
9497 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
9498 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9499 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
9500 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9501 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
9502 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
9504 /* Dimensions, especially f->height, must be done via change_frame_size.
9505 Change will not be effected unless different from the current
9510 SET_FRAME_WIDTH (f
, 0);
9511 change_frame_size (f
, height
, width
, 1, 0, 0);
9517 /* It is now ok to make the frame official even if we get an error
9518 below. And the frame needs to be on Vframe_list or making it
9519 visible won't work. */
9520 Vframe_list
= Fcons (frame
, Vframe_list
);
9522 /* Now that the frame is official, it counts as a reference to
9524 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
9526 return unbind_to (count
, frame
);
9527 #endif /* MAC_TODO */
9532 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
9533 doc
: /* Show STRING in a "tooltip" window on frame FRAME.
9534 A tooltip window is a small window displaying a string.
9536 FRAME nil or omitted means use the selected frame.
9538 PARMS is an optional list of frame parameters which can be used to
9539 change the tooltip's appearance.
9541 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
9542 means use the default timeout of 5 seconds.
9544 If the list of frame parameters PARAMS contains a `left' parameters,
9545 the tooltip is displayed at that x-position. Otherwise it is
9546 displayed at the mouse position, with offset DX added (default is 5 if
9547 DX isn't specified). Likewise for the y-position; if a `top' frame
9548 parameter is specified, it determines the y-position of the tooltip
9549 window, otherwise it is displayed at the mouse position, with offset
9550 DY added (default is 10). */)
9551 (string
, frame
, parms
, timeout
, dx
, dy
)
9552 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
9557 Lisp_Object buffer
, top
, left
;
9558 struct buffer
*old_buffer
;
9559 struct text_pos pos
;
9560 int i
, width
, height
;
9561 int root_x
, root_y
, win_x
, win_y
;
9563 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
9564 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
9565 int count
= SPECPDL_INDEX ();
9567 specbind (Qinhibit_redisplay
, Qt
);
9569 GCPRO4 (string
, parms
, frame
, timeout
);
9571 CHECK_STRING (string
);
9572 f
= check_x_frame (frame
);
9574 timeout
= make_number (5);
9576 CHECK_NATNUM (timeout
);
9579 dx
= make_number (5);
9584 dy
= make_number (-10);
9588 if (NILP (last_show_tip_args
))
9589 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
9591 if (!NILP (tip_frame
))
9593 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
9594 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
9595 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
9597 if (EQ (frame
, last_frame
)
9598 && !NILP (Fequal (last_string
, string
))
9599 && !NILP (Fequal (last_parms
, parms
)))
9601 struct frame
*f
= XFRAME (tip_frame
);
9603 /* Only DX and DY have changed. */
9604 if (!NILP (tip_timer
))
9606 Lisp_Object timer
= tip_timer
;
9608 call1 (Qcancel_timer
, timer
);
9611 #if 0 /* MAC_TODO : Mac specifics */
9613 compute_tip_xy (f
, parms
, dx
, dy
, &root_x
, &root_y
);
9614 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9615 root_x
, root_y
- PIXEL_HEIGHT (f
));
9617 #endif /* MAC_TODO */
9622 /* Hide a previous tip, if any. */
9625 ASET (last_show_tip_args
, 0, string
);
9626 ASET (last_show_tip_args
, 1, frame
);
9627 ASET (last_show_tip_args
, 2, parms
);
9629 /* Add default values to frame parameters. */
9630 if (NILP (Fassq (Qname
, parms
)))
9631 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
9632 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9633 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
9634 if (NILP (Fassq (Qborder_width
, parms
)))
9635 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
9636 if (NILP (Fassq (Qborder_color
, parms
)))
9637 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
9638 if (NILP (Fassq (Qbackground_color
, parms
)))
9639 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
9642 /* Create a frame for the tooltip, and record it in the global
9643 variable tip_frame. */
9644 frame
= x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f
), parms
);
9647 /* Set up the frame's root window. Currently we use a size of 80
9648 columns x 40 lines. If someone wants to show a larger tip, he
9649 will loose. I don't think this is a realistic case. */
9650 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
9651 w
->left
= w
->top
= make_number (0);
9652 w
->width
= make_number (80);
9653 w
->height
= make_number (40);
9655 w
->pseudo_window_p
= 1;
9657 /* Display the tooltip text in a temporary buffer. */
9658 buffer
= Fget_buffer_create (build_string (" *tip*"));
9659 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
9660 old_buffer
= current_buffer
;
9661 set_buffer_internal_1 (XBUFFER (buffer
));
9663 Finsert (1, &string
);
9664 clear_glyph_matrix (w
->desired_matrix
);
9665 clear_glyph_matrix (w
->current_matrix
);
9666 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
9667 try_window (FRAME_ROOT_WINDOW (f
), pos
);
9669 /* Compute width and height of the tooltip. */
9671 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
9673 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
9677 /* Stop at the first empty row at the end. */
9678 if (!row
->enabled_p
|| !row
->displays_text_p
)
9681 /* Let the row go over the full width of the frame. */
9682 row
->full_width_p
= 1;
9684 /* There's a glyph at the end of rows that is use to place
9685 the cursor there. Don't include the width of this glyph. */
9686 if (row
->used
[TEXT_AREA
])
9688 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
9689 row_width
= row
->pixel_width
- last
->pixel_width
;
9692 row_width
= row
->pixel_width
;
9694 height
+= row
->height
;
9695 width
= max (width
, row_width
);
9698 /* Add the frame's internal border to the width and height the X
9699 window should have. */
9700 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9701 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9703 /* Move the tooltip window where the mouse pointer is. Resize and
9705 #if 0 /* TODO : Mac specifics */
9706 compute_tip_xy (f
, parms
, dx
, dy
, &root_x
, &root_y
);
9709 XQueryPointer (FRAME_W32_DISPLAY (f
), FRAME_W32_DISPLAY_INFO (f
)->root_window
,
9710 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
9711 XMoveResizeWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
9712 root_x
+ 5, root_y
- height
- 5, width
, height
);
9713 XMapRaised (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
9715 #endif /* MAC_TODO */
9717 /* Draw into the window. */
9718 w
->must_be_updated_p
= 1;
9719 update_single_window (w
, 1);
9721 /* Restore original current buffer. */
9722 set_buffer_internal_1 (old_buffer
);
9723 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
9726 /* Let the tip disappear after timeout seconds. */
9727 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
9728 intern ("x-hide-tip"));
9731 return unbind_to (count
, Qnil
);
9735 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
9736 doc
: /* Hide the current tooltip window, if there is any.
9737 Value is t is tooltip was open, nil otherwise. */)
9741 Lisp_Object deleted
, frame
, timer
;
9742 struct gcpro gcpro1
, gcpro2
;
9744 /* Return quickly if nothing to do. */
9745 if (NILP (tip_timer
) && NILP (tip_frame
))
9750 GCPRO2 (frame
, timer
);
9751 tip_frame
= tip_timer
= deleted
= Qnil
;
9753 count
= SPECPDL_INDEX ();
9754 specbind (Qinhibit_redisplay
, Qt
);
9755 specbind (Qinhibit_quit
, Qt
);
9758 call1 (Qcancel_timer
, timer
);
9762 Fdelete_frame (frame
, Qnil
);
9767 return unbind_to (count
, deleted
);
9772 /***********************************************************************
9773 File selection dialog
9774 ***********************************************************************/
9776 #if 0 /* MAC_TODO: can standard file dialog */
9777 extern Lisp_Object Qfile_name_history
;
9779 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
9780 doc
: /* Read file name, prompting with PROMPT in directory DIR.
9781 Use a file selection dialog.
9782 Select DEFAULT-FILENAME in the dialog's file selection box, if
9783 specified. Don't let the user enter a file name in the file
9784 selection dialog's entry field, if MUSTMATCH is non-nil. */)
9785 (prompt
, dir
, default_filename
, mustmatch
)
9786 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
9788 struct frame
*f
= SELECTED_FRAME ();
9789 Lisp_Object file
= Qnil
;
9790 int count
= SPECPDL_INDEX ();
9791 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
9792 char filename
[MAX_PATH
+ 1];
9793 char init_dir
[MAX_PATH
+ 1];
9794 int use_dialog_p
= 1;
9796 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
9797 CHECK_STRING (prompt
);
9800 /* Create the dialog with PROMPT as title, using DIR as initial
9801 directory and using "*" as pattern. */
9802 dir
= Fexpand_file_name (dir
, Qnil
);
9803 strncpy (init_dir
, SDATA (dir
), MAX_PATH
);
9804 init_dir
[MAX_PATH
] = '\0';
9805 unixtodos_filename (init_dir
);
9807 if (STRINGP (default_filename
))
9809 char *file_name_only
;
9810 char *full_path_name
= SDATA (default_filename
);
9812 unixtodos_filename (full_path_name
);
9814 file_name_only
= strrchr (full_path_name
, '\\');
9815 if (!file_name_only
)
9816 file_name_only
= full_path_name
;
9821 /* If default_file_name is a directory, don't use the open
9822 file dialog, as it does not support selecting
9824 if (!(*file_name_only
))
9828 strncpy (filename
, file_name_only
, MAX_PATH
);
9829 filename
[MAX_PATH
] = '\0';
9836 OPENFILENAME file_details
;
9837 char *filename_file
;
9839 /* Prevent redisplay. */
9840 specbind (Qinhibit_redisplay
, Qt
);
9843 bzero (&file_details
, sizeof (file_details
));
9844 file_details
.lStructSize
= sizeof (file_details
);
9845 file_details
.hwndOwner
= FRAME_W32_WINDOW (f
);
9846 file_details
.lpstrFile
= filename
;
9847 file_details
.nMaxFile
= sizeof (filename
);
9848 file_details
.lpstrInitialDir
= init_dir
;
9849 file_details
.lpstrTitle
= SDATA (prompt
);
9850 file_details
.Flags
= OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
;
9852 if (!NILP (mustmatch
))
9853 file_details
.Flags
|= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
;
9855 if (GetOpenFileName (&file_details
))
9857 dostounix_filename (filename
);
9858 file
= build_string (filename
);
9864 file
= unbind_to (count
, file
);
9866 /* Open File dialog will not allow folders to be selected, so resort
9867 to minibuffer completing reads for directories. */
9869 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
9870 dir
, mustmatch
, dir
, Qfile_name_history
,
9871 default_filename
, Qnil
);
9875 /* Make "Cancel" equivalent to C-g. */
9877 Fsignal (Qquit
, Qnil
);
9879 return unbind_to (count
, file
);
9881 #endif /* MAC_TODO */
9885 /***********************************************************************
9887 ***********************************************************************/
9891 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9892 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
9896 return valid_image_p (spec
) ? Qt
: Qnil
;
9900 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
9906 if (valid_image_p (spec
))
9907 id
= lookup_image (SELECTED_FRAME (), spec
);
9910 return make_number (id
);
9913 #endif /* GLYPH_DEBUG != 0 */
9920 /* Certainly running on Mac. */
9923 /* The section below is built by the lisp expression at the top of the file,
9924 just above where these variables are declared. */
9925 /*&&& init symbols here &&&*/
9926 Qauto_raise
= intern ("auto-raise");
9927 staticpro (&Qauto_raise
);
9928 Qauto_lower
= intern ("auto-lower");
9929 staticpro (&Qauto_lower
);
9930 Qbar
= intern ("bar");
9932 Qborder_color
= intern ("border-color");
9933 staticpro (&Qborder_color
);
9934 Qborder_width
= intern ("border-width");
9935 staticpro (&Qborder_width
);
9936 Qbox
= intern ("box");
9938 Qcursor_color
= intern ("cursor-color");
9939 staticpro (&Qcursor_color
);
9940 Qcursor_type
= intern ("cursor-type");
9941 staticpro (&Qcursor_type
);
9942 Qgeometry
= intern ("geometry");
9943 staticpro (&Qgeometry
);
9944 Qicon_left
= intern ("icon-left");
9945 staticpro (&Qicon_left
);
9946 Qicon_top
= intern ("icon-top");
9947 staticpro (&Qicon_top
);
9948 Qicon_type
= intern ("icon-type");
9949 staticpro (&Qicon_type
);
9950 Qicon_name
= intern ("icon-name");
9951 staticpro (&Qicon_name
);
9952 Qinternal_border_width
= intern ("internal-border-width");
9953 staticpro (&Qinternal_border_width
);
9954 Qleft
= intern ("left");
9956 Qright
= intern ("right");
9957 staticpro (&Qright
);
9958 Qmouse_color
= intern ("mouse-color");
9959 staticpro (&Qmouse_color
);
9960 Qnone
= intern ("none");
9962 Qparent_id
= intern ("parent-id");
9963 staticpro (&Qparent_id
);
9964 Qscroll_bar_width
= intern ("scroll-bar-width");
9965 staticpro (&Qscroll_bar_width
);
9966 Qsuppress_icon
= intern ("suppress-icon");
9967 staticpro (&Qsuppress_icon
);
9968 Qundefined_color
= intern ("undefined-color");
9969 staticpro (&Qundefined_color
);
9970 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
9971 staticpro (&Qvertical_scroll_bars
);
9972 Qvisibility
= intern ("visibility");
9973 staticpro (&Qvisibility
);
9974 Qwindow_id
= intern ("window-id");
9975 staticpro (&Qwindow_id
);
9976 Qx_frame_parameter
= intern ("x-frame-parameter");
9977 staticpro (&Qx_frame_parameter
);
9978 Qx_resource_name
= intern ("x-resource-name");
9979 staticpro (&Qx_resource_name
);
9980 Quser_position
= intern ("user-position");
9981 staticpro (&Quser_position
);
9982 Quser_size
= intern ("user-size");
9983 staticpro (&Quser_size
);
9984 Qscreen_gamma
= intern ("screen-gamma");
9985 staticpro (&Qscreen_gamma
);
9986 Qline_spacing
= intern ("line-spacing");
9987 staticpro (&Qline_spacing
);
9988 Qcenter
= intern ("center");
9989 staticpro (&Qcenter
);
9990 /* This is the end of symbol initialization. */
9992 Qhyper
= intern ("hyper");
9993 staticpro (&Qhyper
);
9994 Qsuper
= intern ("super");
9995 staticpro (&Qsuper
);
9996 Qmeta
= intern ("meta");
9998 Qalt
= intern ("alt");
10000 Qctrl
= intern ("ctrl");
10001 staticpro (&Qctrl
);
10002 Qcontrol
= intern ("control");
10003 staticpro (&Qcontrol
);
10004 Qshift
= intern ("shift");
10005 staticpro (&Qshift
);
10007 /* Text property `display' should be nonsticky by default. */
10008 Vtext_property_default_nonsticky
10009 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
10012 Qlaplace
= intern ("laplace");
10013 staticpro (&Qlaplace
);
10015 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10016 staticpro (&Qface_set_after_frame_default
);
10018 Fput (Qundefined_color
, Qerror_conditions
,
10019 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10020 Fput (Qundefined_color
, Qerror_message
,
10021 build_string ("Undefined color"));
10023 init_x_parm_symbols ();
10025 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10026 doc
: /* List of directories to search for bitmap files for w32. */);
10027 Vx_bitmap_file_path
= decode_env_path ((char *) 0, "PATH");
10029 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10030 doc
: /* The shape of the pointer when over text.
10031 Changing the value does not affect existing frames
10032 unless you set the mouse color. */);
10033 Vx_pointer_shape
= Qnil
;
10035 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
10036 doc
: /* The name Emacs uses to look up resources; for internal use only.
10037 `x-get-resource' uses this as the first component of the instance name
10038 when requesting resource values.
10039 Emacs initially sets `x-resource-name' to the name under which Emacs
10040 was invoked, or to the value specified with the `-name' or `-rn'
10041 switches, if present. */);
10042 Vx_resource_name
= Qnil
;
10044 Vx_nontext_pointer_shape
= Qnil
;
10046 Vx_mode_pointer_shape
= Qnil
;
10048 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
10049 doc
: /* The shape of the pointer when Emacs is hourglass.
10050 This variable takes effect when you create a new frame
10051 or when you set the mouse color. */);
10052 Vx_hourglass_pointer_shape
= Qnil
;
10054 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
10055 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10056 display_hourglass_p
= 1;
10058 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
10059 doc
: /* *Seconds to wait before displaying an hourglass pointer.
10060 Value must be an integer or float. */);
10061 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
10063 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10064 &Vx_sensitive_text_pointer_shape
,
10065 doc
: /* The shape of the pointer when over mouse-sensitive text.
10066 This variable takes effect when you create a new frame
10067 or when you set the mouse color. */);
10068 Vx_sensitive_text_pointer_shape
= Qnil
;
10070 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
10071 doc
: /* A string indicating the foreground color of the cursor box. */);
10072 Vx_cursor_fore_pixel
= Qnil
;
10074 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
10075 doc
: /* Non-nil if no window manager is in use.
10076 Emacs doesn't try to figure this out; this is always nil
10077 unless you set it to something else. */);
10078 /* We don't have any way to find this out, so set it to nil
10079 and maybe the user would like to set it to t. */
10080 Vx_no_window_manager
= Qnil
;
10082 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10083 &Vx_pixel_size_width_font_regexp
,
10084 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10086 Since Emacs gets width of a font matching with this regexp from
10087 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10088 such a font. This is especially effective for such large fonts as
10089 Chinese, Japanese, and Korean. */);
10090 Vx_pixel_size_width_font_regexp
= Qnil
;
10092 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
10093 doc
: /* Time after which cached images are removed from the cache.
10094 When an image has not been displayed this many seconds, remove it
10095 from the image cache. Value must be an integer or nil with nil
10096 meaning don't clear the cache. */);
10097 Vimage_cache_eviction_delay
= make_number (30 * 60);
10099 #if 0 /* MAC_TODO: implement get X resource */
10100 defsubr (&Sx_get_resource
);
10102 defsubr (&Sx_change_window_property
);
10103 defsubr (&Sx_delete_window_property
);
10104 defsubr (&Sx_window_property
);
10105 defsubr (&Sxw_display_color_p
);
10106 defsubr (&Sx_display_grayscale_p
);
10107 defsubr (&Sxw_color_defined_p
);
10108 defsubr (&Sxw_color_values
);
10109 defsubr (&Sx_server_max_request_size
);
10110 defsubr (&Sx_server_vendor
);
10111 defsubr (&Sx_server_version
);
10112 defsubr (&Sx_display_pixel_width
);
10113 defsubr (&Sx_display_pixel_height
);
10114 defsubr (&Sx_display_mm_width
);
10115 defsubr (&Sx_display_mm_height
);
10116 defsubr (&Sx_display_screens
);
10117 defsubr (&Sx_display_planes
);
10118 defsubr (&Sx_display_color_cells
);
10119 defsubr (&Sx_display_visual_class
);
10120 defsubr (&Sx_display_backing_store
);
10121 defsubr (&Sx_display_save_under
);
10122 #if 0 /* MAC_TODO: implement XParseGeometry */
10123 defsubr (&Sx_parse_geometry
);
10125 defsubr (&Sx_create_frame
);
10126 #if 0 /* MAC_TODO: implement network support */
10127 defsubr (&Sx_open_connection
);
10128 defsubr (&Sx_close_connection
);
10130 defsubr (&Sx_display_list
);
10131 defsubr (&Sx_synchronize
);
10133 /* Setting callback functions for fontset handler. */
10134 get_font_info_func
= x_get_font_info
;
10136 #if 0 /* This function pointer doesn't seem to be used anywhere.
10137 And the pointer assigned has the wrong type, anyway. */
10138 list_fonts_func
= x_list_fonts
;
10141 load_font_func
= x_load_font
;
10142 find_ccl_program_func
= x_find_ccl_program
;
10143 query_font_func
= x_query_font
;
10145 set_frame_fontset_func
= x_set_font
;
10146 check_window_system_func
= check_mac
;
10148 #if 0 /* MAC_TODO: Image support for Mac Images. */
10149 Qxbm
= intern ("xbm");
10151 QCtype
= intern (":type");
10152 staticpro (&QCtype
);
10153 QCconversion
= intern (":conversion");
10154 staticpro (&QCconversion
);
10155 QCheuristic_mask
= intern (":heuristic-mask");
10156 staticpro (&QCheuristic_mask
);
10157 QCcolor_symbols
= intern (":color-symbols");
10158 staticpro (&QCcolor_symbols
);
10159 QCascent
= intern (":ascent");
10160 staticpro (&QCascent
);
10161 QCmargin
= intern (":margin");
10162 staticpro (&QCmargin
);
10163 QCrelief
= intern (":relief");
10164 staticpro (&QCrelief
);
10165 Qpostscript
= intern ("postscript");
10166 staticpro (&Qpostscript
);
10167 QCloader
= intern (":loader");
10168 staticpro (&QCloader
);
10169 QCbounding_box
= intern (":bounding-box");
10170 staticpro (&QCbounding_box
);
10171 QCpt_width
= intern (":pt-width");
10172 staticpro (&QCpt_width
);
10173 QCpt_height
= intern (":pt-height");
10174 staticpro (&QCpt_height
);
10175 QCindex
= intern (":index");
10176 staticpro (&QCindex
);
10177 Qpbm
= intern ("pbm");
10181 Qxpm
= intern ("xpm");
10186 Qjpeg
= intern ("jpeg");
10187 staticpro (&Qjpeg
);
10191 Qtiff
= intern ("tiff");
10192 staticpro (&Qtiff
);
10196 Qgif
= intern ("gif");
10201 Qpng
= intern ("png");
10205 defsubr (&Sclear_image_cache
);
10208 defsubr (&Simagep
);
10209 defsubr (&Slookup_image
);
10211 #endif /* MAC_TODO */
10213 hourglass_atimer
= NULL
;
10214 hourglass_shown_p
= 0;
10216 defsubr (&Sx_show_tip
);
10217 defsubr (&Sx_hide_tip
);
10218 staticpro (&tip_timer
);
10221 #if 0 /* MAC_TODO */
10222 defsubr (&Sx_file_dialog
);
10230 image_types
= NULL
;
10231 Vimage_types
= Qnil
;
10233 define_image_type (&xbm_type
);
10234 #if 0 /* NTEMACS_TODO : Image support for W32 */
10235 define_image_type (&gs_type
);
10236 define_image_type (&pbm_type
);
10239 define_image_type (&xpm_type
);
10243 define_image_type (&jpeg_type
);
10247 define_image_type (&tiff_type
);
10251 define_image_type (&gif_type
);
10255 define_image_type (&png_type
);
10257 #endif /* NTEMACS_TODO */