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