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