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