Use wildcards.
[emacs.git] / src / xfns.c
blobc8bce15fbd642ae597ba9ce16a26f324307dd723
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
35 #include "lisp.h"
36 #include "xterm.h"
37 #include "frame.h"
38 #include "window.h"
39 #include "buffer.h"
40 #include "intervals.h"
41 #include "dispextern.h"
42 #include "keyboard.h"
43 #include "blockinput.h"
44 #include <epaths.h>
45 #include "charset.h"
46 #include "coding.h"
47 #include "fontset.h"
48 #include "systime.h"
49 #include "termhooks.h"
50 #include "atimer.h"
52 #ifdef HAVE_X_WINDOWS
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
58 #ifndef VMS
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
61 #else
62 #include <X11/bitmaps/gray>
63 #endif
64 #else
65 #include "[.bitmaps]gray.xbm"
66 #endif
68 #ifdef USE_X_TOOLKIT
69 #include <X11/Shell.h>
71 #ifndef USE_MOTIF
72 #include <X11/Xaw/Paned.h>
73 #include <X11/Xaw/Label.h>
74 #endif /* USE_MOTIF */
76 #ifdef USG
77 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
78 #include <X11/Xos.h>
79 #define USG
80 #else
81 #include <X11/Xos.h>
82 #endif
84 #include "widget.h"
86 #include "../lwlib/lwlib.h"
88 #ifdef USE_MOTIF
89 #include <Xm/Xm.h>
90 #include <Xm/DialogS.h>
91 #include <Xm/FileSB.h>
92 #endif
94 /* Do the EDITRES protocol if running X11R5
95 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
98 #define HACK_EDITRES
99 extern void _XEditResCheckMessages ();
100 #endif /* R5 + Athena */
102 /* Unique id counter for widgets created by the Lucid Widget Library. */
104 extern LWLIB_ID widget_id_tick;
106 #ifdef USE_LUCID
107 /* This is part of a kludge--see lwlib/xlwmenu.c. */
108 extern XFontStruct *xlwmenu_default_font;
109 #endif
111 extern void free_frame_menubar ();
112 extern double atof ();
114 #ifdef USE_MOTIF
116 /* LessTif/Motif version info. */
118 static Lisp_Object Vmotif_version_string;
120 #endif /* USE_MOTIF */
122 #endif /* USE_X_TOOLKIT */
124 #ifdef HAVE_X11R4
125 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
126 #else
127 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
128 #endif
130 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
131 it, and including `bitmaps/gray' more than once is a problem when
132 config.h defines `static' as an empty replacement string. */
134 int gray_bitmap_width = gray_width;
135 int gray_bitmap_height = gray_height;
136 char *gray_bitmap_bits = gray_bits;
138 /* The name we're using in resource queries. Most often "emacs". */
140 Lisp_Object Vx_resource_name;
142 /* The application class we're using in resource queries.
143 Normally "Emacs". */
145 Lisp_Object Vx_resource_class;
147 /* Non-zero means we're allowed to display an hourglass cursor. */
149 int display_hourglass_p;
151 /* The background and shape of the mouse pointer, and shape when not
152 over text or in the modeline. */
154 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
155 Lisp_Object Vx_hourglass_pointer_shape;
157 /* The shape when over mouse-sensitive text. */
159 Lisp_Object Vx_sensitive_text_pointer_shape;
161 /* If non-nil, the pointer shape to indicate that windows can be
162 dragged horizontally. */
164 Lisp_Object Vx_window_horizontal_drag_shape;
166 /* Color of chars displayed in cursor box. */
168 Lisp_Object Vx_cursor_fore_pixel;
170 /* Nonzero if using X. */
172 static int x_in_use;
174 /* Non nil if no window manager is in use. */
176 Lisp_Object Vx_no_window_manager;
178 /* Search path for bitmap files. */
180 Lisp_Object Vx_bitmap_file_path;
182 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
184 Lisp_Object Vx_pixel_size_width_font_regexp;
186 Lisp_Object Qauto_raise;
187 Lisp_Object Qauto_lower;
188 Lisp_Object Qbar;
189 Lisp_Object Qborder_color;
190 Lisp_Object Qborder_width;
191 Lisp_Object Qbox;
192 Lisp_Object Qcursor_color;
193 Lisp_Object Qcursor_type;
194 Lisp_Object Qgeometry;
195 Lisp_Object Qicon_left;
196 Lisp_Object Qicon_top;
197 Lisp_Object Qicon_type;
198 Lisp_Object Qicon_name;
199 Lisp_Object Qinternal_border_width;
200 Lisp_Object Qleft;
201 Lisp_Object Qright;
202 Lisp_Object Qmouse_color;
203 Lisp_Object Qnone;
204 Lisp_Object Qouter_window_id;
205 Lisp_Object Qparent_id;
206 Lisp_Object Qscroll_bar_width;
207 Lisp_Object Qsuppress_icon;
208 extern Lisp_Object Qtop;
209 Lisp_Object Qundefined_color;
210 Lisp_Object Qvertical_scroll_bars;
211 Lisp_Object Qvisibility;
212 Lisp_Object Qwindow_id;
213 Lisp_Object Qx_frame_parameter;
214 Lisp_Object Qx_resource_name;
215 Lisp_Object Quser_position;
216 Lisp_Object Quser_size;
217 extern Lisp_Object Qdisplay;
218 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
219 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
220 Lisp_Object Qcompound_text, Qcancel_timer;
221 Lisp_Object Qwait_for_wm;
223 /* The below are defined in frame.c. */
225 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
226 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
227 extern Lisp_Object Qtool_bar_lines;
229 extern Lisp_Object Vwindow_system_version;
231 Lisp_Object Qface_set_after_frame_default;
233 #if GLYPH_DEBUG
234 int image_cache_refcount, dpyinfo_refcount;
235 #endif
239 /* Error if we are not connected to X. */
241 void
242 check_x ()
244 if (! x_in_use)
245 error ("X windows are not in use or not initialized");
248 /* Nonzero if we can use mouse menus.
249 You should not call this unless HAVE_MENUS is defined. */
252 have_menus_p ()
254 return x_in_use;
257 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
258 and checking validity for X. */
260 FRAME_PTR
261 check_x_frame (frame)
262 Lisp_Object frame;
264 FRAME_PTR f;
266 if (NILP (frame))
267 frame = selected_frame;
268 CHECK_LIVE_FRAME (frame);
269 f = XFRAME (frame);
270 if (! FRAME_X_P (f))
271 error ("Non-X frame used");
272 return f;
275 /* Let the user specify an X display with a frame.
276 nil stands for the selected frame--or, if that is not an X frame,
277 the first X display on the list. */
279 static struct x_display_info *
280 check_x_display_info (frame)
281 Lisp_Object frame;
283 struct x_display_info *dpyinfo = NULL;
285 if (NILP (frame))
287 struct frame *sf = XFRAME (selected_frame);
289 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
290 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
291 else if (x_display_list != 0)
292 dpyinfo = x_display_list;
293 else
294 error ("X windows are not in use or not initialized");
296 else if (STRINGP (frame))
297 dpyinfo = x_display_info_for_name (frame);
298 else
300 FRAME_PTR f;
302 CHECK_LIVE_FRAME (frame);
303 f = XFRAME (frame);
304 if (! FRAME_X_P (f))
305 error ("Non-X frame used");
306 dpyinfo = FRAME_X_DISPLAY_INFO (f);
309 return dpyinfo;
313 /* Return the Emacs frame-object corresponding to an X window.
314 It could be the frame's main window or an icon window. */
316 /* This function can be called during GC, so use GC_xxx type test macros. */
318 struct frame *
319 x_window_to_frame (dpyinfo, wdesc)
320 struct x_display_info *dpyinfo;
321 int wdesc;
323 Lisp_Object tail, frame;
324 struct frame *f;
326 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
328 frame = XCAR (tail);
329 if (!GC_FRAMEP (frame))
330 continue;
331 f = XFRAME (frame);
332 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
333 continue;
334 if (f->output_data.x->hourglass_window == wdesc)
335 return f;
336 #ifdef USE_X_TOOLKIT
337 if ((f->output_data.x->edit_widget
338 && XtWindow (f->output_data.x->edit_widget) == wdesc)
339 /* A tooltip frame? */
340 || (!f->output_data.x->edit_widget
341 && FRAME_X_WINDOW (f) == wdesc)
342 || f->output_data.x->icon_desc == wdesc)
343 return f;
344 #else /* not USE_X_TOOLKIT */
345 if (FRAME_X_WINDOW (f) == wdesc
346 || f->output_data.x->icon_desc == wdesc)
347 return f;
348 #endif /* not USE_X_TOOLKIT */
350 return 0;
353 #ifdef USE_X_TOOLKIT
354 /* Like x_window_to_frame but also compares the window with the widget's
355 windows. */
357 struct frame *
358 x_any_window_to_frame (dpyinfo, wdesc)
359 struct x_display_info *dpyinfo;
360 int wdesc;
362 Lisp_Object tail, frame;
363 struct frame *f, *found;
364 struct x_output *x;
366 found = NULL;
367 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
369 frame = XCAR (tail);
370 if (!GC_FRAMEP (frame))
371 continue;
373 f = XFRAME (frame);
374 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
376 /* This frame matches if the window is any of its widgets. */
377 x = f->output_data.x;
378 if (x->hourglass_window == wdesc)
379 found = f;
380 else if (x->widget)
382 if (wdesc == XtWindow (x->widget)
383 || wdesc == XtWindow (x->column_widget)
384 || wdesc == XtWindow (x->edit_widget))
385 found = f;
386 /* Match if the window is this frame's menubar. */
387 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
388 found = f;
390 else if (FRAME_X_WINDOW (f) == wdesc)
391 /* A tooltip frame. */
392 found = f;
396 return found;
399 /* Likewise, but exclude the menu bar widget. */
401 struct frame *
402 x_non_menubar_window_to_frame (dpyinfo, wdesc)
403 struct x_display_info *dpyinfo;
404 int wdesc;
406 Lisp_Object tail, frame;
407 struct frame *f;
408 struct x_output *x;
410 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
412 frame = XCAR (tail);
413 if (!GC_FRAMEP (frame))
414 continue;
415 f = XFRAME (frame);
416 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
417 continue;
418 x = f->output_data.x;
419 /* This frame matches if the window is any of its widgets. */
420 if (x->hourglass_window == wdesc)
421 return f;
422 else if (x->widget)
424 if (wdesc == XtWindow (x->widget)
425 || wdesc == XtWindow (x->column_widget)
426 || wdesc == XtWindow (x->edit_widget))
427 return f;
429 else if (FRAME_X_WINDOW (f) == wdesc)
430 /* A tooltip frame. */
431 return f;
433 return 0;
436 /* Likewise, but consider only the menu bar widget. */
438 struct frame *
439 x_menubar_window_to_frame (dpyinfo, wdesc)
440 struct x_display_info *dpyinfo;
441 int wdesc;
443 Lisp_Object tail, frame;
444 struct frame *f;
445 struct x_output *x;
447 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
449 frame = XCAR (tail);
450 if (!GC_FRAMEP (frame))
451 continue;
452 f = XFRAME (frame);
453 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
454 continue;
455 x = f->output_data.x;
456 /* Match if the window is this frame's menubar. */
457 if (x->menubar_widget
458 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
459 return f;
461 return 0;
464 /* Return the frame whose principal (outermost) window is WDESC.
465 If WDESC is some other (smaller) window, we return 0. */
467 struct frame *
468 x_top_window_to_frame (dpyinfo, wdesc)
469 struct x_display_info *dpyinfo;
470 int wdesc;
472 Lisp_Object tail, frame;
473 struct frame *f;
474 struct x_output *x;
476 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
478 frame = XCAR (tail);
479 if (!GC_FRAMEP (frame))
480 continue;
481 f = XFRAME (frame);
482 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
483 continue;
484 x = f->output_data.x;
486 if (x->widget)
488 /* This frame matches if the window is its topmost widget. */
489 if (wdesc == XtWindow (x->widget))
490 return f;
491 #if 0 /* I don't know why it did this,
492 but it seems logically wrong,
493 and it causes trouble for MapNotify events. */
494 /* Match if the window is this frame's menubar. */
495 if (x->menubar_widget
496 && wdesc == XtWindow (x->menubar_widget))
497 return f;
498 #endif
500 else if (FRAME_X_WINDOW (f) == wdesc)
501 /* Tooltip frame. */
502 return f;
504 return 0;
506 #endif /* USE_X_TOOLKIT */
510 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
511 id, which is just an int that this section returns. Bitmaps are
512 reference counted so they can be shared among frames.
514 Bitmap indices are guaranteed to be > 0, so a negative number can
515 be used to indicate no bitmap.
517 If you use x_create_bitmap_from_data, then you must keep track of
518 the bitmaps yourself. That is, creating a bitmap from the same
519 data more than once will not be caught. */
522 /* Functions to access the contents of a bitmap, given an id. */
525 x_bitmap_height (f, id)
526 FRAME_PTR f;
527 int id;
529 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
533 x_bitmap_width (f, id)
534 FRAME_PTR f;
535 int id;
537 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
541 x_bitmap_pixmap (f, id)
542 FRAME_PTR f;
543 int id;
545 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
549 /* Allocate a new bitmap record. Returns index of new record. */
551 static int
552 x_allocate_bitmap_record (f)
553 FRAME_PTR f;
555 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
556 int i;
558 if (dpyinfo->bitmaps == NULL)
560 dpyinfo->bitmaps_size = 10;
561 dpyinfo->bitmaps
562 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
563 dpyinfo->bitmaps_last = 1;
564 return 1;
567 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
568 return ++dpyinfo->bitmaps_last;
570 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
571 if (dpyinfo->bitmaps[i].refcount == 0)
572 return i + 1;
574 dpyinfo->bitmaps_size *= 2;
575 dpyinfo->bitmaps
576 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
577 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
578 return ++dpyinfo->bitmaps_last;
581 /* Add one reference to the reference count of the bitmap with id ID. */
583 void
584 x_reference_bitmap (f, id)
585 FRAME_PTR f;
586 int id;
588 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
591 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
594 x_create_bitmap_from_data (f, bits, width, height)
595 struct frame *f;
596 char *bits;
597 unsigned int width, height;
599 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
600 Pixmap bitmap;
601 int id;
603 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
604 bits, width, height);
606 if (! bitmap)
607 return -1;
609 id = x_allocate_bitmap_record (f);
610 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
611 dpyinfo->bitmaps[id - 1].file = NULL;
612 dpyinfo->bitmaps[id - 1].refcount = 1;
613 dpyinfo->bitmaps[id - 1].depth = 1;
614 dpyinfo->bitmaps[id - 1].height = height;
615 dpyinfo->bitmaps[id - 1].width = width;
617 return id;
620 /* Create bitmap from file FILE for frame F. */
623 x_create_bitmap_from_file (f, file)
624 struct frame *f;
625 Lisp_Object file;
627 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
628 unsigned int width, height;
629 Pixmap bitmap;
630 int xhot, yhot, result, id;
631 Lisp_Object found;
632 int fd;
633 char *filename;
635 /* Look for an existing bitmap with the same name. */
636 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
638 if (dpyinfo->bitmaps[id].refcount
639 && dpyinfo->bitmaps[id].file
640 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
642 ++dpyinfo->bitmaps[id].refcount;
643 return id + 1;
647 /* Search bitmap-file-path for the file, if appropriate. */
648 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
649 if (fd < 0)
650 return -1;
651 emacs_close (fd);
653 filename = (char *) XSTRING (found)->data;
655 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
656 filename, &width, &height, &bitmap, &xhot, &yhot);
657 if (result != BitmapSuccess)
658 return -1;
660 id = x_allocate_bitmap_record (f);
661 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
662 dpyinfo->bitmaps[id - 1].refcount = 1;
663 dpyinfo->bitmaps[id - 1].file
664 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
665 dpyinfo->bitmaps[id - 1].depth = 1;
666 dpyinfo->bitmaps[id - 1].height = height;
667 dpyinfo->bitmaps[id - 1].width = width;
668 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
670 return id;
673 /* Remove reference to bitmap with id number ID. */
675 void
676 x_destroy_bitmap (f, id)
677 FRAME_PTR f;
678 int id;
680 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
682 if (id > 0)
684 --dpyinfo->bitmaps[id - 1].refcount;
685 if (dpyinfo->bitmaps[id - 1].refcount == 0)
687 BLOCK_INPUT;
688 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
689 if (dpyinfo->bitmaps[id - 1].file)
691 xfree (dpyinfo->bitmaps[id - 1].file);
692 dpyinfo->bitmaps[id - 1].file = NULL;
694 UNBLOCK_INPUT;
699 /* Free all the bitmaps for the display specified by DPYINFO. */
701 static void
702 x_destroy_all_bitmaps (dpyinfo)
703 struct x_display_info *dpyinfo;
705 int i;
706 for (i = 0; i < dpyinfo->bitmaps_last; i++)
707 if (dpyinfo->bitmaps[i].refcount > 0)
709 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
710 if (dpyinfo->bitmaps[i].file)
711 xfree (dpyinfo->bitmaps[i].file);
713 dpyinfo->bitmaps_last = 0;
716 /* Connect the frame-parameter names for X frames
717 to the ways of passing the parameter values to the window system.
719 The name of a parameter, as a Lisp symbol,
720 has an `x-frame-parameter' property which is an integer in Lisp
721 that is an index in this table. */
723 struct x_frame_parm_table
725 char *name;
726 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
729 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
730 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
731 static void x_change_window_heights P_ ((Lisp_Object, int));
732 static void x_disable_image P_ ((struct frame *, struct image *));
733 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
734 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
735 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
736 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
747 Lisp_Object));
748 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
750 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
752 Lisp_Object));
753 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
760 Lisp_Object));
761 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
762 Lisp_Object));
763 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
764 Lisp_Object,
765 Lisp_Object,
766 char *, char *,
767 int));
768 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
769 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
770 Lisp_Object));
771 static void init_color_table P_ ((void));
772 static void free_color_table P_ ((void));
773 static unsigned long *colors_in_color_table P_ ((int *n));
774 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
775 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
779 static struct x_frame_parm_table x_frame_parms[] =
781 {"auto-raise", x_set_autoraise},
782 {"auto-lower", x_set_autolower},
783 {"background-color", x_set_background_color},
784 {"border-color", x_set_border_color},
785 {"border-width", x_set_border_width},
786 {"cursor-color", x_set_cursor_color},
787 {"cursor-type", x_set_cursor_type},
788 {"font", x_set_font},
789 {"foreground-color", x_set_foreground_color},
790 {"icon-name", x_set_icon_name},
791 {"icon-type", x_set_icon_type},
792 {"internal-border-width", x_set_internal_border_width},
793 {"menu-bar-lines", x_set_menu_bar_lines},
794 {"mouse-color", x_set_mouse_color},
795 {"name", x_explicitly_set_name},
796 {"scroll-bar-width", x_set_scroll_bar_width},
797 {"title", x_set_title},
798 {"unsplittable", x_set_unsplittable},
799 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
800 {"visibility", x_set_visibility},
801 {"tool-bar-lines", x_set_tool_bar_lines},
802 {"scroll-bar-foreground", x_set_scroll_bar_foreground},
803 {"scroll-bar-background", x_set_scroll_bar_background},
804 {"screen-gamma", x_set_screen_gamma},
805 {"line-spacing", x_set_line_spacing},
806 {"left-fringe", x_set_fringe_width},
807 {"right-fringe", x_set_fringe_width},
808 {"wait-for-wm", x_set_wait_for_wm}
811 /* Attach the `x-frame-parameter' properties to
812 the Lisp symbol names of parameters relevant to X. */
814 void
815 init_x_parm_symbols ()
817 int i;
819 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
820 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
821 make_number (i));
824 /* Change the parameters of frame F as specified by ALIST.
825 If a parameter is not specially recognized, do nothing special;
826 otherwise call the `x_set_...' function for that parameter.
827 Except for certain geometry properties, always call store_frame_param
828 to store the new value in the parameter alist. */
830 void
831 x_set_frame_parameters (f, alist)
832 FRAME_PTR f;
833 Lisp_Object alist;
835 Lisp_Object tail;
837 /* If both of these parameters are present, it's more efficient to
838 set them both at once. So we wait until we've looked at the
839 entire list before we set them. */
840 int width, height;
842 /* Same here. */
843 Lisp_Object left, top;
845 /* Same with these. */
846 Lisp_Object icon_left, icon_top;
848 /* Record in these vectors all the parms specified. */
849 Lisp_Object *parms;
850 Lisp_Object *values;
851 int i, p;
852 int left_no_change = 0, top_no_change = 0;
853 int icon_left_no_change = 0, icon_top_no_change = 0;
855 struct gcpro gcpro1, gcpro2;
857 i = 0;
858 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
859 i++;
861 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
862 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
864 /* Extract parm names and values into those vectors. */
866 i = 0;
867 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
869 Lisp_Object elt;
871 elt = Fcar (tail);
872 parms[i] = Fcar (elt);
873 values[i] = Fcdr (elt);
874 i++;
876 /* TAIL and ALIST are not used again below here. */
877 alist = tail = Qnil;
879 GCPRO2 (*parms, *values);
880 gcpro1.nvars = i;
881 gcpro2.nvars = i;
883 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
884 because their values appear in VALUES and strings are not valid. */
885 top = left = Qunbound;
886 icon_left = icon_top = Qunbound;
888 /* Provide default values for HEIGHT and WIDTH. */
889 if (FRAME_NEW_WIDTH (f))
890 width = FRAME_NEW_WIDTH (f);
891 else
892 width = FRAME_WIDTH (f);
894 if (FRAME_NEW_HEIGHT (f))
895 height = FRAME_NEW_HEIGHT (f);
896 else
897 height = FRAME_HEIGHT (f);
899 /* Process foreground_color and background_color before anything else.
900 They are independent of other properties, but other properties (e.g.,
901 cursor_color) are dependent upon them. */
902 /* Process default font as well, since fringe widths depends on it. */
903 for (p = 0; p < i; p++)
905 Lisp_Object prop, val;
907 prop = parms[p];
908 val = values[p];
909 if (EQ (prop, Qforeground_color)
910 || EQ (prop, Qbackground_color)
911 || EQ (prop, Qfont))
913 register Lisp_Object param_index, old_value;
915 old_value = get_frame_param (f, prop);
917 if (NILP (Fequal (val, old_value)))
919 store_frame_param (f, prop, val);
921 param_index = Fget (prop, Qx_frame_parameter);
922 if (NATNUMP (param_index)
923 && (XFASTINT (param_index)
924 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
925 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
930 /* Now process them in reverse of specified order. */
931 for (i--; i >= 0; i--)
933 Lisp_Object prop, val;
935 prop = parms[i];
936 val = values[i];
938 if (EQ (prop, Qwidth) && NUMBERP (val))
939 width = XFASTINT (val);
940 else if (EQ (prop, Qheight) && NUMBERP (val))
941 height = XFASTINT (val);
942 else if (EQ (prop, Qtop))
943 top = val;
944 else if (EQ (prop, Qleft))
945 left = val;
946 else if (EQ (prop, Qicon_top))
947 icon_top = val;
948 else if (EQ (prop, Qicon_left))
949 icon_left = val;
950 else if (EQ (prop, Qforeground_color)
951 || EQ (prop, Qbackground_color)
952 || EQ (prop, Qfont))
953 /* Processed above. */
954 continue;
955 else
957 register Lisp_Object param_index, old_value;
959 old_value = get_frame_param (f, prop);
961 store_frame_param (f, prop, val);
963 param_index = Fget (prop, Qx_frame_parameter);
964 if (NATNUMP (param_index)
965 && (XFASTINT (param_index)
966 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
967 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
971 /* Don't die if just one of these was set. */
972 if (EQ (left, Qunbound))
974 left_no_change = 1;
975 if (f->output_data.x->left_pos < 0)
976 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
977 else
978 XSETINT (left, f->output_data.x->left_pos);
980 if (EQ (top, Qunbound))
982 top_no_change = 1;
983 if (f->output_data.x->top_pos < 0)
984 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
985 else
986 XSETINT (top, f->output_data.x->top_pos);
989 /* If one of the icon positions was not set, preserve or default it. */
990 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
992 icon_left_no_change = 1;
993 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
994 if (NILP (icon_left))
995 XSETINT (icon_left, 0);
997 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
999 icon_top_no_change = 1;
1000 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
1001 if (NILP (icon_top))
1002 XSETINT (icon_top, 0);
1005 /* Don't set these parameters unless they've been explicitly
1006 specified. The window might be mapped or resized while we're in
1007 this function, and we don't want to override that unless the lisp
1008 code has asked for it.
1010 Don't set these parameters unless they actually differ from the
1011 window's current parameters; the window may not actually exist
1012 yet. */
1014 Lisp_Object frame;
1016 check_frame_size (f, &height, &width);
1018 XSETFRAME (frame, f);
1020 if (width != FRAME_WIDTH (f)
1021 || height != FRAME_HEIGHT (f)
1022 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1023 Fset_frame_size (frame, make_number (width), make_number (height));
1025 if ((!NILP (left) || !NILP (top))
1026 && ! (left_no_change && top_no_change)
1027 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1028 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1030 int leftpos = 0;
1031 int toppos = 0;
1033 /* Record the signs. */
1034 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1035 if (EQ (left, Qminus))
1036 f->output_data.x->size_hint_flags |= XNegative;
1037 else if (INTEGERP (left))
1039 leftpos = XINT (left);
1040 if (leftpos < 0)
1041 f->output_data.x->size_hint_flags |= XNegative;
1043 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1044 && CONSP (XCDR (left))
1045 && INTEGERP (XCAR (XCDR (left))))
1047 leftpos = - XINT (XCAR (XCDR (left)));
1048 f->output_data.x->size_hint_flags |= XNegative;
1050 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1051 && CONSP (XCDR (left))
1052 && INTEGERP (XCAR (XCDR (left))))
1054 leftpos = XINT (XCAR (XCDR (left)));
1057 if (EQ (top, Qminus))
1058 f->output_data.x->size_hint_flags |= YNegative;
1059 else if (INTEGERP (top))
1061 toppos = XINT (top);
1062 if (toppos < 0)
1063 f->output_data.x->size_hint_flags |= YNegative;
1065 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1066 && CONSP (XCDR (top))
1067 && INTEGERP (XCAR (XCDR (top))))
1069 toppos = - XINT (XCAR (XCDR (top)));
1070 f->output_data.x->size_hint_flags |= YNegative;
1072 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1073 && CONSP (XCDR (top))
1074 && INTEGERP (XCAR (XCDR (top))))
1076 toppos = XINT (XCAR (XCDR (top)));
1080 /* Store the numeric value of the position. */
1081 f->output_data.x->top_pos = toppos;
1082 f->output_data.x->left_pos = leftpos;
1084 f->output_data.x->win_gravity = NorthWestGravity;
1086 /* Actually set that position, and convert to absolute. */
1087 x_set_offset (f, leftpos, toppos, -1);
1090 if ((!NILP (icon_left) || !NILP (icon_top))
1091 && ! (icon_left_no_change && icon_top_no_change))
1092 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1095 UNGCPRO;
1098 /* Store the screen positions of frame F into XPTR and YPTR.
1099 These are the positions of the containing window manager window,
1100 not Emacs's own window. */
1102 void
1103 x_real_positions (f, xptr, yptr)
1104 FRAME_PTR f;
1105 int *xptr, *yptr;
1107 int win_x, win_y;
1108 Window child;
1110 /* This is pretty gross, but seems to be the easiest way out of
1111 the problem that arises when restarting window-managers. */
1113 #ifdef USE_X_TOOLKIT
1114 Window outer = (f->output_data.x->widget
1115 ? XtWindow (f->output_data.x->widget)
1116 : FRAME_X_WINDOW (f));
1117 #else
1118 Window outer = f->output_data.x->window_desc;
1119 #endif
1120 Window tmp_root_window;
1121 Window *tmp_children;
1122 unsigned int tmp_nchildren;
1124 while (1)
1126 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1127 Window outer_window;
1129 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1130 &f->output_data.x->parent_desc,
1131 &tmp_children, &tmp_nchildren);
1132 XFree ((char *) tmp_children);
1134 win_x = win_y = 0;
1136 /* Find the position of the outside upper-left corner of
1137 the inner window, with respect to the outer window. */
1138 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1139 outer_window = f->output_data.x->parent_desc;
1140 else
1141 outer_window = outer;
1143 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1145 /* From-window, to-window. */
1146 outer_window,
1147 FRAME_X_DISPLAY_INFO (f)->root_window,
1149 /* From-position, to-position. */
1150 0, 0, &win_x, &win_y,
1152 /* Child of win. */
1153 &child);
1155 /* It is possible for the window returned by the XQueryNotify
1156 to become invalid by the time we call XTranslateCoordinates.
1157 That can happen when you restart some window managers.
1158 If so, we get an error in XTranslateCoordinates.
1159 Detect that and try the whole thing over. */
1160 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1162 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1163 break;
1166 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1169 *xptr = win_x;
1170 *yptr = win_y;
1173 /* Insert a description of internally-recorded parameters of frame X
1174 into the parameter alist *ALISTPTR that is to be given to the user.
1175 Only parameters that are specific to the X window system
1176 and whose values are not correctly recorded in the frame's
1177 param_alist need to be considered here. */
1179 void
1180 x_report_frame_params (f, alistptr)
1181 struct frame *f;
1182 Lisp_Object *alistptr;
1184 char buf[16];
1185 Lisp_Object tem;
1187 /* Represent negative positions (off the top or left screen edge)
1188 in a way that Fmodify_frame_parameters will understand correctly. */
1189 XSETINT (tem, f->output_data.x->left_pos);
1190 if (f->output_data.x->left_pos >= 0)
1191 store_in_alist (alistptr, Qleft, tem);
1192 else
1193 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1195 XSETINT (tem, f->output_data.x->top_pos);
1196 if (f->output_data.x->top_pos >= 0)
1197 store_in_alist (alistptr, Qtop, tem);
1198 else
1199 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1201 store_in_alist (alistptr, Qborder_width,
1202 make_number (f->output_data.x->border_width));
1203 store_in_alist (alistptr, Qinternal_border_width,
1204 make_number (f->output_data.x->internal_border_width));
1205 store_in_alist (alistptr, Qleft_fringe,
1206 make_number (f->output_data.x->left_fringe_width));
1207 store_in_alist (alistptr, Qright_fringe,
1208 make_number (f->output_data.x->right_fringe_width));
1209 store_in_alist (alistptr, Qscroll_bar_width,
1210 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1211 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
1212 : 0));
1213 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1214 store_in_alist (alistptr, Qwindow_id,
1215 build_string (buf));
1216 #ifdef USE_X_TOOLKIT
1217 /* Tooltip frame may not have this widget. */
1218 if (f->output_data.x->widget)
1219 #endif
1220 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1221 store_in_alist (alistptr, Qouter_window_id,
1222 build_string (buf));
1223 store_in_alist (alistptr, Qicon_name, f->icon_name);
1224 FRAME_SAMPLE_VISIBILITY (f);
1225 store_in_alist (alistptr, Qvisibility,
1226 (FRAME_VISIBLE_P (f) ? Qt
1227 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1228 store_in_alist (alistptr, Qdisplay,
1229 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1231 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1232 tem = Qnil;
1233 else
1234 XSETFASTINT (tem, f->output_data.x->parent_desc);
1235 store_in_alist (alistptr, Qparent_id, tem);
1240 /* Gamma-correct COLOR on frame F. */
1242 void
1243 gamma_correct (f, color)
1244 struct frame *f;
1245 XColor *color;
1247 if (f->gamma)
1249 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1250 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1251 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1256 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1257 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1258 allocate the color. Value is zero if COLOR_NAME is invalid, or
1259 no color could be allocated. */
1262 x_defined_color (f, color_name, color, alloc_p)
1263 struct frame *f;
1264 char *color_name;
1265 XColor *color;
1266 int alloc_p;
1268 int success_p;
1269 Display *dpy = FRAME_X_DISPLAY (f);
1270 Colormap cmap = FRAME_X_COLORMAP (f);
1272 BLOCK_INPUT;
1273 success_p = XParseColor (dpy, cmap, color_name, color);
1274 if (success_p && alloc_p)
1275 success_p = x_alloc_nearest_color (f, cmap, color);
1276 UNBLOCK_INPUT;
1278 return success_p;
1282 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1283 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1284 Signal an error if color can't be allocated. */
1287 x_decode_color (f, color_name, mono_color)
1288 FRAME_PTR f;
1289 Lisp_Object color_name;
1290 int mono_color;
1292 XColor cdef;
1294 CHECK_STRING (color_name);
1296 #if 0 /* Don't do this. It's wrong when we're not using the default
1297 colormap, it makes freeing difficult, and it's probably not
1298 an important optimization. */
1299 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1300 return BLACK_PIX_DEFAULT (f);
1301 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1302 return WHITE_PIX_DEFAULT (f);
1303 #endif
1305 /* Return MONO_COLOR for monochrome frames. */
1306 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1307 return mono_color;
1309 /* x_defined_color is responsible for coping with failures
1310 by looking for a near-miss. */
1311 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1312 return cdef.pixel;
1314 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1315 Fcons (color_name, Qnil)));
1316 return 0;
1321 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1322 the previous value of that parameter, NEW_VALUE is the new value. */
1324 static void
1325 x_set_line_spacing (f, new_value, old_value)
1326 struct frame *f;
1327 Lisp_Object new_value, old_value;
1329 if (NILP (new_value))
1330 f->extra_line_spacing = 0;
1331 else if (NATNUMP (new_value))
1332 f->extra_line_spacing = XFASTINT (new_value);
1333 else
1334 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1335 Fcons (new_value, Qnil)));
1336 if (FRAME_VISIBLE_P (f))
1337 redraw_frame (f);
1341 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1342 the previous value of that parameter, NEW_VALUE is the new value.
1343 See also the comment of wait_for_wm in struct x_output. */
1345 static void
1346 x_set_wait_for_wm (f, new_value, old_value)
1347 struct frame *f;
1348 Lisp_Object new_value, old_value;
1350 f->output_data.x->wait_for_wm = !NILP (new_value);
1354 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1355 the previous value of that parameter, NEW_VALUE is the new
1356 value. */
1358 static void
1359 x_set_screen_gamma (f, new_value, old_value)
1360 struct frame *f;
1361 Lisp_Object new_value, old_value;
1363 if (NILP (new_value))
1364 f->gamma = 0;
1365 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1366 /* The value 0.4545 is the normal viewing gamma. */
1367 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1368 else
1369 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1370 Fcons (new_value, Qnil)));
1372 clear_face_cache (0);
1376 /* Functions called only from `x_set_frame_param'
1377 to set individual parameters.
1379 If FRAME_X_WINDOW (f) is 0,
1380 the frame is being created and its X-window does not exist yet.
1381 In that case, just record the parameter's new value
1382 in the standard place; do not attempt to change the window. */
1384 void
1385 x_set_foreground_color (f, arg, oldval)
1386 struct frame *f;
1387 Lisp_Object arg, oldval;
1389 struct x_output *x = f->output_data.x;
1390 unsigned long fg, old_fg;
1392 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1393 old_fg = x->foreground_pixel;
1394 x->foreground_pixel = fg;
1396 if (FRAME_X_WINDOW (f) != 0)
1398 Display *dpy = FRAME_X_DISPLAY (f);
1400 BLOCK_INPUT;
1401 XSetForeground (dpy, x->normal_gc, fg);
1402 XSetBackground (dpy, x->reverse_gc, fg);
1404 if (x->cursor_pixel == old_fg)
1406 unload_color (f, x->cursor_pixel);
1407 x->cursor_pixel = x_copy_color (f, fg);
1408 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1411 UNBLOCK_INPUT;
1413 update_face_from_frame_parameter (f, Qforeground_color, arg);
1415 if (FRAME_VISIBLE_P (f))
1416 redraw_frame (f);
1419 unload_color (f, old_fg);
1422 void
1423 x_set_background_color (f, arg, oldval)
1424 struct frame *f;
1425 Lisp_Object arg, oldval;
1427 struct x_output *x = f->output_data.x;
1428 unsigned long bg;
1430 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1431 unload_color (f, x->background_pixel);
1432 x->background_pixel = bg;
1434 if (FRAME_X_WINDOW (f) != 0)
1436 Display *dpy = FRAME_X_DISPLAY (f);
1438 BLOCK_INPUT;
1439 XSetBackground (dpy, x->normal_gc, bg);
1440 XSetForeground (dpy, x->reverse_gc, bg);
1441 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1442 XSetForeground (dpy, x->cursor_gc, bg);
1444 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1445 toolkit scroll bars. */
1447 Lisp_Object bar;
1448 for (bar = FRAME_SCROLL_BARS (f);
1449 !NILP (bar);
1450 bar = XSCROLL_BAR (bar)->next)
1452 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1453 XSetWindowBackground (dpy, window, bg);
1456 #endif /* USE_TOOLKIT_SCROLL_BARS */
1458 UNBLOCK_INPUT;
1459 update_face_from_frame_parameter (f, Qbackground_color, arg);
1461 if (FRAME_VISIBLE_P (f))
1462 redraw_frame (f);
1466 void
1467 x_set_mouse_color (f, arg, oldval)
1468 struct frame *f;
1469 Lisp_Object arg, oldval;
1471 struct x_output *x = f->output_data.x;
1472 Display *dpy = FRAME_X_DISPLAY (f);
1473 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1474 Cursor hourglass_cursor, horizontal_drag_cursor;
1475 int count;
1476 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1477 unsigned long mask_color = x->background_pixel;
1479 /* Don't let pointers be invisible. */
1480 if (mask_color == pixel)
1482 x_free_colors (f, &pixel, 1);
1483 pixel = x_copy_color (f, x->foreground_pixel);
1486 unload_color (f, x->mouse_pixel);
1487 x->mouse_pixel = pixel;
1489 BLOCK_INPUT;
1491 /* It's not okay to crash if the user selects a screwy cursor. */
1492 count = x_catch_errors (dpy);
1494 if (!NILP (Vx_pointer_shape))
1496 CHECK_NUMBER (Vx_pointer_shape);
1497 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1499 else
1500 cursor = XCreateFontCursor (dpy, XC_xterm);
1501 x_check_errors (dpy, "bad text pointer cursor: %s");
1503 if (!NILP (Vx_nontext_pointer_shape))
1505 CHECK_NUMBER (Vx_nontext_pointer_shape);
1506 nontext_cursor
1507 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1509 else
1510 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1511 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1513 if (!NILP (Vx_hourglass_pointer_shape))
1515 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1516 hourglass_cursor
1517 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1519 else
1520 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1521 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1523 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1524 if (!NILP (Vx_mode_pointer_shape))
1526 CHECK_NUMBER (Vx_mode_pointer_shape);
1527 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1529 else
1530 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1531 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1533 if (!NILP (Vx_sensitive_text_pointer_shape))
1535 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1536 cross_cursor
1537 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1539 else
1540 cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
1542 if (!NILP (Vx_window_horizontal_drag_shape))
1544 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1545 horizontal_drag_cursor
1546 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1548 else
1549 horizontal_drag_cursor
1550 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1552 /* Check and report errors with the above calls. */
1553 x_check_errors (dpy, "can't set cursor shape: %s");
1554 x_uncatch_errors (dpy, count);
1557 XColor fore_color, back_color;
1559 fore_color.pixel = x->mouse_pixel;
1560 x_query_color (f, &fore_color);
1561 back_color.pixel = mask_color;
1562 x_query_color (f, &back_color);
1564 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1565 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1566 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1567 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1568 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1569 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1572 if (FRAME_X_WINDOW (f) != 0)
1573 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1575 if (cursor != x->text_cursor
1576 && x->text_cursor != 0)
1577 XFreeCursor (dpy, x->text_cursor);
1578 x->text_cursor = cursor;
1580 if (nontext_cursor != x->nontext_cursor
1581 && x->nontext_cursor != 0)
1582 XFreeCursor (dpy, x->nontext_cursor);
1583 x->nontext_cursor = nontext_cursor;
1585 if (hourglass_cursor != x->hourglass_cursor
1586 && x->hourglass_cursor != 0)
1587 XFreeCursor (dpy, x->hourglass_cursor);
1588 x->hourglass_cursor = hourglass_cursor;
1590 if (mode_cursor != x->modeline_cursor
1591 && x->modeline_cursor != 0)
1592 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1593 x->modeline_cursor = mode_cursor;
1595 if (cross_cursor != x->cross_cursor
1596 && x->cross_cursor != 0)
1597 XFreeCursor (dpy, x->cross_cursor);
1598 x->cross_cursor = cross_cursor;
1600 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1601 && x->horizontal_drag_cursor != 0)
1602 XFreeCursor (dpy, x->horizontal_drag_cursor);
1603 x->horizontal_drag_cursor = horizontal_drag_cursor;
1605 XFlush (dpy);
1606 UNBLOCK_INPUT;
1608 update_face_from_frame_parameter (f, Qmouse_color, arg);
1611 void
1612 x_set_cursor_color (f, arg, oldval)
1613 struct frame *f;
1614 Lisp_Object arg, oldval;
1616 unsigned long fore_pixel, pixel;
1617 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1618 struct x_output *x = f->output_data.x;
1620 if (!NILP (Vx_cursor_fore_pixel))
1622 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1623 WHITE_PIX_DEFAULT (f));
1624 fore_pixel_allocated_p = 1;
1626 else
1627 fore_pixel = x->background_pixel;
1629 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1630 pixel_allocated_p = 1;
1632 /* Make sure that the cursor color differs from the background color. */
1633 if (pixel == x->background_pixel)
1635 if (pixel_allocated_p)
1637 x_free_colors (f, &pixel, 1);
1638 pixel_allocated_p = 0;
1641 pixel = x->mouse_pixel;
1642 if (pixel == fore_pixel)
1644 if (fore_pixel_allocated_p)
1646 x_free_colors (f, &fore_pixel, 1);
1647 fore_pixel_allocated_p = 0;
1649 fore_pixel = x->background_pixel;
1653 unload_color (f, x->cursor_foreground_pixel);
1654 if (!fore_pixel_allocated_p)
1655 fore_pixel = x_copy_color (f, fore_pixel);
1656 x->cursor_foreground_pixel = fore_pixel;
1658 unload_color (f, x->cursor_pixel);
1659 if (!pixel_allocated_p)
1660 pixel = x_copy_color (f, pixel);
1661 x->cursor_pixel = pixel;
1663 if (FRAME_X_WINDOW (f) != 0)
1665 BLOCK_INPUT;
1666 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1667 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1668 UNBLOCK_INPUT;
1670 if (FRAME_VISIBLE_P (f))
1672 x_update_cursor (f, 0);
1673 x_update_cursor (f, 1);
1677 update_face_from_frame_parameter (f, Qcursor_color, arg);
1680 /* Set the border-color of frame F to value described by ARG.
1681 ARG can be a string naming a color.
1682 The border-color is used for the border that is drawn by the X server.
1683 Note that this does not fully take effect if done before
1684 F has an x-window; it must be redone when the window is created.
1686 Note: this is done in two routines because of the way X10 works.
1688 Note: under X11, this is normally the province of the window manager,
1689 and so emacs' border colors may be overridden. */
1691 void
1692 x_set_border_color (f, arg, oldval)
1693 struct frame *f;
1694 Lisp_Object arg, oldval;
1696 int pix;
1698 CHECK_STRING (arg);
1699 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1700 x_set_border_pixel (f, pix);
1701 update_face_from_frame_parameter (f, Qborder_color, arg);
1704 /* Set the border-color of frame F to pixel value PIX.
1705 Note that this does not fully take effect if done before
1706 F has an x-window. */
1708 void
1709 x_set_border_pixel (f, pix)
1710 struct frame *f;
1711 int pix;
1713 unload_color (f, f->output_data.x->border_pixel);
1714 f->output_data.x->border_pixel = pix;
1716 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1718 BLOCK_INPUT;
1719 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1720 (unsigned long)pix);
1721 UNBLOCK_INPUT;
1723 if (FRAME_VISIBLE_P (f))
1724 redraw_frame (f);
1729 /* Value is the internal representation of the specified cursor type
1730 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1731 of the bar cursor. */
1733 enum text_cursor_kinds
1734 x_specified_cursor_type (arg, width)
1735 Lisp_Object arg;
1736 int *width;
1738 enum text_cursor_kinds type;
1740 if (EQ (arg, Qbar))
1742 type = BAR_CURSOR;
1743 *width = 2;
1745 else if (CONSP (arg)
1746 && EQ (XCAR (arg), Qbar)
1747 && INTEGERP (XCDR (arg))
1748 && XINT (XCDR (arg)) >= 0)
1750 type = BAR_CURSOR;
1751 *width = XINT (XCDR (arg));
1753 else if (NILP (arg))
1754 type = NO_CURSOR;
1755 else
1756 /* Treat anything unknown as "box cursor".
1757 It was bad to signal an error; people have trouble fixing
1758 .Xdefaults with Emacs, when it has something bad in it. */
1759 type = FILLED_BOX_CURSOR;
1761 return type;
1764 void
1765 x_set_cursor_type (f, arg, oldval)
1766 FRAME_PTR f;
1767 Lisp_Object arg, oldval;
1769 int width;
1771 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1772 f->output_data.x->cursor_width = width;
1774 /* Make sure the cursor gets redrawn. This is overkill, but how
1775 often do people change cursor types? */
1776 update_mode_lines++;
1779 void
1780 x_set_icon_type (f, arg, oldval)
1781 struct frame *f;
1782 Lisp_Object arg, oldval;
1784 int result;
1786 if (STRINGP (arg))
1788 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1789 return;
1791 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1792 return;
1794 BLOCK_INPUT;
1795 if (NILP (arg))
1796 result = x_text_icon (f,
1797 (char *) XSTRING ((!NILP (f->icon_name)
1798 ? f->icon_name
1799 : f->name))->data);
1800 else
1801 result = x_bitmap_icon (f, arg);
1803 if (result)
1805 UNBLOCK_INPUT;
1806 error ("No icon window available");
1809 XFlush (FRAME_X_DISPLAY (f));
1810 UNBLOCK_INPUT;
1813 /* Return non-nil if frame F wants a bitmap icon. */
1815 Lisp_Object
1816 x_icon_type (f)
1817 FRAME_PTR f;
1819 Lisp_Object tem;
1821 tem = assq_no_quit (Qicon_type, f->param_alist);
1822 if (CONSP (tem))
1823 return XCDR (tem);
1824 else
1825 return Qnil;
1828 void
1829 x_set_icon_name (f, arg, oldval)
1830 struct frame *f;
1831 Lisp_Object arg, oldval;
1833 int result;
1835 if (STRINGP (arg))
1837 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1838 return;
1840 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1841 return;
1843 f->icon_name = arg;
1845 if (f->output_data.x->icon_bitmap != 0)
1846 return;
1848 BLOCK_INPUT;
1850 result = x_text_icon (f,
1851 (char *) XSTRING ((!NILP (f->icon_name)
1852 ? f->icon_name
1853 : !NILP (f->title)
1854 ? f->title
1855 : f->name))->data);
1857 if (result)
1859 UNBLOCK_INPUT;
1860 error ("No icon window available");
1863 XFlush (FRAME_X_DISPLAY (f));
1864 UNBLOCK_INPUT;
1867 void
1868 x_set_font (f, arg, oldval)
1869 struct frame *f;
1870 Lisp_Object arg, oldval;
1872 Lisp_Object result;
1873 Lisp_Object fontset_name;
1874 Lisp_Object frame;
1875 int old_fontset = f->output_data.x->fontset;
1877 CHECK_STRING (arg);
1879 fontset_name = Fquery_fontset (arg, Qnil);
1881 BLOCK_INPUT;
1882 result = (STRINGP (fontset_name)
1883 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1884 : x_new_font (f, XSTRING (arg)->data));
1885 UNBLOCK_INPUT;
1887 if (EQ (result, Qnil))
1888 error ("Font `%s' is not defined", XSTRING (arg)->data);
1889 else if (EQ (result, Qt))
1890 error ("The characters of the given font have varying widths");
1891 else if (STRINGP (result))
1893 if (STRINGP (fontset_name))
1895 /* Fontset names are built from ASCII font names, so the
1896 names may be equal despite there was a change. */
1897 if (old_fontset == f->output_data.x->fontset)
1898 return;
1900 else if (!NILP (Fequal (result, oldval)))
1901 return;
1903 store_frame_param (f, Qfont, result);
1904 recompute_basic_faces (f);
1906 else
1907 abort ();
1909 do_pending_window_change (0);
1911 /* Don't call `face-set-after-frame-default' when faces haven't been
1912 initialized yet. This is the case when called from
1913 Fx_create_frame. In that case, the X widget or window doesn't
1914 exist either, and we can end up in x_report_frame_params with a
1915 null widget which gives a segfault. */
1916 if (FRAME_FACE_CACHE (f))
1918 XSETFRAME (frame, f);
1919 call1 (Qface_set_after_frame_default, frame);
1923 static void
1924 x_set_fringe_width (f, new_value, old_value)
1925 struct frame *f;
1926 Lisp_Object new_value, old_value;
1928 x_compute_fringe_widths (f, 1);
1931 void
1932 x_set_border_width (f, arg, oldval)
1933 struct frame *f;
1934 Lisp_Object arg, oldval;
1936 CHECK_NUMBER (arg);
1938 if (XINT (arg) == f->output_data.x->border_width)
1939 return;
1941 if (FRAME_X_WINDOW (f) != 0)
1942 error ("Cannot change the border width of a window");
1944 f->output_data.x->border_width = XINT (arg);
1947 void
1948 x_set_internal_border_width (f, arg, oldval)
1949 struct frame *f;
1950 Lisp_Object arg, oldval;
1952 int old = f->output_data.x->internal_border_width;
1954 CHECK_NUMBER (arg);
1955 f->output_data.x->internal_border_width = XINT (arg);
1956 if (f->output_data.x->internal_border_width < 0)
1957 f->output_data.x->internal_border_width = 0;
1959 #ifdef USE_X_TOOLKIT
1960 if (f->output_data.x->edit_widget)
1961 widget_store_internal_border (f->output_data.x->edit_widget);
1962 #endif
1964 if (f->output_data.x->internal_border_width == old)
1965 return;
1967 if (FRAME_X_WINDOW (f) != 0)
1969 x_set_window_size (f, 0, f->width, f->height);
1970 SET_FRAME_GARBAGED (f);
1971 do_pending_window_change (0);
1973 else
1974 SET_FRAME_GARBAGED (f);
1977 void
1978 x_set_visibility (f, value, oldval)
1979 struct frame *f;
1980 Lisp_Object value, oldval;
1982 Lisp_Object frame;
1983 XSETFRAME (frame, f);
1985 if (NILP (value))
1986 Fmake_frame_invisible (frame, Qt);
1987 else if (EQ (value, Qicon))
1988 Ficonify_frame (frame);
1989 else
1990 Fmake_frame_visible (frame);
1994 /* Change window heights in windows rooted in WINDOW by N lines. */
1996 static void
1997 x_change_window_heights (window, n)
1998 Lisp_Object window;
1999 int n;
2001 struct window *w = XWINDOW (window);
2003 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2004 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2006 if (INTEGERP (w->orig_top))
2007 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2008 if (INTEGERP (w->orig_height))
2009 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2011 /* Handle just the top child in a vertical split. */
2012 if (!NILP (w->vchild))
2013 x_change_window_heights (w->vchild, n);
2015 /* Adjust all children in a horizontal split. */
2016 for (window = w->hchild; !NILP (window); window = w->next)
2018 w = XWINDOW (window);
2019 x_change_window_heights (window, n);
2023 void
2024 x_set_menu_bar_lines (f, value, oldval)
2025 struct frame *f;
2026 Lisp_Object value, oldval;
2028 int nlines;
2029 #ifndef USE_X_TOOLKIT
2030 int olines = FRAME_MENU_BAR_LINES (f);
2031 #endif
2033 /* Right now, menu bars don't work properly in minibuf-only frames;
2034 most of the commands try to apply themselves to the minibuffer
2035 frame itself, and get an error because you can't switch buffers
2036 in or split the minibuffer window. */
2037 if (FRAME_MINIBUF_ONLY_P (f))
2038 return;
2040 if (INTEGERP (value))
2041 nlines = XINT (value);
2042 else
2043 nlines = 0;
2045 /* Make sure we redisplay all windows in this frame. */
2046 windows_or_buffers_changed++;
2048 #ifdef USE_X_TOOLKIT
2049 FRAME_MENU_BAR_LINES (f) = 0;
2050 if (nlines)
2052 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2053 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
2054 /* Make sure next redisplay shows the menu bar. */
2055 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2057 else
2059 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2060 free_frame_menubar (f);
2061 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2062 if (FRAME_X_P (f))
2063 f->output_data.x->menubar_widget = 0;
2065 #else /* not USE_X_TOOLKIT */
2066 FRAME_MENU_BAR_LINES (f) = nlines;
2067 x_change_window_heights (f->root_window, nlines - olines);
2068 #endif /* not USE_X_TOOLKIT */
2069 adjust_glyphs (f);
2073 /* Set the number of lines used for the tool bar of frame F to VALUE.
2074 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2075 is the old number of tool bar lines. This function changes the
2076 height of all windows on frame F to match the new tool bar height.
2077 The frame's height doesn't change. */
2079 void
2080 x_set_tool_bar_lines (f, value, oldval)
2081 struct frame *f;
2082 Lisp_Object value, oldval;
2084 int delta, nlines, root_height;
2085 Lisp_Object root_window;
2087 /* Treat tool bars like menu bars. */
2088 if (FRAME_MINIBUF_ONLY_P (f))
2089 return;
2091 /* Use VALUE only if an integer >= 0. */
2092 if (INTEGERP (value) && XINT (value) >= 0)
2093 nlines = XFASTINT (value);
2094 else
2095 nlines = 0;
2097 /* Make sure we redisplay all windows in this frame. */
2098 ++windows_or_buffers_changed;
2100 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2102 /* Don't resize the tool-bar to more than we have room for. */
2103 root_window = FRAME_ROOT_WINDOW (f);
2104 root_height = XINT (XWINDOW (root_window)->height);
2105 if (root_height - delta < 1)
2107 delta = root_height - 1;
2108 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2111 FRAME_TOOL_BAR_LINES (f) = nlines;
2112 x_change_window_heights (root_window, delta);
2113 adjust_glyphs (f);
2115 /* We also have to make sure that the internal border at the top of
2116 the frame, below the menu bar or tool bar, is redrawn when the
2117 tool bar disappears. This is so because the internal border is
2118 below the tool bar if one is displayed, but is below the menu bar
2119 if there isn't a tool bar. The tool bar draws into the area
2120 below the menu bar. */
2121 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2123 updating_frame = f;
2124 clear_frame ();
2125 clear_current_matrices (f);
2126 updating_frame = NULL;
2129 /* If the tool bar gets smaller, the internal border below it
2130 has to be cleared. It was formerly part of the display
2131 of the larger tool bar, and updating windows won't clear it. */
2132 if (delta < 0)
2134 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2135 int width = PIXEL_WIDTH (f);
2136 int y = nlines * CANON_Y_UNIT (f);
2138 BLOCK_INPUT;
2139 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2140 0, y, width, height, False);
2141 UNBLOCK_INPUT;
2143 if (WINDOWP (f->tool_bar_window))
2144 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2149 /* Set the foreground color for scroll bars on frame F to VALUE.
2150 VALUE should be a string, a color name. If it isn't a string or
2151 isn't a valid color name, do nothing. OLDVAL is the old value of
2152 the frame parameter. */
2154 void
2155 x_set_scroll_bar_foreground (f, value, oldval)
2156 struct frame *f;
2157 Lisp_Object value, oldval;
2159 unsigned long pixel;
2161 if (STRINGP (value))
2162 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2163 else
2164 pixel = -1;
2166 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2167 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2169 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2170 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2172 /* Remove all scroll bars because they have wrong colors. */
2173 if (condemn_scroll_bars_hook)
2174 (*condemn_scroll_bars_hook) (f);
2175 if (judge_scroll_bars_hook)
2176 (*judge_scroll_bars_hook) (f);
2178 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2179 redraw_frame (f);
2184 /* Set the background color for scroll bars on frame F to VALUE VALUE
2185 should be a string, a color name. If it isn't a string or isn't a
2186 valid color name, do nothing. OLDVAL is the old value of the frame
2187 parameter. */
2189 void
2190 x_set_scroll_bar_background (f, value, oldval)
2191 struct frame *f;
2192 Lisp_Object value, oldval;
2194 unsigned long pixel;
2196 if (STRINGP (value))
2197 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2198 else
2199 pixel = -1;
2201 if (f->output_data.x->scroll_bar_background_pixel != -1)
2202 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2204 #ifdef USE_TOOLKIT_SCROLL_BARS
2205 /* Scrollbar shadow colors. */
2206 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
2208 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
2209 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2211 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
2213 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
2214 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2216 #endif /* USE_TOOLKIT_SCROLL_BARS */
2218 f->output_data.x->scroll_bar_background_pixel = pixel;
2219 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2221 /* Remove all scroll bars because they have wrong colors. */
2222 if (condemn_scroll_bars_hook)
2223 (*condemn_scroll_bars_hook) (f);
2224 if (judge_scroll_bars_hook)
2225 (*judge_scroll_bars_hook) (f);
2227 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2228 redraw_frame (f);
2233 /* Encode Lisp string STRING as a text in a format appropriate for
2234 XICCC (X Inter Client Communication Conventions).
2236 If STRING contains only ASCII characters, do no conversion and
2237 return the string data of STRING. Otherwise, encode the text by
2238 CODING_SYSTEM, and return a newly allocated memory area which
2239 should be freed by `xfree' by a caller.
2241 Store the byte length of resulting text in *TEXT_BYTES.
2243 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2244 which means that the `encoding' of the result can be `STRING'.
2245 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2246 the result should be `COMPOUND_TEXT'. */
2248 unsigned char *
2249 x_encode_text (string, coding_system, text_bytes, stringp)
2250 Lisp_Object string, coding_system;
2251 int *text_bytes, *stringp;
2253 unsigned char *str = XSTRING (string)->data;
2254 int chars = XSTRING (string)->size;
2255 int bytes = STRING_BYTES (XSTRING (string));
2256 int charset_info;
2257 int bufsize;
2258 unsigned char *buf;
2259 struct coding_system coding;
2261 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2262 if (charset_info == 0)
2264 /* No multibyte character in OBJ. We need not encode it. */
2265 *text_bytes = bytes;
2266 *stringp = 1;
2267 return str;
2270 setup_coding_system (coding_system, &coding);
2271 coding.src_multibyte = 1;
2272 coding.dst_multibyte = 0;
2273 coding.mode |= CODING_MODE_LAST_BLOCK;
2274 if (coding.type == coding_type_iso2022)
2275 coding.flags |= CODING_FLAG_ISO_SAFE;
2276 /* We suppress producing escape sequences for composition. */
2277 coding.composing = COMPOSITION_DISABLED;
2278 bufsize = encoding_buffer_size (&coding, bytes);
2279 buf = (unsigned char *) xmalloc (bufsize);
2280 encode_coding (&coding, str, buf, bytes, bufsize);
2281 *text_bytes = coding.produced;
2282 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2283 return buf;
2287 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2288 x_id_name.
2290 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2291 name; if NAME is a string, set F's name to NAME and set
2292 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2294 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2295 suggesting a new name, which lisp code should override; if
2296 F->explicit_name is set, ignore the new name; otherwise, set it. */
2298 void
2299 x_set_name (f, name, explicit)
2300 struct frame *f;
2301 Lisp_Object name;
2302 int explicit;
2304 /* Make sure that requests from lisp code override requests from
2305 Emacs redisplay code. */
2306 if (explicit)
2308 /* If we're switching from explicit to implicit, we had better
2309 update the mode lines and thereby update the title. */
2310 if (f->explicit_name && NILP (name))
2311 update_mode_lines = 1;
2313 f->explicit_name = ! NILP (name);
2315 else if (f->explicit_name)
2316 return;
2318 /* If NAME is nil, set the name to the x_id_name. */
2319 if (NILP (name))
2321 /* Check for no change needed in this very common case
2322 before we do any consing. */
2323 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2324 XSTRING (f->name)->data))
2325 return;
2326 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2328 else
2329 CHECK_STRING (name);
2331 /* Don't change the name if it's already NAME. */
2332 if (! NILP (Fstring_equal (name, f->name)))
2333 return;
2335 f->name = name;
2337 /* For setting the frame title, the title parameter should override
2338 the name parameter. */
2339 if (! NILP (f->title))
2340 name = f->title;
2342 if (FRAME_X_WINDOW (f))
2344 BLOCK_INPUT;
2345 #ifdef HAVE_X11R4
2347 XTextProperty text, icon;
2348 int bytes, stringp;
2349 Lisp_Object coding_system;
2351 coding_system = Vlocale_coding_system;
2352 if (NILP (coding_system))
2353 coding_system = Qcompound_text;
2354 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2355 text.encoding = (stringp ? XA_STRING
2356 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2357 text.format = 8;
2358 text.nitems = bytes;
2360 if (NILP (f->icon_name))
2362 icon = text;
2364 else
2366 icon.value = x_encode_text (f->icon_name, coding_system,
2367 &bytes, &stringp);
2368 icon.encoding = (stringp ? XA_STRING
2369 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2370 icon.format = 8;
2371 icon.nitems = bytes;
2373 #ifdef USE_X_TOOLKIT
2374 XSetWMName (FRAME_X_DISPLAY (f),
2375 XtWindow (f->output_data.x->widget), &text);
2376 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2377 &icon);
2378 #else /* not USE_X_TOOLKIT */
2379 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2380 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2381 #endif /* not USE_X_TOOLKIT */
2382 if (!NILP (f->icon_name)
2383 && icon.value != XSTRING (f->icon_name)->data)
2384 xfree (icon.value);
2385 if (text.value != XSTRING (name)->data)
2386 xfree (text.value);
2388 #else /* not HAVE_X11R4 */
2389 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2390 XSTRING (name)->data);
2391 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2392 XSTRING (name)->data);
2393 #endif /* not HAVE_X11R4 */
2394 UNBLOCK_INPUT;
2398 /* This function should be called when the user's lisp code has
2399 specified a name for the frame; the name will override any set by the
2400 redisplay code. */
2401 void
2402 x_explicitly_set_name (f, arg, oldval)
2403 FRAME_PTR f;
2404 Lisp_Object arg, oldval;
2406 x_set_name (f, arg, 1);
2409 /* This function should be called by Emacs redisplay code to set the
2410 name; names set this way will never override names set by the user's
2411 lisp code. */
2412 void
2413 x_implicitly_set_name (f, arg, oldval)
2414 FRAME_PTR f;
2415 Lisp_Object arg, oldval;
2417 x_set_name (f, arg, 0);
2420 /* Change the title of frame F to NAME.
2421 If NAME is nil, use the frame name as the title.
2423 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2424 name; if NAME is a string, set F's name to NAME and set
2425 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2427 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2428 suggesting a new name, which lisp code should override; if
2429 F->explicit_name is set, ignore the new name; otherwise, set it. */
2431 void
2432 x_set_title (f, name, old_name)
2433 struct frame *f;
2434 Lisp_Object name, old_name;
2436 /* Don't change the title if it's already NAME. */
2437 if (EQ (name, f->title))
2438 return;
2440 update_mode_lines = 1;
2442 f->title = name;
2444 if (NILP (name))
2445 name = f->name;
2446 else
2447 CHECK_STRING (name);
2449 if (FRAME_X_WINDOW (f))
2451 BLOCK_INPUT;
2452 #ifdef HAVE_X11R4
2454 XTextProperty text, icon;
2455 int bytes, stringp;
2456 Lisp_Object coding_system;
2458 coding_system = Vlocale_coding_system;
2459 if (NILP (coding_system))
2460 coding_system = Qcompound_text;
2461 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2462 text.encoding = (stringp ? XA_STRING
2463 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2464 text.format = 8;
2465 text.nitems = bytes;
2467 if (NILP (f->icon_name))
2469 icon = text;
2471 else
2473 icon.value = x_encode_text (f->icon_name, coding_system,
2474 &bytes, &stringp);
2475 icon.encoding = (stringp ? XA_STRING
2476 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2477 icon.format = 8;
2478 icon.nitems = bytes;
2480 #ifdef USE_X_TOOLKIT
2481 XSetWMName (FRAME_X_DISPLAY (f),
2482 XtWindow (f->output_data.x->widget), &text);
2483 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2484 &icon);
2485 #else /* not USE_X_TOOLKIT */
2486 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2487 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2488 #endif /* not USE_X_TOOLKIT */
2489 if (!NILP (f->icon_name)
2490 && icon.value != XSTRING (f->icon_name)->data)
2491 xfree (icon.value);
2492 if (text.value != XSTRING (name)->data)
2493 xfree (text.value);
2495 #else /* not HAVE_X11R4 */
2496 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2497 XSTRING (name)->data);
2498 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2499 XSTRING (name)->data);
2500 #endif /* not HAVE_X11R4 */
2501 UNBLOCK_INPUT;
2505 void
2506 x_set_autoraise (f, arg, oldval)
2507 struct frame *f;
2508 Lisp_Object arg, oldval;
2510 f->auto_raise = !EQ (Qnil, arg);
2513 void
2514 x_set_autolower (f, arg, oldval)
2515 struct frame *f;
2516 Lisp_Object arg, oldval;
2518 f->auto_lower = !EQ (Qnil, arg);
2521 void
2522 x_set_unsplittable (f, arg, oldval)
2523 struct frame *f;
2524 Lisp_Object arg, oldval;
2526 f->no_split = !NILP (arg);
2529 void
2530 x_set_vertical_scroll_bars (f, arg, oldval)
2531 struct frame *f;
2532 Lisp_Object arg, oldval;
2534 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2535 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2536 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2537 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2539 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2540 = (NILP (arg)
2541 ? vertical_scroll_bar_none
2542 : EQ (Qright, arg)
2543 ? vertical_scroll_bar_right
2544 : vertical_scroll_bar_left);
2546 /* We set this parameter before creating the X window for the
2547 frame, so we can get the geometry right from the start.
2548 However, if the window hasn't been created yet, we shouldn't
2549 call x_set_window_size. */
2550 if (FRAME_X_WINDOW (f))
2551 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2552 do_pending_window_change (0);
2556 void
2557 x_set_scroll_bar_width (f, arg, oldval)
2558 struct frame *f;
2559 Lisp_Object arg, oldval;
2561 int wid = FONT_WIDTH (f->output_data.x->font);
2563 if (NILP (arg))
2565 #ifdef USE_TOOLKIT_SCROLL_BARS
2566 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2567 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2568 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2569 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2570 #else
2571 /* Make the actual width at least 14 pixels and a multiple of a
2572 character width. */
2573 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2575 /* Use all of that space (aside from required margins) for the
2576 scroll bar. */
2577 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2578 #endif
2580 if (FRAME_X_WINDOW (f))
2581 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2582 do_pending_window_change (0);
2584 else if (INTEGERP (arg) && XINT (arg) > 0
2585 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2587 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2588 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2590 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2591 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2592 if (FRAME_X_WINDOW (f))
2593 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2596 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2597 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2598 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2603 /* Subroutines of creating an X frame. */
2605 /* Make sure that Vx_resource_name is set to a reasonable value.
2606 Fix it up, or set it to `emacs' if it is too hopeless. */
2608 static void
2609 validate_x_resource_name ()
2611 int len = 0;
2612 /* Number of valid characters in the resource name. */
2613 int good_count = 0;
2614 /* Number of invalid characters in the resource name. */
2615 int bad_count = 0;
2616 Lisp_Object new;
2617 int i;
2619 if (!STRINGP (Vx_resource_class))
2620 Vx_resource_class = build_string (EMACS_CLASS);
2622 if (STRINGP (Vx_resource_name))
2624 unsigned char *p = XSTRING (Vx_resource_name)->data;
2625 int i;
2627 len = STRING_BYTES (XSTRING (Vx_resource_name));
2629 /* Only letters, digits, - and _ are valid in resource names.
2630 Count the valid characters and count the invalid ones. */
2631 for (i = 0; i < len; i++)
2633 int c = p[i];
2634 if (! ((c >= 'a' && c <= 'z')
2635 || (c >= 'A' && c <= 'Z')
2636 || (c >= '0' && c <= '9')
2637 || c == '-' || c == '_'))
2638 bad_count++;
2639 else
2640 good_count++;
2643 else
2644 /* Not a string => completely invalid. */
2645 bad_count = 5, good_count = 0;
2647 /* If name is valid already, return. */
2648 if (bad_count == 0)
2649 return;
2651 /* If name is entirely invalid, or nearly so, use `emacs'. */
2652 if (good_count == 0
2653 || (good_count == 1 && bad_count > 0))
2655 Vx_resource_name = build_string ("emacs");
2656 return;
2659 /* Name is partly valid. Copy it and replace the invalid characters
2660 with underscores. */
2662 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2664 for (i = 0; i < len; i++)
2666 int c = XSTRING (new)->data[i];
2667 if (! ((c >= 'a' && c <= 'z')
2668 || (c >= 'A' && c <= 'Z')
2669 || (c >= '0' && c <= '9')
2670 || c == '-' || c == '_'))
2671 XSTRING (new)->data[i] = '_';
2676 extern char *x_get_string_resource ();
2678 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2679 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2680 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2681 class, where INSTANCE is the name under which Emacs was invoked, or
2682 the name specified by the `-name' or `-rn' command-line arguments.
2684 The optional arguments COMPONENT and SUBCLASS add to the key and the
2685 class, respectively. You must specify both of them or neither.
2686 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2687 and the class is `Emacs.CLASS.SUBCLASS'. */)
2688 (attribute, class, component, subclass)
2689 Lisp_Object attribute, class, component, subclass;
2691 register char *value;
2692 char *name_key;
2693 char *class_key;
2695 check_x ();
2697 CHECK_STRING (attribute);
2698 CHECK_STRING (class);
2700 if (!NILP (component))
2701 CHECK_STRING (component);
2702 if (!NILP (subclass))
2703 CHECK_STRING (subclass);
2704 if (NILP (component) != NILP (subclass))
2705 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2707 validate_x_resource_name ();
2709 /* Allocate space for the components, the dots which separate them,
2710 and the final '\0'. Make them big enough for the worst case. */
2711 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2712 + (STRINGP (component)
2713 ? STRING_BYTES (XSTRING (component)) : 0)
2714 + STRING_BYTES (XSTRING (attribute))
2715 + 3);
2717 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2718 + STRING_BYTES (XSTRING (class))
2719 + (STRINGP (subclass)
2720 ? STRING_BYTES (XSTRING (subclass)) : 0)
2721 + 3);
2723 /* Start with emacs.FRAMENAME for the name (the specific one)
2724 and with `Emacs' for the class key (the general one). */
2725 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2726 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2728 strcat (class_key, ".");
2729 strcat (class_key, XSTRING (class)->data);
2731 if (!NILP (component))
2733 strcat (class_key, ".");
2734 strcat (class_key, XSTRING (subclass)->data);
2736 strcat (name_key, ".");
2737 strcat (name_key, XSTRING (component)->data);
2740 strcat (name_key, ".");
2741 strcat (name_key, XSTRING (attribute)->data);
2743 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2744 name_key, class_key);
2746 if (value != (char *) 0)
2747 return build_string (value);
2748 else
2749 return Qnil;
2752 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2754 Lisp_Object
2755 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2756 struct x_display_info *dpyinfo;
2757 Lisp_Object attribute, class, component, subclass;
2759 register char *value;
2760 char *name_key;
2761 char *class_key;
2763 CHECK_STRING (attribute);
2764 CHECK_STRING (class);
2766 if (!NILP (component))
2767 CHECK_STRING (component);
2768 if (!NILP (subclass))
2769 CHECK_STRING (subclass);
2770 if (NILP (component) != NILP (subclass))
2771 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2773 validate_x_resource_name ();
2775 /* Allocate space for the components, the dots which separate them,
2776 and the final '\0'. Make them big enough for the worst case. */
2777 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2778 + (STRINGP (component)
2779 ? STRING_BYTES (XSTRING (component)) : 0)
2780 + STRING_BYTES (XSTRING (attribute))
2781 + 3);
2783 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2784 + STRING_BYTES (XSTRING (class))
2785 + (STRINGP (subclass)
2786 ? STRING_BYTES (XSTRING (subclass)) : 0)
2787 + 3);
2789 /* Start with emacs.FRAMENAME for the name (the specific one)
2790 and with `Emacs' for the class key (the general one). */
2791 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2792 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2794 strcat (class_key, ".");
2795 strcat (class_key, XSTRING (class)->data);
2797 if (!NILP (component))
2799 strcat (class_key, ".");
2800 strcat (class_key, XSTRING (subclass)->data);
2802 strcat (name_key, ".");
2803 strcat (name_key, XSTRING (component)->data);
2806 strcat (name_key, ".");
2807 strcat (name_key, XSTRING (attribute)->data);
2809 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2811 if (value != (char *) 0)
2812 return build_string (value);
2813 else
2814 return Qnil;
2817 /* Used when C code wants a resource value. */
2819 char *
2820 x_get_resource_string (attribute, class)
2821 char *attribute, *class;
2823 char *name_key;
2824 char *class_key;
2825 struct frame *sf = SELECTED_FRAME ();
2827 /* Allocate space for the components, the dots which separate them,
2828 and the final '\0'. */
2829 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2830 + strlen (attribute) + 2);
2831 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2832 + strlen (class) + 2);
2834 sprintf (name_key, "%s.%s",
2835 XSTRING (Vinvocation_name)->data,
2836 attribute);
2837 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2839 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2840 name_key, class_key);
2843 /* Types we might convert a resource string into. */
2844 enum resource_types
2846 RES_TYPE_NUMBER,
2847 RES_TYPE_FLOAT,
2848 RES_TYPE_BOOLEAN,
2849 RES_TYPE_STRING,
2850 RES_TYPE_SYMBOL
2853 /* Return the value of parameter PARAM.
2855 First search ALIST, then Vdefault_frame_alist, then the X defaults
2856 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2858 Convert the resource to the type specified by desired_type.
2860 If no default is specified, return Qunbound. If you call
2861 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2862 and don't let it get stored in any Lisp-visible variables! */
2864 static Lisp_Object
2865 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2866 struct x_display_info *dpyinfo;
2867 Lisp_Object alist, param;
2868 char *attribute;
2869 char *class;
2870 enum resource_types type;
2872 register Lisp_Object tem;
2874 tem = Fassq (param, alist);
2875 if (EQ (tem, Qnil))
2876 tem = Fassq (param, Vdefault_frame_alist);
2877 if (EQ (tem, Qnil))
2880 if (attribute)
2882 tem = display_x_get_resource (dpyinfo,
2883 build_string (attribute),
2884 build_string (class),
2885 Qnil, Qnil);
2887 if (NILP (tem))
2888 return Qunbound;
2890 switch (type)
2892 case RES_TYPE_NUMBER:
2893 return make_number (atoi (XSTRING (tem)->data));
2895 case RES_TYPE_FLOAT:
2896 return make_float (atof (XSTRING (tem)->data));
2898 case RES_TYPE_BOOLEAN:
2899 tem = Fdowncase (tem);
2900 if (!strcmp (XSTRING (tem)->data, "on")
2901 || !strcmp (XSTRING (tem)->data, "true"))
2902 return Qt;
2903 else
2904 return Qnil;
2906 case RES_TYPE_STRING:
2907 return tem;
2909 case RES_TYPE_SYMBOL:
2910 /* As a special case, we map the values `true' and `on'
2911 to Qt, and `false' and `off' to Qnil. */
2913 Lisp_Object lower;
2914 lower = Fdowncase (tem);
2915 if (!strcmp (XSTRING (lower)->data, "on")
2916 || !strcmp (XSTRING (lower)->data, "true"))
2917 return Qt;
2918 else if (!strcmp (XSTRING (lower)->data, "off")
2919 || !strcmp (XSTRING (lower)->data, "false"))
2920 return Qnil;
2921 else
2922 return Fintern (tem, Qnil);
2925 default:
2926 abort ();
2929 else
2930 return Qunbound;
2932 return Fcdr (tem);
2935 /* Like x_get_arg, but also record the value in f->param_alist. */
2937 static Lisp_Object
2938 x_get_and_record_arg (f, alist, param, attribute, class, type)
2939 struct frame *f;
2940 Lisp_Object alist, param;
2941 char *attribute;
2942 char *class;
2943 enum resource_types type;
2945 Lisp_Object value;
2947 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2948 attribute, class, type);
2949 if (! NILP (value))
2950 store_frame_param (f, param, value);
2952 return value;
2955 /* Record in frame F the specified or default value according to ALIST
2956 of the parameter named PROP (a Lisp symbol).
2957 If no value is specified for PROP, look for an X default for XPROP
2958 on the frame named NAME.
2959 If that is not found either, use the value DEFLT. */
2961 static Lisp_Object
2962 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2963 struct frame *f;
2964 Lisp_Object alist;
2965 Lisp_Object prop;
2966 Lisp_Object deflt;
2967 char *xprop;
2968 char *xclass;
2969 enum resource_types type;
2971 Lisp_Object tem;
2973 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2974 if (EQ (tem, Qunbound))
2975 tem = deflt;
2976 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2977 return tem;
2981 /* Record in frame F the specified or default value according to ALIST
2982 of the parameter named PROP (a Lisp symbol). If no value is
2983 specified for PROP, look for an X default for XPROP on the frame
2984 named NAME. If that is not found either, use the value DEFLT. */
2986 static Lisp_Object
2987 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2988 foreground_p)
2989 struct frame *f;
2990 Lisp_Object alist;
2991 Lisp_Object prop;
2992 char *xprop;
2993 char *xclass;
2994 int foreground_p;
2996 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2997 Lisp_Object tem;
2999 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
3000 if (EQ (tem, Qunbound))
3002 #ifdef USE_TOOLKIT_SCROLL_BARS
3004 /* See if an X resource for the scroll bar color has been
3005 specified. */
3006 tem = display_x_get_resource (dpyinfo,
3007 build_string (foreground_p
3008 ? "foreground"
3009 : "background"),
3010 empty_string,
3011 build_string ("verticalScrollBar"),
3012 empty_string);
3013 if (!STRINGP (tem))
3015 /* If nothing has been specified, scroll bars will use a
3016 toolkit-dependent default. Because these defaults are
3017 difficult to get at without actually creating a scroll
3018 bar, use nil to indicate that no color has been
3019 specified. */
3020 tem = Qnil;
3023 #else /* not USE_TOOLKIT_SCROLL_BARS */
3025 tem = Qnil;
3027 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3030 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3031 return tem;
3036 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3037 doc: /* Parse an X-style geometry string STRING.
3038 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3039 The properties returned may include `top', `left', `height', and `width'.
3040 The value of `left' or `top' may be an integer,
3041 or a list (+ N) meaning N pixels relative to top/left corner,
3042 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3043 (string)
3044 Lisp_Object string;
3046 int geometry, x, y;
3047 unsigned int width, height;
3048 Lisp_Object result;
3050 CHECK_STRING (string);
3052 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3053 &x, &y, &width, &height);
3055 #if 0
3056 if (!!(geometry & XValue) != !!(geometry & YValue))
3057 error ("Must specify both x and y position, or neither");
3058 #endif
3060 result = Qnil;
3061 if (geometry & XValue)
3063 Lisp_Object element;
3065 if (x >= 0 && (geometry & XNegative))
3066 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3067 else if (x < 0 && ! (geometry & XNegative))
3068 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3069 else
3070 element = Fcons (Qleft, make_number (x));
3071 result = Fcons (element, result);
3074 if (geometry & YValue)
3076 Lisp_Object element;
3078 if (y >= 0 && (geometry & YNegative))
3079 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3080 else if (y < 0 && ! (geometry & YNegative))
3081 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3082 else
3083 element = Fcons (Qtop, make_number (y));
3084 result = Fcons (element, result);
3087 if (geometry & WidthValue)
3088 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3089 if (geometry & HeightValue)
3090 result = Fcons (Fcons (Qheight, make_number (height)), result);
3092 return result;
3095 /* Calculate the desired size and position of this window,
3096 and return the flags saying which aspects were specified.
3098 This function does not make the coordinates positive. */
3100 #define DEFAULT_ROWS 40
3101 #define DEFAULT_COLS 80
3103 static int
3104 x_figure_window_size (f, parms)
3105 struct frame *f;
3106 Lisp_Object parms;
3108 register Lisp_Object tem0, tem1, tem2;
3109 long window_prompting = 0;
3110 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3112 /* Default values if we fall through.
3113 Actually, if that happens we should get
3114 window manager prompting. */
3115 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3116 f->height = DEFAULT_ROWS;
3117 /* Window managers expect that if program-specified
3118 positions are not (0,0), they're intentional, not defaults. */
3119 f->output_data.x->top_pos = 0;
3120 f->output_data.x->left_pos = 0;
3122 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3123 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3124 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3125 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3127 if (!EQ (tem0, Qunbound))
3129 CHECK_NUMBER (tem0);
3130 f->height = XINT (tem0);
3132 if (!EQ (tem1, Qunbound))
3134 CHECK_NUMBER (tem1);
3135 SET_FRAME_WIDTH (f, XINT (tem1));
3137 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3138 window_prompting |= USSize;
3139 else
3140 window_prompting |= PSize;
3143 f->output_data.x->vertical_scroll_bar_extra
3144 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3146 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3148 x_compute_fringe_widths (f, 0);
3150 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3151 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3153 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3154 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3155 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3156 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3158 if (EQ (tem0, Qminus))
3160 f->output_data.x->top_pos = 0;
3161 window_prompting |= YNegative;
3163 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3164 && CONSP (XCDR (tem0))
3165 && INTEGERP (XCAR (XCDR (tem0))))
3167 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3168 window_prompting |= YNegative;
3170 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3171 && CONSP (XCDR (tem0))
3172 && INTEGERP (XCAR (XCDR (tem0))))
3174 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3176 else if (EQ (tem0, Qunbound))
3177 f->output_data.x->top_pos = 0;
3178 else
3180 CHECK_NUMBER (tem0);
3181 f->output_data.x->top_pos = XINT (tem0);
3182 if (f->output_data.x->top_pos < 0)
3183 window_prompting |= YNegative;
3186 if (EQ (tem1, Qminus))
3188 f->output_data.x->left_pos = 0;
3189 window_prompting |= XNegative;
3191 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3192 && CONSP (XCDR (tem1))
3193 && INTEGERP (XCAR (XCDR (tem1))))
3195 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3196 window_prompting |= XNegative;
3198 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3199 && CONSP (XCDR (tem1))
3200 && INTEGERP (XCAR (XCDR (tem1))))
3202 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3204 else if (EQ (tem1, Qunbound))
3205 f->output_data.x->left_pos = 0;
3206 else
3208 CHECK_NUMBER (tem1);
3209 f->output_data.x->left_pos = XINT (tem1);
3210 if (f->output_data.x->left_pos < 0)
3211 window_prompting |= XNegative;
3214 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3215 window_prompting |= USPosition;
3216 else
3217 window_prompting |= PPosition;
3220 return window_prompting;
3223 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3225 Status
3226 XSetWMProtocols (dpy, w, protocols, count)
3227 Display *dpy;
3228 Window w;
3229 Atom *protocols;
3230 int count;
3232 Atom prop;
3233 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3234 if (prop == None) return False;
3235 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3236 (unsigned char *) protocols, count);
3237 return True;
3239 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3241 #ifdef USE_X_TOOLKIT
3243 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3244 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3245 already be present because of the toolkit (Motif adds some of them,
3246 for example, but Xt doesn't). */
3248 static void
3249 hack_wm_protocols (f, widget)
3250 FRAME_PTR f;
3251 Widget widget;
3253 Display *dpy = XtDisplay (widget);
3254 Window w = XtWindow (widget);
3255 int need_delete = 1;
3256 int need_focus = 1;
3257 int need_save = 1;
3259 BLOCK_INPUT;
3261 Atom type, *atoms = 0;
3262 int format = 0;
3263 unsigned long nitems = 0;
3264 unsigned long bytes_after;
3266 if ((XGetWindowProperty (dpy, w,
3267 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3268 (long)0, (long)100, False, XA_ATOM,
3269 &type, &format, &nitems, &bytes_after,
3270 (unsigned char **) &atoms)
3271 == Success)
3272 && format == 32 && type == XA_ATOM)
3273 while (nitems > 0)
3275 nitems--;
3276 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3277 need_delete = 0;
3278 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3279 need_focus = 0;
3280 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3281 need_save = 0;
3283 if (atoms) XFree ((char *) atoms);
3286 Atom props [10];
3287 int count = 0;
3288 if (need_delete)
3289 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3290 if (need_focus)
3291 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3292 if (need_save)
3293 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3294 if (count)
3295 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3296 XA_ATOM, 32, PropModeAppend,
3297 (unsigned char *) props, count);
3299 UNBLOCK_INPUT;
3301 #endif
3305 /* Support routines for XIC (X Input Context). */
3307 #ifdef HAVE_X_I18N
3309 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3310 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3313 /* Supported XIM styles, ordered by preferenc. */
3315 static XIMStyle supported_xim_styles[] =
3317 XIMPreeditPosition | XIMStatusArea,
3318 XIMPreeditPosition | XIMStatusNothing,
3319 XIMPreeditPosition | XIMStatusNone,
3320 XIMPreeditNothing | XIMStatusArea,
3321 XIMPreeditNothing | XIMStatusNothing,
3322 XIMPreeditNothing | XIMStatusNone,
3323 XIMPreeditNone | XIMStatusArea,
3324 XIMPreeditNone | XIMStatusNothing,
3325 XIMPreeditNone | XIMStatusNone,
3330 /* Create an X fontset on frame F with base font name
3331 BASE_FONTNAME.. */
3333 static XFontSet
3334 xic_create_xfontset (f, base_fontname)
3335 struct frame *f;
3336 char *base_fontname;
3338 XFontSet xfs;
3339 char **missing_list;
3340 int missing_count;
3341 char *def_string;
3343 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3344 base_fontname, &missing_list,
3345 &missing_count, &def_string);
3346 if (missing_list)
3347 XFreeStringList (missing_list);
3349 /* No need to free def_string. */
3350 return xfs;
3354 /* Value is the best input style, given user preferences USER (already
3355 checked to be supported by Emacs), and styles supported by the
3356 input method XIM. */
3358 static XIMStyle
3359 best_xim_style (user, xim)
3360 XIMStyles *user;
3361 XIMStyles *xim;
3363 int i, j;
3365 for (i = 0; i < user->count_styles; ++i)
3366 for (j = 0; j < xim->count_styles; ++j)
3367 if (user->supported_styles[i] == xim->supported_styles[j])
3368 return user->supported_styles[i];
3370 /* Return the default style. */
3371 return XIMPreeditNothing | XIMStatusNothing;
3374 /* Create XIC for frame F. */
3376 static XIMStyle xic_style;
3378 void
3379 create_frame_xic (f)
3380 struct frame *f;
3382 XIM xim;
3383 XIC xic = NULL;
3384 XFontSet xfs = NULL;
3386 if (FRAME_XIC (f))
3387 return;
3389 xim = FRAME_X_XIM (f);
3390 if (xim)
3392 XRectangle s_area;
3393 XPoint spot;
3394 XVaNestedList preedit_attr;
3395 XVaNestedList status_attr;
3396 char *base_fontname;
3397 int fontset;
3399 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3400 spot.x = 0; spot.y = 1;
3401 /* Create X fontset. */
3402 fontset = FRAME_FONTSET (f);
3403 if (fontset < 0)
3404 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3405 else
3407 /* Determine the base fontname from the ASCII font name of
3408 FONTSET. */
3409 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3410 char *p = ascii_font;
3411 int i;
3413 for (i = 0; *p; p++)
3414 if (*p == '-') i++;
3415 if (i != 14)
3416 /* As the font name doesn't conform to XLFD, we can't
3417 modify it to get a suitable base fontname for the
3418 frame. */
3419 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3420 else
3422 int len = strlen (ascii_font) + 1;
3423 char *p1 = NULL;
3425 for (i = 0, p = ascii_font; i < 8; p++)
3427 if (*p == '-')
3429 i++;
3430 if (i == 3)
3431 p1 = p + 1;
3434 base_fontname = (char *) alloca (len);
3435 bzero (base_fontname, len);
3436 strcpy (base_fontname, "-*-*-");
3437 bcopy (p1, base_fontname + 5, p - p1);
3438 strcat (base_fontname, "*-*-*-*-*-*-*");
3441 xfs = xic_create_xfontset (f, base_fontname);
3443 /* Determine XIC style. */
3444 if (xic_style == 0)
3446 XIMStyles supported_list;
3447 supported_list.count_styles = (sizeof supported_xim_styles
3448 / sizeof supported_xim_styles[0]);
3449 supported_list.supported_styles = supported_xim_styles;
3450 xic_style = best_xim_style (&supported_list,
3451 FRAME_X_XIM_STYLES (f));
3454 preedit_attr = XVaCreateNestedList (0,
3455 XNFontSet, xfs,
3456 XNForeground,
3457 FRAME_FOREGROUND_PIXEL (f),
3458 XNBackground,
3459 FRAME_BACKGROUND_PIXEL (f),
3460 (xic_style & XIMPreeditPosition
3461 ? XNSpotLocation
3462 : NULL),
3463 &spot,
3464 NULL);
3465 status_attr = XVaCreateNestedList (0,
3466 XNArea,
3467 &s_area,
3468 XNFontSet,
3469 xfs,
3470 XNForeground,
3471 FRAME_FOREGROUND_PIXEL (f),
3472 XNBackground,
3473 FRAME_BACKGROUND_PIXEL (f),
3474 NULL);
3476 xic = XCreateIC (xim,
3477 XNInputStyle, xic_style,
3478 XNClientWindow, FRAME_X_WINDOW(f),
3479 XNFocusWindow, FRAME_X_WINDOW(f),
3480 XNStatusAttributes, status_attr,
3481 XNPreeditAttributes, preedit_attr,
3482 NULL);
3483 XFree (preedit_attr);
3484 XFree (status_attr);
3487 FRAME_XIC (f) = xic;
3488 FRAME_XIC_STYLE (f) = xic_style;
3489 FRAME_XIC_FONTSET (f) = xfs;
3493 /* Destroy XIC and free XIC fontset of frame F, if any. */
3495 void
3496 free_frame_xic (f)
3497 struct frame *f;
3499 if (FRAME_XIC (f) == NULL)
3500 return;
3502 XDestroyIC (FRAME_XIC (f));
3503 if (FRAME_XIC_FONTSET (f))
3504 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3506 FRAME_XIC (f) = NULL;
3507 FRAME_XIC_FONTSET (f) = NULL;
3511 /* Place preedit area for XIC of window W's frame to specified
3512 pixel position X/Y. X and Y are relative to window W. */
3514 void
3515 xic_set_preeditarea (w, x, y)
3516 struct window *w;
3517 int x, y;
3519 struct frame *f = XFRAME (w->frame);
3520 XVaNestedList attr;
3521 XPoint spot;
3523 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3524 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3525 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3526 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3527 XFree (attr);
3531 /* Place status area for XIC in bottom right corner of frame F.. */
3533 void
3534 xic_set_statusarea (f)
3535 struct frame *f;
3537 XIC xic = FRAME_XIC (f);
3538 XVaNestedList attr;
3539 XRectangle area;
3540 XRectangle *needed;
3542 /* Negotiate geometry of status area. If input method has existing
3543 status area, use its current size. */
3544 area.x = area.y = area.width = area.height = 0;
3545 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3546 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3547 XFree (attr);
3549 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3550 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3551 XFree (attr);
3553 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3555 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3556 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3557 XFree (attr);
3560 area.width = needed->width;
3561 area.height = needed->height;
3562 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3563 area.y = (PIXEL_HEIGHT (f) - area.height
3564 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3565 XFree (needed);
3567 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3568 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3569 XFree (attr);
3573 /* Set X fontset for XIC of frame F, using base font name
3574 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3576 void
3577 xic_set_xfontset (f, base_fontname)
3578 struct frame *f;
3579 char *base_fontname;
3581 XVaNestedList attr;
3582 XFontSet xfs;
3584 xfs = xic_create_xfontset (f, base_fontname);
3586 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3587 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3588 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3589 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3590 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3591 XFree (attr);
3593 if (FRAME_XIC_FONTSET (f))
3594 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3595 FRAME_XIC_FONTSET (f) = xfs;
3598 #endif /* HAVE_X_I18N */
3602 #ifdef USE_X_TOOLKIT
3604 /* Create and set up the X widget for frame F. */
3606 static void
3607 x_window (f, window_prompting, minibuffer_only)
3608 struct frame *f;
3609 long window_prompting;
3610 int minibuffer_only;
3612 XClassHint class_hints;
3613 XSetWindowAttributes attributes;
3614 unsigned long attribute_mask;
3615 Widget shell_widget;
3616 Widget pane_widget;
3617 Widget frame_widget;
3618 Arg al [25];
3619 int ac;
3621 BLOCK_INPUT;
3623 /* Use the resource name as the top-level widget name
3624 for looking up resources. Make a non-Lisp copy
3625 for the window manager, so GC relocation won't bother it.
3627 Elsewhere we specify the window name for the window manager. */
3630 char *str = (char *) XSTRING (Vx_resource_name)->data;
3631 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3632 strcpy (f->namebuf, str);
3635 ac = 0;
3636 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3637 XtSetArg (al[ac], XtNinput, 1); ac++;
3638 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3639 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3640 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3641 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3642 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3643 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3644 applicationShellWidgetClass,
3645 FRAME_X_DISPLAY (f), al, ac);
3647 f->output_data.x->widget = shell_widget;
3648 /* maybe_set_screen_title_format (shell_widget); */
3650 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3651 (widget_value *) NULL,
3652 shell_widget, False,
3653 (lw_callback) NULL,
3654 (lw_callback) NULL,
3655 (lw_callback) NULL,
3656 (lw_callback) NULL);
3658 ac = 0;
3659 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3660 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3661 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3662 XtSetValues (pane_widget, al, ac);
3663 f->output_data.x->column_widget = pane_widget;
3665 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3666 the emacs screen when changing menubar. This reduces flickering. */
3668 ac = 0;
3669 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3670 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3671 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3672 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3673 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3674 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3675 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3676 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3677 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3678 al, ac);
3680 f->output_data.x->edit_widget = frame_widget;
3682 XtManageChild (frame_widget);
3684 /* Do some needed geometry management. */
3686 int len;
3687 char *tem, shell_position[32];
3688 Arg al[2];
3689 int ac = 0;
3690 int extra_borders = 0;
3691 int menubar_size
3692 = (f->output_data.x->menubar_widget
3693 ? (f->output_data.x->menubar_widget->core.height
3694 + f->output_data.x->menubar_widget->core.border_width)
3695 : 0);
3697 #if 0 /* Experimentally, we now get the right results
3698 for -geometry -0-0 without this. 24 Aug 96, rms. */
3699 if (FRAME_EXTERNAL_MENU_BAR (f))
3701 Dimension ibw = 0;
3702 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3703 menubar_size += ibw;
3705 #endif
3707 f->output_data.x->menubar_height = menubar_size;
3709 #ifndef USE_LUCID
3710 /* Motif seems to need this amount added to the sizes
3711 specified for the shell widget. The Athena/Lucid widgets don't.
3712 Both conclusions reached experimentally. -- rms. */
3713 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3714 &extra_borders, NULL);
3715 extra_borders *= 2;
3716 #endif
3718 /* Convert our geometry parameters into a geometry string
3719 and specify it.
3720 Note that we do not specify here whether the position
3721 is a user-specified or program-specified one.
3722 We pass that information later, in x_wm_set_size_hints. */
3724 int left = f->output_data.x->left_pos;
3725 int xneg = window_prompting & XNegative;
3726 int top = f->output_data.x->top_pos;
3727 int yneg = window_prompting & YNegative;
3728 if (xneg)
3729 left = -left;
3730 if (yneg)
3731 top = -top;
3733 if (window_prompting & USPosition)
3734 sprintf (shell_position, "=%dx%d%c%d%c%d",
3735 PIXEL_WIDTH (f) + extra_borders,
3736 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3737 (xneg ? '-' : '+'), left,
3738 (yneg ? '-' : '+'), top);
3739 else
3740 sprintf (shell_position, "=%dx%d",
3741 PIXEL_WIDTH (f) + extra_borders,
3742 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3745 len = strlen (shell_position) + 1;
3746 /* We don't free this because we don't know whether
3747 it is safe to free it while the frame exists.
3748 It isn't worth the trouble of arranging to free it
3749 when the frame is deleted. */
3750 tem = (char *) xmalloc (len);
3751 strncpy (tem, shell_position, len);
3752 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3753 XtSetValues (shell_widget, al, ac);
3756 XtManageChild (pane_widget);
3757 XtRealizeWidget (shell_widget);
3759 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3761 validate_x_resource_name ();
3763 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3764 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3765 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3767 #ifdef HAVE_X_I18N
3768 FRAME_XIC (f) = NULL;
3769 #ifdef USE_XIM
3770 create_frame_xic (f);
3771 #endif
3772 #endif
3774 f->output_data.x->wm_hints.input = True;
3775 f->output_data.x->wm_hints.flags |= InputHint;
3776 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3777 &f->output_data.x->wm_hints);
3779 hack_wm_protocols (f, shell_widget);
3781 #ifdef HACK_EDITRES
3782 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3783 #endif
3785 /* Do a stupid property change to force the server to generate a
3786 PropertyNotify event so that the event_stream server timestamp will
3787 be initialized to something relevant to the time we created the window.
3789 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3790 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3791 XA_ATOM, 32, PropModeAppend,
3792 (unsigned char*) NULL, 0);
3794 /* Make all the standard events reach the Emacs frame. */
3795 attributes.event_mask = STANDARD_EVENT_SET;
3797 #ifdef HAVE_X_I18N
3798 if (FRAME_XIC (f))
3800 /* XIM server might require some X events. */
3801 unsigned long fevent = NoEventMask;
3802 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3803 attributes.event_mask |= fevent;
3805 #endif /* HAVE_X_I18N */
3807 attribute_mask = CWEventMask;
3808 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3809 attribute_mask, &attributes);
3811 XtMapWidget (frame_widget);
3813 /* x_set_name normally ignores requests to set the name if the
3814 requested name is the same as the current name. This is the one
3815 place where that assumption isn't correct; f->name is set, but
3816 the X server hasn't been told. */
3818 Lisp_Object name;
3819 int explicit = f->explicit_name;
3821 f->explicit_name = 0;
3822 name = f->name;
3823 f->name = Qnil;
3824 x_set_name (f, name, explicit);
3827 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3828 f->output_data.x->text_cursor);
3830 UNBLOCK_INPUT;
3832 /* This is a no-op, except under Motif. Make sure main areas are
3833 set to something reasonable, in case we get an error later. */
3834 lw_set_main_areas (pane_widget, 0, frame_widget);
3837 #else /* not USE_X_TOOLKIT */
3839 /* Create and set up the X window for frame F. */
3841 void
3842 x_window (f)
3843 struct frame *f;
3846 XClassHint class_hints;
3847 XSetWindowAttributes attributes;
3848 unsigned long attribute_mask;
3850 attributes.background_pixel = f->output_data.x->background_pixel;
3851 attributes.border_pixel = f->output_data.x->border_pixel;
3852 attributes.bit_gravity = StaticGravity;
3853 attributes.backing_store = NotUseful;
3854 attributes.save_under = True;
3855 attributes.event_mask = STANDARD_EVENT_SET;
3856 attributes.colormap = FRAME_X_COLORMAP (f);
3857 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3858 | CWColormap);
3860 BLOCK_INPUT;
3861 FRAME_X_WINDOW (f)
3862 = XCreateWindow (FRAME_X_DISPLAY (f),
3863 f->output_data.x->parent_desc,
3864 f->output_data.x->left_pos,
3865 f->output_data.x->top_pos,
3866 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3867 f->output_data.x->border_width,
3868 CopyFromParent, /* depth */
3869 InputOutput, /* class */
3870 FRAME_X_VISUAL (f),
3871 attribute_mask, &attributes);
3873 #ifdef HAVE_X_I18N
3874 #ifdef USE_XIM
3875 create_frame_xic (f);
3876 if (FRAME_XIC (f))
3878 /* XIM server might require some X events. */
3879 unsigned long fevent = NoEventMask;
3880 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3881 attributes.event_mask |= fevent;
3882 attribute_mask = CWEventMask;
3883 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3884 attribute_mask, &attributes);
3886 #endif
3887 #endif /* HAVE_X_I18N */
3889 validate_x_resource_name ();
3891 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3892 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3893 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3895 /* The menubar is part of the ordinary display;
3896 it does not count in addition to the height of the window. */
3897 f->output_data.x->menubar_height = 0;
3899 /* This indicates that we use the "Passive Input" input model.
3900 Unless we do this, we don't get the Focus{In,Out} events that we
3901 need to draw the cursor correctly. Accursed bureaucrats.
3902 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3904 f->output_data.x->wm_hints.input = True;
3905 f->output_data.x->wm_hints.flags |= InputHint;
3906 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3907 &f->output_data.x->wm_hints);
3908 f->output_data.x->wm_hints.icon_pixmap = None;
3910 /* Request "save yourself" and "delete window" commands from wm. */
3912 Atom protocols[2];
3913 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3914 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3915 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3918 /* x_set_name normally ignores requests to set the name if the
3919 requested name is the same as the current name. This is the one
3920 place where that assumption isn't correct; f->name is set, but
3921 the X server hasn't been told. */
3923 Lisp_Object name;
3924 int explicit = f->explicit_name;
3926 f->explicit_name = 0;
3927 name = f->name;
3928 f->name = Qnil;
3929 x_set_name (f, name, explicit);
3932 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3933 f->output_data.x->text_cursor);
3935 UNBLOCK_INPUT;
3937 if (FRAME_X_WINDOW (f) == 0)
3938 error ("Unable to create window");
3941 #endif /* not USE_X_TOOLKIT */
3943 /* Handle the icon stuff for this window. Perhaps later we might
3944 want an x_set_icon_position which can be called interactively as
3945 well. */
3947 static void
3948 x_icon (f, parms)
3949 struct frame *f;
3950 Lisp_Object parms;
3952 Lisp_Object icon_x, icon_y;
3953 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3955 /* Set the position of the icon. Note that twm groups all
3956 icons in an icon window. */
3957 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3958 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3959 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3961 CHECK_NUMBER (icon_x);
3962 CHECK_NUMBER (icon_y);
3964 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3965 error ("Both left and top icon corners of icon must be specified");
3967 BLOCK_INPUT;
3969 if (! EQ (icon_x, Qunbound))
3970 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3972 /* Start up iconic or window? */
3973 x_wm_set_window_state
3974 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3975 Qicon)
3976 ? IconicState
3977 : NormalState));
3979 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3980 ? f->icon_name
3981 : f->name))->data);
3983 UNBLOCK_INPUT;
3986 /* Make the GCs needed for this window, setting the
3987 background, border and mouse colors; also create the
3988 mouse cursor and the gray border tile. */
3990 static char cursor_bits[] =
3992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3995 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3998 static void
3999 x_make_gc (f)
4000 struct frame *f;
4002 XGCValues gc_values;
4004 BLOCK_INPUT;
4006 /* Create the GCs of this frame.
4007 Note that many default values are used. */
4009 /* Normal video */
4010 gc_values.font = f->output_data.x->font->fid;
4011 gc_values.foreground = f->output_data.x->foreground_pixel;
4012 gc_values.background = f->output_data.x->background_pixel;
4013 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
4014 f->output_data.x->normal_gc
4015 = XCreateGC (FRAME_X_DISPLAY (f),
4016 FRAME_X_WINDOW (f),
4017 GCLineWidth | GCFont | GCForeground | GCBackground,
4018 &gc_values);
4020 /* Reverse video style. */
4021 gc_values.foreground = f->output_data.x->background_pixel;
4022 gc_values.background = f->output_data.x->foreground_pixel;
4023 f->output_data.x->reverse_gc
4024 = XCreateGC (FRAME_X_DISPLAY (f),
4025 FRAME_X_WINDOW (f),
4026 GCFont | GCForeground | GCBackground | GCLineWidth,
4027 &gc_values);
4029 /* Cursor has cursor-color background, background-color foreground. */
4030 gc_values.foreground = f->output_data.x->background_pixel;
4031 gc_values.background = f->output_data.x->cursor_pixel;
4032 gc_values.fill_style = FillOpaqueStippled;
4033 gc_values.stipple
4034 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4035 FRAME_X_DISPLAY_INFO (f)->root_window,
4036 cursor_bits, 16, 16);
4037 f->output_data.x->cursor_gc
4038 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4039 (GCFont | GCForeground | GCBackground
4040 | GCFillStyle /* | GCStipple */ | GCLineWidth),
4041 &gc_values);
4043 /* Reliefs. */
4044 f->output_data.x->white_relief.gc = 0;
4045 f->output_data.x->black_relief.gc = 0;
4047 /* Create the gray border tile used when the pointer is not in
4048 the frame. Since this depends on the frame's pixel values,
4049 this must be done on a per-frame basis. */
4050 f->output_data.x->border_tile
4051 = (XCreatePixmapFromBitmapData
4052 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4053 gray_bits, gray_width, gray_height,
4054 f->output_data.x->foreground_pixel,
4055 f->output_data.x->background_pixel,
4056 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4058 UNBLOCK_INPUT;
4062 /* Free what was was allocated in x_make_gc. */
4064 void
4065 x_free_gcs (f)
4066 struct frame *f;
4068 Display *dpy = FRAME_X_DISPLAY (f);
4070 BLOCK_INPUT;
4072 if (f->output_data.x->normal_gc)
4074 XFreeGC (dpy, f->output_data.x->normal_gc);
4075 f->output_data.x->normal_gc = 0;
4078 if (f->output_data.x->reverse_gc)
4080 XFreeGC (dpy, f->output_data.x->reverse_gc);
4081 f->output_data.x->reverse_gc = 0;
4084 if (f->output_data.x->cursor_gc)
4086 XFreeGC (dpy, f->output_data.x->cursor_gc);
4087 f->output_data.x->cursor_gc = 0;
4090 if (f->output_data.x->border_tile)
4092 XFreePixmap (dpy, f->output_data.x->border_tile);
4093 f->output_data.x->border_tile = 0;
4096 UNBLOCK_INPUT;
4100 /* Handler for signals raised during x_create_frame and
4101 x_create_top_frame. FRAME is the frame which is partially
4102 constructed. */
4104 static Lisp_Object
4105 unwind_create_frame (frame)
4106 Lisp_Object frame;
4108 struct frame *f = XFRAME (frame);
4110 /* If frame is ``official'', nothing to do. */
4111 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4113 #if GLYPH_DEBUG
4114 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4115 #endif
4117 x_free_frame_resources (f);
4119 /* Check that reference counts are indeed correct. */
4120 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4121 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4122 return Qt;
4125 return Qnil;
4129 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4130 1, 1, 0,
4131 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
4132 Returns an Emacs frame object.
4133 ALIST is an alist of frame parameters.
4134 If the parameters specify that the frame should not have a minibuffer,
4135 and do not specify a specific minibuffer window to use,
4136 then `default-minibuffer-frame' must be a frame whose minibuffer can
4137 be shared by the new frame.
4139 This function is an internal primitive--use `make-frame' instead. */)
4140 (parms)
4141 Lisp_Object parms;
4143 struct frame *f;
4144 Lisp_Object frame, tem;
4145 Lisp_Object name;
4146 int minibuffer_only = 0;
4147 long window_prompting = 0;
4148 int width, height;
4149 int count = BINDING_STACK_SIZE ();
4150 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4151 Lisp_Object display;
4152 struct x_display_info *dpyinfo = NULL;
4153 Lisp_Object parent;
4154 struct kboard *kb;
4156 check_x ();
4158 /* Use this general default value to start with
4159 until we know if this frame has a specified name. */
4160 Vx_resource_name = Vinvocation_name;
4162 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4163 if (EQ (display, Qunbound))
4164 display = Qnil;
4165 dpyinfo = check_x_display_info (display);
4166 #ifdef MULTI_KBOARD
4167 kb = dpyinfo->kboard;
4168 #else
4169 kb = &the_only_kboard;
4170 #endif
4172 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4173 if (!STRINGP (name)
4174 && ! EQ (name, Qunbound)
4175 && ! NILP (name))
4176 error ("Invalid frame name--not a string or nil");
4178 if (STRINGP (name))
4179 Vx_resource_name = name;
4181 /* See if parent window is specified. */
4182 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4183 if (EQ (parent, Qunbound))
4184 parent = Qnil;
4185 if (! NILP (parent))
4186 CHECK_NUMBER (parent);
4188 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4189 /* No need to protect DISPLAY because that's not used after passing
4190 it to make_frame_without_minibuffer. */
4191 frame = Qnil;
4192 GCPRO4 (parms, parent, name, frame);
4193 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4194 RES_TYPE_SYMBOL);
4195 if (EQ (tem, Qnone) || NILP (tem))
4196 f = make_frame_without_minibuffer (Qnil, kb, display);
4197 else if (EQ (tem, Qonly))
4199 f = make_minibuffer_frame ();
4200 minibuffer_only = 1;
4202 else if (WINDOWP (tem))
4203 f = make_frame_without_minibuffer (tem, kb, display);
4204 else
4205 f = make_frame (1);
4207 XSETFRAME (frame, f);
4209 /* Note that X Windows does support scroll bars. */
4210 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4212 f->output_method = output_x_window;
4213 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4214 bzero (f->output_data.x, sizeof (struct x_output));
4215 f->output_data.x->icon_bitmap = -1;
4216 f->output_data.x->fontset = -1;
4217 f->output_data.x->scroll_bar_foreground_pixel = -1;
4218 f->output_data.x->scroll_bar_background_pixel = -1;
4219 #ifdef USE_TOOLKIT_SCROLL_BARS
4220 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4221 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4222 #endif /* USE_TOOLKIT_SCROLL_BARS */
4223 record_unwind_protect (unwind_create_frame, frame);
4225 f->icon_name
4226 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4227 RES_TYPE_STRING);
4228 if (! STRINGP (f->icon_name))
4229 f->icon_name = Qnil;
4231 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4232 #if GLYPH_DEBUG
4233 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4234 dpyinfo_refcount = dpyinfo->reference_count;
4235 #endif /* GLYPH_DEBUG */
4236 #ifdef MULTI_KBOARD
4237 FRAME_KBOARD (f) = kb;
4238 #endif
4240 /* These colors will be set anyway later, but it's important
4241 to get the color reference counts right, so initialize them! */
4243 Lisp_Object black;
4244 struct gcpro gcpro1;
4246 /* Function x_decode_color can signal an error. Make
4247 sure to initialize color slots so that we won't try
4248 to free colors we haven't allocated. */
4249 f->output_data.x->foreground_pixel = -1;
4250 f->output_data.x->background_pixel = -1;
4251 f->output_data.x->cursor_pixel = -1;
4252 f->output_data.x->cursor_foreground_pixel = -1;
4253 f->output_data.x->border_pixel = -1;
4254 f->output_data.x->mouse_pixel = -1;
4256 black = build_string ("black");
4257 GCPRO1 (black);
4258 f->output_data.x->foreground_pixel
4259 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4260 f->output_data.x->background_pixel
4261 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4262 f->output_data.x->cursor_pixel
4263 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4264 f->output_data.x->cursor_foreground_pixel
4265 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4266 f->output_data.x->border_pixel
4267 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4268 f->output_data.x->mouse_pixel
4269 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4270 UNGCPRO;
4273 /* Specify the parent under which to make this X window. */
4275 if (!NILP (parent))
4277 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4278 f->output_data.x->explicit_parent = 1;
4280 else
4282 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4283 f->output_data.x->explicit_parent = 0;
4286 /* Set the name; the functions to which we pass f expect the name to
4287 be set. */
4288 if (EQ (name, Qunbound) || NILP (name))
4290 f->name = build_string (dpyinfo->x_id_name);
4291 f->explicit_name = 0;
4293 else
4295 f->name = name;
4296 f->explicit_name = 1;
4297 /* use the frame's title when getting resources for this frame. */
4298 specbind (Qx_resource_name, name);
4301 /* Extract the window parameters from the supplied values
4302 that are needed to determine window geometry. */
4304 Lisp_Object font;
4306 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4308 BLOCK_INPUT;
4309 /* First, try whatever font the caller has specified. */
4310 if (STRINGP (font))
4312 tem = Fquery_fontset (font, Qnil);
4313 if (STRINGP (tem))
4314 font = x_new_fontset (f, XSTRING (tem)->data);
4315 else
4316 font = x_new_font (f, XSTRING (font)->data);
4319 /* Try out a font which we hope has bold and italic variations. */
4320 if (!STRINGP (font))
4321 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4322 if (!STRINGP (font))
4323 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4324 if (! STRINGP (font))
4325 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4326 if (! STRINGP (font))
4327 /* This was formerly the first thing tried, but it finds too many fonts
4328 and takes too long. */
4329 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4330 /* If those didn't work, look for something which will at least work. */
4331 if (! STRINGP (font))
4332 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4333 UNBLOCK_INPUT;
4334 if (! STRINGP (font))
4335 font = build_string ("fixed");
4337 x_default_parameter (f, parms, Qfont, font,
4338 "font", "Font", RES_TYPE_STRING);
4341 #ifdef USE_LUCID
4342 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4343 whereby it fails to get any font. */
4344 xlwmenu_default_font = f->output_data.x->font;
4345 #endif
4347 x_default_parameter (f, parms, Qborder_width, make_number (2),
4348 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4350 /* This defaults to 1 in order to match xterm. We recognize either
4351 internalBorderWidth or internalBorder (which is what xterm calls
4352 it). */
4353 if (NILP (Fassq (Qinternal_border_width, parms)))
4355 Lisp_Object value;
4357 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4358 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4359 if (! EQ (value, Qunbound))
4360 parms = Fcons (Fcons (Qinternal_border_width, value),
4361 parms);
4363 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4364 "internalBorderWidth", "internalBorderWidth",
4365 RES_TYPE_NUMBER);
4366 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4367 "verticalScrollBars", "ScrollBars",
4368 RES_TYPE_SYMBOL);
4370 /* Also do the stuff which must be set before the window exists. */
4371 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4372 "foreground", "Foreground", RES_TYPE_STRING);
4373 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4374 "background", "Background", RES_TYPE_STRING);
4375 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4376 "pointerColor", "Foreground", RES_TYPE_STRING);
4377 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4378 "cursorColor", "Foreground", RES_TYPE_STRING);
4379 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4380 "borderColor", "BorderColor", RES_TYPE_STRING);
4381 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4382 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4383 x_default_parameter (f, parms, Qline_spacing, Qnil,
4384 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4385 x_default_parameter (f, parms, Qleft_fringe, Qnil,
4386 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4387 x_default_parameter (f, parms, Qright_fringe, Qnil,
4388 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4390 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4391 "scrollBarForeground",
4392 "ScrollBarForeground", 1);
4393 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4394 "scrollBarBackground",
4395 "ScrollBarBackground", 0);
4397 /* Init faces before x_default_parameter is called for scroll-bar
4398 parameters because that function calls x_set_scroll_bar_width,
4399 which calls change_frame_size, which calls Fset_window_buffer,
4400 which runs hooks, which call Fvertical_motion. At the end, we
4401 end up in init_iterator with a null face cache, which should not
4402 happen. */
4403 init_frame_faces (f);
4405 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4406 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4407 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4408 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4409 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4410 "bufferPredicate", "BufferPredicate",
4411 RES_TYPE_SYMBOL);
4412 x_default_parameter (f, parms, Qtitle, Qnil,
4413 "title", "Title", RES_TYPE_STRING);
4414 x_default_parameter (f, parms, Qwait_for_wm, Qt,
4415 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4417 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4419 /* Add the tool-bar height to the initial frame height so that the
4420 user gets a text display area of the size he specified with -g or
4421 via .Xdefaults. Later changes of the tool-bar height don't
4422 change the frame size. This is done so that users can create
4423 tall Emacs frames without having to guess how tall the tool-bar
4424 will get. */
4425 if (FRAME_TOOL_BAR_LINES (f))
4427 int margin, relief, bar_height;
4429 relief = (tool_bar_button_relief >= 0
4430 ? tool_bar_button_relief
4431 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4433 if (INTEGERP (Vtool_bar_button_margin)
4434 && XINT (Vtool_bar_button_margin) > 0)
4435 margin = XFASTINT (Vtool_bar_button_margin);
4436 else if (CONSP (Vtool_bar_button_margin)
4437 && INTEGERP (XCDR (Vtool_bar_button_margin))
4438 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4439 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4440 else
4441 margin = 0;
4443 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4444 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4447 /* Compute the size of the X window. */
4448 window_prompting = x_figure_window_size (f, parms);
4450 if (window_prompting & XNegative)
4452 if (window_prompting & YNegative)
4453 f->output_data.x->win_gravity = SouthEastGravity;
4454 else
4455 f->output_data.x->win_gravity = NorthEastGravity;
4457 else
4459 if (window_prompting & YNegative)
4460 f->output_data.x->win_gravity = SouthWestGravity;
4461 else
4462 f->output_data.x->win_gravity = NorthWestGravity;
4465 f->output_data.x->size_hint_flags = window_prompting;
4467 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4468 f->no_split = minibuffer_only || EQ (tem, Qt);
4470 /* Create the X widget or window. */
4471 #ifdef USE_X_TOOLKIT
4472 x_window (f, window_prompting, minibuffer_only);
4473 #else
4474 x_window (f);
4475 #endif
4477 x_icon (f, parms);
4478 x_make_gc (f);
4480 /* Now consider the frame official. */
4481 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4482 Vframe_list = Fcons (frame, Vframe_list);
4484 /* We need to do this after creating the X window, so that the
4485 icon-creation functions can say whose icon they're describing. */
4486 x_default_parameter (f, parms, Qicon_type, Qnil,
4487 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4489 x_default_parameter (f, parms, Qauto_raise, Qnil,
4490 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4491 x_default_parameter (f, parms, Qauto_lower, Qnil,
4492 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4493 x_default_parameter (f, parms, Qcursor_type, Qbox,
4494 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4495 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4496 "scrollBarWidth", "ScrollBarWidth",
4497 RES_TYPE_NUMBER);
4499 /* Dimensions, especially f->height, must be done via change_frame_size.
4500 Change will not be effected unless different from the current
4501 f->height. */
4502 width = f->width;
4503 height = f->height;
4505 f->height = 0;
4506 SET_FRAME_WIDTH (f, 0);
4507 change_frame_size (f, height, width, 1, 0, 0);
4509 /* Set up faces after all frame parameters are known. This call
4510 also merges in face attributes specified for new frames. If we
4511 don't do this, the `menu' face for instance won't have the right
4512 colors, and the menu bar won't appear in the specified colors for
4513 new frames. */
4514 call1 (Qface_set_after_frame_default, frame);
4516 #ifdef USE_X_TOOLKIT
4517 /* Create the menu bar. */
4518 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4520 /* If this signals an error, we haven't set size hints for the
4521 frame and we didn't make it visible. */
4522 initialize_frame_menubar (f);
4524 /* This is a no-op, except under Motif where it arranges the
4525 main window for the widgets on it. */
4526 lw_set_main_areas (f->output_data.x->column_widget,
4527 f->output_data.x->menubar_widget,
4528 f->output_data.x->edit_widget);
4530 #endif /* USE_X_TOOLKIT */
4532 /* Tell the server what size and position, etc, we want, and how
4533 badly we want them. This should be done after we have the menu
4534 bar so that its size can be taken into account. */
4535 BLOCK_INPUT;
4536 x_wm_set_size_hint (f, window_prompting, 0);
4537 UNBLOCK_INPUT;
4539 /* Make the window appear on the frame and enable display, unless
4540 the caller says not to. However, with explicit parent, Emacs
4541 cannot control visibility, so don't try. */
4542 if (! f->output_data.x->explicit_parent)
4544 Lisp_Object visibility;
4546 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4547 RES_TYPE_SYMBOL);
4548 if (EQ (visibility, Qunbound))
4549 visibility = Qt;
4551 if (EQ (visibility, Qicon))
4552 x_iconify_frame (f);
4553 else if (! NILP (visibility))
4554 x_make_frame_visible (f);
4555 else
4556 /* Must have been Qnil. */
4560 UNGCPRO;
4562 /* Make sure windows on this frame appear in calls to next-window
4563 and similar functions. */
4564 Vwindow_list = Qnil;
4566 return unbind_to (count, frame);
4570 /* FRAME is used only to get a handle on the X display. We don't pass the
4571 display info directly because we're called from frame.c, which doesn't
4572 know about that structure. */
4574 Lisp_Object
4575 x_get_focus_frame (frame)
4576 struct frame *frame;
4578 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4579 Lisp_Object xfocus;
4580 if (! dpyinfo->x_focus_frame)
4581 return Qnil;
4583 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4584 return xfocus;
4588 /* In certain situations, when the window manager follows a
4589 click-to-focus policy, there seems to be no way around calling
4590 XSetInputFocus to give another frame the input focus .
4592 In an ideal world, XSetInputFocus should generally be avoided so
4593 that applications don't interfere with the window manager's focus
4594 policy. But I think it's okay to use when it's clearly done
4595 following a user-command. */
4597 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4598 doc: /* Set the input focus to FRAME.
4599 FRAME nil means use the selected frame. */)
4600 (frame)
4601 Lisp_Object frame;
4603 struct frame *f = check_x_frame (frame);
4604 Display *dpy = FRAME_X_DISPLAY (f);
4605 int count;
4607 BLOCK_INPUT;
4608 count = x_catch_errors (dpy);
4609 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4610 RevertToParent, CurrentTime);
4611 x_uncatch_errors (dpy, count);
4612 UNBLOCK_INPUT;
4614 return Qnil;
4618 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4619 doc: /* Internal function called by `color-defined-p', which see. */)
4620 (color, frame)
4621 Lisp_Object color, frame;
4623 XColor foo;
4624 FRAME_PTR f = check_x_frame (frame);
4626 CHECK_STRING (color);
4628 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4629 return Qt;
4630 else
4631 return Qnil;
4634 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4635 doc: /* Internal function called by `color-values', which see. */)
4636 (color, frame)
4637 Lisp_Object color, frame;
4639 XColor foo;
4640 FRAME_PTR f = check_x_frame (frame);
4642 CHECK_STRING (color);
4644 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4646 Lisp_Object rgb[3];
4648 rgb[0] = make_number (foo.red);
4649 rgb[1] = make_number (foo.green);
4650 rgb[2] = make_number (foo.blue);
4651 return Flist (3, rgb);
4653 else
4654 return Qnil;
4657 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4658 doc: /* Internal function called by `display-color-p', which see. */)
4659 (display)
4660 Lisp_Object display;
4662 struct x_display_info *dpyinfo = check_x_display_info (display);
4664 if (dpyinfo->n_planes <= 2)
4665 return Qnil;
4667 switch (dpyinfo->visual->class)
4669 case StaticColor:
4670 case PseudoColor:
4671 case TrueColor:
4672 case DirectColor:
4673 return Qt;
4675 default:
4676 return Qnil;
4680 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4681 0, 1, 0,
4682 doc: /* Return t if the X display supports shades of gray.
4683 Note that color displays do support shades of gray.
4684 The optional argument DISPLAY specifies which display to ask about.
4685 DISPLAY should be either a frame or a display name (a string).
4686 If omitted or nil, that stands for the selected frame's display. */)
4687 (display)
4688 Lisp_Object display;
4690 struct x_display_info *dpyinfo = check_x_display_info (display);
4692 if (dpyinfo->n_planes <= 1)
4693 return Qnil;
4695 switch (dpyinfo->visual->class)
4697 case StaticColor:
4698 case PseudoColor:
4699 case TrueColor:
4700 case DirectColor:
4701 case StaticGray:
4702 case GrayScale:
4703 return Qt;
4705 default:
4706 return Qnil;
4710 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4711 0, 1, 0,
4712 doc: /* Returns the width in pixels of the X display DISPLAY.
4713 The optional argument DISPLAY specifies which display to ask about.
4714 DISPLAY should be either a frame or a display name (a string).
4715 If omitted or nil, that stands for the selected frame's display. */)
4716 (display)
4717 Lisp_Object display;
4719 struct x_display_info *dpyinfo = check_x_display_info (display);
4721 return make_number (dpyinfo->width);
4724 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4725 Sx_display_pixel_height, 0, 1, 0,
4726 doc: /* Returns the height in pixels of the X display DISPLAY.
4727 The optional argument DISPLAY specifies which display to ask about.
4728 DISPLAY should be either a frame or a display name (a string).
4729 If omitted or nil, that stands for the selected frame's display. */)
4730 (display)
4731 Lisp_Object display;
4733 struct x_display_info *dpyinfo = check_x_display_info (display);
4735 return make_number (dpyinfo->height);
4738 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4739 0, 1, 0,
4740 doc: /* Returns the number of bitplanes of the X display DISPLAY.
4741 The optional argument DISPLAY specifies which display to ask about.
4742 DISPLAY should be either a frame or a display name (a string).
4743 If omitted or nil, that stands for the selected frame's display. */)
4744 (display)
4745 Lisp_Object display;
4747 struct x_display_info *dpyinfo = check_x_display_info (display);
4749 return make_number (dpyinfo->n_planes);
4752 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4753 0, 1, 0,
4754 doc: /* Returns the number of color cells of the X display DISPLAY.
4755 The optional argument DISPLAY specifies which display to ask about.
4756 DISPLAY should be either a frame or a display name (a string).
4757 If omitted or nil, that stands for the selected frame's display. */)
4758 (display)
4759 Lisp_Object display;
4761 struct x_display_info *dpyinfo = check_x_display_info (display);
4763 return make_number (DisplayCells (dpyinfo->display,
4764 XScreenNumberOfScreen (dpyinfo->screen)));
4767 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4768 Sx_server_max_request_size,
4769 0, 1, 0,
4770 doc: /* Returns the maximum request size of the X server of display DISPLAY.
4771 The optional argument DISPLAY specifies which display to ask about.
4772 DISPLAY should be either a frame or a display name (a string).
4773 If omitted or nil, that stands for the selected frame's display. */)
4774 (display)
4775 Lisp_Object display;
4777 struct x_display_info *dpyinfo = check_x_display_info (display);
4779 return make_number (MAXREQUEST (dpyinfo->display));
4782 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4783 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
4784 The optional argument DISPLAY specifies which display to ask about.
4785 DISPLAY should be either a frame or a display name (a string).
4786 If omitted or nil, that stands for the selected frame's display. */)
4787 (display)
4788 Lisp_Object display;
4790 struct x_display_info *dpyinfo = check_x_display_info (display);
4791 char *vendor = ServerVendor (dpyinfo->display);
4793 if (! vendor) vendor = "";
4794 return build_string (vendor);
4797 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4798 doc: /* Returns the version numbers of the X server of display DISPLAY.
4799 The value is a list of three integers: the major and minor
4800 version numbers of the X Protocol in use, and the vendor-specific release
4801 number. See also the function `x-server-vendor'.
4803 The optional argument DISPLAY specifies which display to ask about.
4804 DISPLAY should be either a frame or a display name (a string).
4805 If omitted or nil, that stands for the selected frame's display. */)
4806 (display)
4807 Lisp_Object display;
4809 struct x_display_info *dpyinfo = check_x_display_info (display);
4810 Display *dpy = dpyinfo->display;
4812 return Fcons (make_number (ProtocolVersion (dpy)),
4813 Fcons (make_number (ProtocolRevision (dpy)),
4814 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4817 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4818 doc: /* Return the number of screens on the X server of display DISPLAY.
4819 The optional argument DISPLAY specifies which display to ask about.
4820 DISPLAY should be either a frame or a display name (a string).
4821 If omitted or nil, that stands for the selected frame's display. */)
4822 (display)
4823 Lisp_Object display;
4825 struct x_display_info *dpyinfo = check_x_display_info (display);
4827 return make_number (ScreenCount (dpyinfo->display));
4830 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4831 doc: /* Return the height in millimeters of the X display DISPLAY.
4832 The optional argument DISPLAY specifies which display to ask about.
4833 DISPLAY should be either a frame or a display name (a string).
4834 If omitted or nil, that stands for the selected frame's display. */)
4835 (display)
4836 Lisp_Object display;
4838 struct x_display_info *dpyinfo = check_x_display_info (display);
4840 return make_number (HeightMMOfScreen (dpyinfo->screen));
4843 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4844 doc: /* Return the width in millimeters of the X display DISPLAY.
4845 The optional argument DISPLAY specifies which display to ask about.
4846 DISPLAY should be either a frame or a display name (a string).
4847 If omitted or nil, that stands for the selected frame's display. */)
4848 (display)
4849 Lisp_Object display;
4851 struct x_display_info *dpyinfo = check_x_display_info (display);
4853 return make_number (WidthMMOfScreen (dpyinfo->screen));
4856 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4857 Sx_display_backing_store, 0, 1, 0,
4858 doc: /* Returns an indication of whether X display DISPLAY does backing store.
4859 The value may be `always', `when-mapped', or `not-useful'.
4860 The optional argument DISPLAY specifies which display to ask about.
4861 DISPLAY should be either a frame or a display name (a string).
4862 If omitted or nil, that stands for the selected frame's display. */)
4863 (display)
4864 Lisp_Object display;
4866 struct x_display_info *dpyinfo = check_x_display_info (display);
4867 Lisp_Object result;
4869 switch (DoesBackingStore (dpyinfo->screen))
4871 case Always:
4872 result = intern ("always");
4873 break;
4875 case WhenMapped:
4876 result = intern ("when-mapped");
4877 break;
4879 case NotUseful:
4880 result = intern ("not-useful");
4881 break;
4883 default:
4884 error ("Strange value for BackingStore parameter of screen");
4885 result = Qnil;
4888 return result;
4891 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4892 Sx_display_visual_class, 0, 1, 0,
4893 doc: /* Return the visual class of the X display DISPLAY.
4894 The value is one of the symbols `static-gray', `gray-scale',
4895 `static-color', `pseudo-color', `true-color', or `direct-color'.
4897 The optional argument DISPLAY specifies which display to ask about.
4898 DISPLAY should be either a frame or a display name (a string).
4899 If omitted or nil, that stands for the selected frame's display. */)
4900 (display)
4901 Lisp_Object display;
4903 struct x_display_info *dpyinfo = check_x_display_info (display);
4904 Lisp_Object result;
4906 switch (dpyinfo->visual->class)
4908 case StaticGray:
4909 result = intern ("static-gray");
4910 break;
4911 case GrayScale:
4912 result = intern ("gray-scale");
4913 break;
4914 case StaticColor:
4915 result = intern ("static-color");
4916 break;
4917 case PseudoColor:
4918 result = intern ("pseudo-color");
4919 break;
4920 case TrueColor:
4921 result = intern ("true-color");
4922 break;
4923 case DirectColor:
4924 result = intern ("direct-color");
4925 break;
4926 default:
4927 error ("Display has an unknown visual class");
4928 result = Qnil;
4931 return result;
4934 DEFUN ("x-display-save-under", Fx_display_save_under,
4935 Sx_display_save_under, 0, 1, 0,
4936 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
4937 The optional argument DISPLAY specifies which display to ask about.
4938 DISPLAY should be either a frame or a display name (a string).
4939 If omitted or nil, that stands for the selected frame's display. */)
4940 (display)
4941 Lisp_Object display;
4943 struct x_display_info *dpyinfo = check_x_display_info (display);
4945 if (DoesSaveUnders (dpyinfo->screen) == True)
4946 return Qt;
4947 else
4948 return Qnil;
4952 x_pixel_width (f)
4953 register struct frame *f;
4955 return PIXEL_WIDTH (f);
4959 x_pixel_height (f)
4960 register struct frame *f;
4962 return PIXEL_HEIGHT (f);
4966 x_char_width (f)
4967 register struct frame *f;
4969 return FONT_WIDTH (f->output_data.x->font);
4973 x_char_height (f)
4974 register struct frame *f;
4976 return f->output_data.x->line_height;
4980 x_screen_planes (f)
4981 register struct frame *f;
4983 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4988 /************************************************************************
4989 X Displays
4990 ************************************************************************/
4993 /* Mapping visual names to visuals. */
4995 static struct visual_class
4997 char *name;
4998 int class;
5000 visual_classes[] =
5002 {"StaticGray", StaticGray},
5003 {"GrayScale", GrayScale},
5004 {"StaticColor", StaticColor},
5005 {"PseudoColor", PseudoColor},
5006 {"TrueColor", TrueColor},
5007 {"DirectColor", DirectColor},
5008 {NULL, 0}
5012 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5014 /* Value is the screen number of screen SCR. This is a substitute for
5015 the X function with the same name when that doesn't exist. */
5018 XScreenNumberOfScreen (scr)
5019 register Screen *scr;
5021 Display *dpy = scr->display;
5022 int i;
5024 for (i = 0; i < dpy->nscreens; ++i)
5025 if (scr == dpy->screens + i)
5026 break;
5028 return i;
5031 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5034 /* Select the visual that should be used on display DPYINFO. Set
5035 members of DPYINFO appropriately. Called from x_term_init. */
5037 void
5038 select_visual (dpyinfo)
5039 struct x_display_info *dpyinfo;
5041 Display *dpy = dpyinfo->display;
5042 Screen *screen = dpyinfo->screen;
5043 Lisp_Object value;
5045 /* See if a visual is specified. */
5046 value = display_x_get_resource (dpyinfo,
5047 build_string ("visualClass"),
5048 build_string ("VisualClass"),
5049 Qnil, Qnil);
5050 if (STRINGP (value))
5052 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5053 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5054 depth, a decimal number. NAME is compared with case ignored. */
5055 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
5056 char *dash;
5057 int i, class = -1;
5058 XVisualInfo vinfo;
5060 strcpy (s, XSTRING (value)->data);
5061 dash = index (s, '-');
5062 if (dash)
5064 dpyinfo->n_planes = atoi (dash + 1);
5065 *dash = '\0';
5067 else
5068 /* We won't find a matching visual with depth 0, so that
5069 an error will be printed below. */
5070 dpyinfo->n_planes = 0;
5072 /* Determine the visual class. */
5073 for (i = 0; visual_classes[i].name; ++i)
5074 if (xstricmp (s, visual_classes[i].name) == 0)
5076 class = visual_classes[i].class;
5077 break;
5080 /* Look up a matching visual for the specified class. */
5081 if (class == -1
5082 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5083 dpyinfo->n_planes, class, &vinfo))
5084 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
5086 dpyinfo->visual = vinfo.visual;
5088 else
5090 int n_visuals;
5091 XVisualInfo *vinfo, vinfo_template;
5093 dpyinfo->visual = DefaultVisualOfScreen (screen);
5095 #ifdef HAVE_X11R4
5096 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5097 #else
5098 vinfo_template.visualid = dpyinfo->visual->visualid;
5099 #endif
5100 vinfo_template.screen = XScreenNumberOfScreen (screen);
5101 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5102 &vinfo_template, &n_visuals);
5103 if (n_visuals != 1)
5104 fatal ("Can't get proper X visual info");
5106 dpyinfo->n_planes = vinfo->depth;
5107 XFree ((char *) vinfo);
5112 /* Return the X display structure for the display named NAME.
5113 Open a new connection if necessary. */
5115 struct x_display_info *
5116 x_display_info_for_name (name)
5117 Lisp_Object name;
5119 Lisp_Object names;
5120 struct x_display_info *dpyinfo;
5122 CHECK_STRING (name);
5124 if (! EQ (Vwindow_system, intern ("x")))
5125 error ("Not using X Windows");
5127 for (dpyinfo = x_display_list, names = x_display_name_list;
5128 dpyinfo;
5129 dpyinfo = dpyinfo->next, names = XCDR (names))
5131 Lisp_Object tem;
5132 tem = Fstring_equal (XCAR (XCAR (names)), name);
5133 if (!NILP (tem))
5134 return dpyinfo;
5137 /* Use this general default value to start with. */
5138 Vx_resource_name = Vinvocation_name;
5140 validate_x_resource_name ();
5142 dpyinfo = x_term_init (name, (char *)0,
5143 (char *) XSTRING (Vx_resource_name)->data);
5145 if (dpyinfo == 0)
5146 error ("Cannot connect to X server %s", XSTRING (name)->data);
5148 x_in_use = 1;
5149 XSETFASTINT (Vwindow_system_version, 11);
5151 return dpyinfo;
5155 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5156 1, 3, 0,
5157 doc: /* Open a connection to an X server.
5158 DISPLAY is the name of the display to connect to.
5159 Optional second arg XRM-STRING is a string of resources in xrdb format.
5160 If the optional third arg MUST-SUCCEED is non-nil,
5161 terminate Emacs if we can't open the connection. */)
5162 (display, xrm_string, must_succeed)
5163 Lisp_Object display, xrm_string, must_succeed;
5165 unsigned char *xrm_option;
5166 struct x_display_info *dpyinfo;
5168 CHECK_STRING (display);
5169 if (! NILP (xrm_string))
5170 CHECK_STRING (xrm_string);
5172 if (! EQ (Vwindow_system, intern ("x")))
5173 error ("Not using X Windows");
5175 if (! NILP (xrm_string))
5176 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5177 else
5178 xrm_option = (unsigned char *) 0;
5180 validate_x_resource_name ();
5182 /* This is what opens the connection and sets x_current_display.
5183 This also initializes many symbols, such as those used for input. */
5184 dpyinfo = x_term_init (display, xrm_option,
5185 (char *) XSTRING (Vx_resource_name)->data);
5187 if (dpyinfo == 0)
5189 if (!NILP (must_succeed))
5190 fatal ("Cannot connect to X server %s.\n\
5191 Check the DISPLAY environment variable or use `-d'.\n\
5192 Also use the `xhost' program to verify that it is set to permit\n\
5193 connections from your machine.\n",
5194 XSTRING (display)->data);
5195 else
5196 error ("Cannot connect to X server %s", XSTRING (display)->data);
5199 x_in_use = 1;
5201 XSETFASTINT (Vwindow_system_version, 11);
5202 return Qnil;
5205 DEFUN ("x-close-connection", Fx_close_connection,
5206 Sx_close_connection, 1, 1, 0,
5207 doc: /* Close the connection to DISPLAY's X server.
5208 For DISPLAY, specify either a frame or a display name (a string).
5209 If DISPLAY is nil, that stands for the selected frame's display. */)
5210 (display)
5211 Lisp_Object display;
5213 struct x_display_info *dpyinfo = check_x_display_info (display);
5214 int i;
5216 if (dpyinfo->reference_count > 0)
5217 error ("Display still has frames on it");
5219 BLOCK_INPUT;
5220 /* Free the fonts in the font table. */
5221 for (i = 0; i < dpyinfo->n_fonts; i++)
5222 if (dpyinfo->font_table[i].name)
5224 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5225 xfree (dpyinfo->font_table[i].full_name);
5226 xfree (dpyinfo->font_table[i].name);
5227 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5230 x_destroy_all_bitmaps (dpyinfo);
5231 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5233 #ifdef USE_X_TOOLKIT
5234 XtCloseDisplay (dpyinfo->display);
5235 #else
5236 XCloseDisplay (dpyinfo->display);
5237 #endif
5239 x_delete_display (dpyinfo);
5240 UNBLOCK_INPUT;
5242 return Qnil;
5245 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5246 doc: /* Return the list of display names that Emacs has connections to. */)
5249 Lisp_Object tail, result;
5251 result = Qnil;
5252 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5253 result = Fcons (XCAR (XCAR (tail)), result);
5255 return result;
5258 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5259 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5260 If ON is nil, allow buffering of requests.
5261 Turning on synchronization prohibits the Xlib routines from buffering
5262 requests and seriously degrades performance, but makes debugging much
5263 easier.
5264 The optional second argument DISPLAY specifies which display to act on.
5265 DISPLAY should be either a frame or a display name (a string).
5266 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5267 (on, display)
5268 Lisp_Object display, on;
5270 struct x_display_info *dpyinfo = check_x_display_info (display);
5272 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5274 return Qnil;
5277 /* Wait for responses to all X commands issued so far for frame F. */
5279 void
5280 x_sync (f)
5281 FRAME_PTR f;
5283 BLOCK_INPUT;
5284 XSync (FRAME_X_DISPLAY (f), False);
5285 UNBLOCK_INPUT;
5289 /***********************************************************************
5290 Image types
5291 ***********************************************************************/
5293 /* Value is the number of elements of vector VECTOR. */
5295 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5297 /* List of supported image types. Use define_image_type to add new
5298 types. Use lookup_image_type to find a type for a given symbol. */
5300 static struct image_type *image_types;
5302 /* The symbol `image' which is the car of the lists used to represent
5303 images in Lisp. */
5305 extern Lisp_Object Qimage;
5307 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5309 Lisp_Object Qxbm;
5311 /* Keywords. */
5313 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5314 extern Lisp_Object QCdata;
5315 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5316 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5317 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5319 /* Other symbols. */
5321 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5323 /* Time in seconds after which images should be removed from the cache
5324 if not displayed. */
5326 Lisp_Object Vimage_cache_eviction_delay;
5328 /* Function prototypes. */
5330 static void define_image_type P_ ((struct image_type *type));
5331 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5332 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5333 static void x_laplace P_ ((struct frame *, struct image *));
5334 static void x_emboss P_ ((struct frame *, struct image *));
5335 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5336 Lisp_Object));
5339 /* Define a new image type from TYPE. This adds a copy of TYPE to
5340 image_types and adds the symbol *TYPE->type to Vimage_types. */
5342 static void
5343 define_image_type (type)
5344 struct image_type *type;
5346 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5347 The initialized data segment is read-only. */
5348 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5349 bcopy (type, p, sizeof *p);
5350 p->next = image_types;
5351 image_types = p;
5352 Vimage_types = Fcons (*p->type, Vimage_types);
5356 /* Look up image type SYMBOL, and return a pointer to its image_type
5357 structure. Value is null if SYMBOL is not a known image type. */
5359 static INLINE struct image_type *
5360 lookup_image_type (symbol)
5361 Lisp_Object symbol;
5363 struct image_type *type;
5365 for (type = image_types; type; type = type->next)
5366 if (EQ (symbol, *type->type))
5367 break;
5369 return type;
5373 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5374 valid image specification is a list whose car is the symbol
5375 `image', and whose rest is a property list. The property list must
5376 contain a value for key `:type'. That value must be the name of a
5377 supported image type. The rest of the property list depends on the
5378 image type. */
5381 valid_image_p (object)
5382 Lisp_Object object;
5384 int valid_p = 0;
5386 if (CONSP (object) && EQ (XCAR (object), Qimage))
5388 Lisp_Object tem;
5390 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5391 if (EQ (XCAR (tem), QCtype))
5393 tem = XCDR (tem);
5394 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5396 struct image_type *type;
5397 type = lookup_image_type (XCAR (tem));
5398 if (type)
5399 valid_p = type->valid_p (object);
5402 break;
5406 return valid_p;
5410 /* Log error message with format string FORMAT and argument ARG.
5411 Signaling an error, e.g. when an image cannot be loaded, is not a
5412 good idea because this would interrupt redisplay, and the error
5413 message display would lead to another redisplay. This function
5414 therefore simply displays a message. */
5416 static void
5417 image_error (format, arg1, arg2)
5418 char *format;
5419 Lisp_Object arg1, arg2;
5421 add_to_log (format, arg1, arg2);
5426 /***********************************************************************
5427 Image specifications
5428 ***********************************************************************/
5430 enum image_value_type
5432 IMAGE_DONT_CHECK_VALUE_TYPE,
5433 IMAGE_STRING_VALUE,
5434 IMAGE_STRING_OR_NIL_VALUE,
5435 IMAGE_SYMBOL_VALUE,
5436 IMAGE_POSITIVE_INTEGER_VALUE,
5437 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5438 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5439 IMAGE_ASCENT_VALUE,
5440 IMAGE_INTEGER_VALUE,
5441 IMAGE_FUNCTION_VALUE,
5442 IMAGE_NUMBER_VALUE,
5443 IMAGE_BOOL_VALUE
5446 /* Structure used when parsing image specifications. */
5448 struct image_keyword
5450 /* Name of keyword. */
5451 char *name;
5453 /* The type of value allowed. */
5454 enum image_value_type type;
5456 /* Non-zero means key must be present. */
5457 int mandatory_p;
5459 /* Used to recognize duplicate keywords in a property list. */
5460 int count;
5462 /* The value that was found. */
5463 Lisp_Object value;
5467 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5468 int, Lisp_Object));
5469 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5472 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5473 has the format (image KEYWORD VALUE ...). One of the keyword/
5474 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5475 image_keywords structures of size NKEYWORDS describing other
5476 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5478 static int
5479 parse_image_spec (spec, keywords, nkeywords, type)
5480 Lisp_Object spec;
5481 struct image_keyword *keywords;
5482 int nkeywords;
5483 Lisp_Object type;
5485 int i;
5486 Lisp_Object plist;
5488 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5489 return 0;
5491 plist = XCDR (spec);
5492 while (CONSP (plist))
5494 Lisp_Object key, value;
5496 /* First element of a pair must be a symbol. */
5497 key = XCAR (plist);
5498 plist = XCDR (plist);
5499 if (!SYMBOLP (key))
5500 return 0;
5502 /* There must follow a value. */
5503 if (!CONSP (plist))
5504 return 0;
5505 value = XCAR (plist);
5506 plist = XCDR (plist);
5508 /* Find key in KEYWORDS. Error if not found. */
5509 for (i = 0; i < nkeywords; ++i)
5510 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5511 break;
5513 if (i == nkeywords)
5514 continue;
5516 /* Record that we recognized the keyword. If a keywords
5517 was found more than once, it's an error. */
5518 keywords[i].value = value;
5519 ++keywords[i].count;
5521 if (keywords[i].count > 1)
5522 return 0;
5524 /* Check type of value against allowed type. */
5525 switch (keywords[i].type)
5527 case IMAGE_STRING_VALUE:
5528 if (!STRINGP (value))
5529 return 0;
5530 break;
5532 case IMAGE_STRING_OR_NIL_VALUE:
5533 if (!STRINGP (value) && !NILP (value))
5534 return 0;
5535 break;
5537 case IMAGE_SYMBOL_VALUE:
5538 if (!SYMBOLP (value))
5539 return 0;
5540 break;
5542 case IMAGE_POSITIVE_INTEGER_VALUE:
5543 if (!INTEGERP (value) || XINT (value) <= 0)
5544 return 0;
5545 break;
5547 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5548 if (INTEGERP (value) && XINT (value) >= 0)
5549 break;
5550 if (CONSP (value)
5551 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5552 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5553 break;
5554 return 0;
5556 case IMAGE_ASCENT_VALUE:
5557 if (SYMBOLP (value) && EQ (value, Qcenter))
5558 break;
5559 else if (INTEGERP (value)
5560 && XINT (value) >= 0
5561 && XINT (value) <= 100)
5562 break;
5563 return 0;
5565 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5566 if (!INTEGERP (value) || XINT (value) < 0)
5567 return 0;
5568 break;
5570 case IMAGE_DONT_CHECK_VALUE_TYPE:
5571 break;
5573 case IMAGE_FUNCTION_VALUE:
5574 value = indirect_function (value);
5575 if (SUBRP (value)
5576 || COMPILEDP (value)
5577 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5578 break;
5579 return 0;
5581 case IMAGE_NUMBER_VALUE:
5582 if (!INTEGERP (value) && !FLOATP (value))
5583 return 0;
5584 break;
5586 case IMAGE_INTEGER_VALUE:
5587 if (!INTEGERP (value))
5588 return 0;
5589 break;
5591 case IMAGE_BOOL_VALUE:
5592 if (!NILP (value) && !EQ (value, Qt))
5593 return 0;
5594 break;
5596 default:
5597 abort ();
5598 break;
5601 if (EQ (key, QCtype) && !EQ (type, value))
5602 return 0;
5605 /* Check that all mandatory fields are present. */
5606 for (i = 0; i < nkeywords; ++i)
5607 if (keywords[i].mandatory_p && keywords[i].count == 0)
5608 return 0;
5610 return NILP (plist);
5614 /* Return the value of KEY in image specification SPEC. Value is nil
5615 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5616 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5618 static Lisp_Object
5619 image_spec_value (spec, key, found)
5620 Lisp_Object spec, key;
5621 int *found;
5623 Lisp_Object tail;
5625 xassert (valid_image_p (spec));
5627 for (tail = XCDR (spec);
5628 CONSP (tail) && CONSP (XCDR (tail));
5629 tail = XCDR (XCDR (tail)))
5631 if (EQ (XCAR (tail), key))
5633 if (found)
5634 *found = 1;
5635 return XCAR (XCDR (tail));
5639 if (found)
5640 *found = 0;
5641 return Qnil;
5645 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5646 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5647 PIXELS non-nil means return the size in pixels, otherwise return the
5648 size in canonical character units.
5649 FRAME is the frame on which the image will be displayed. FRAME nil
5650 or omitted means use the selected frame. */)
5651 (spec, pixels, frame)
5652 Lisp_Object spec, pixels, frame;
5654 Lisp_Object size;
5656 size = Qnil;
5657 if (valid_image_p (spec))
5659 struct frame *f = check_x_frame (frame);
5660 int id = lookup_image (f, spec);
5661 struct image *img = IMAGE_FROM_ID (f, id);
5662 int width = img->width + 2 * img->hmargin;
5663 int height = img->height + 2 * img->vmargin;
5665 if (NILP (pixels))
5666 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5667 make_float ((double) height / CANON_Y_UNIT (f)));
5668 else
5669 size = Fcons (make_number (width), make_number (height));
5671 else
5672 error ("Invalid image specification");
5674 return size;
5678 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5679 doc: /* Return t if image SPEC has a mask bitmap.
5680 FRAME is the frame on which the image will be displayed. FRAME nil
5681 or omitted means use the selected frame. */)
5682 (spec, frame)
5683 Lisp_Object spec, frame;
5685 Lisp_Object mask;
5687 mask = Qnil;
5688 if (valid_image_p (spec))
5690 struct frame *f = check_x_frame (frame);
5691 int id = lookup_image (f, spec);
5692 struct image *img = IMAGE_FROM_ID (f, id);
5693 if (img->mask)
5694 mask = Qt;
5696 else
5697 error ("Invalid image specification");
5699 return mask;
5704 /***********************************************************************
5705 Image type independent image structures
5706 ***********************************************************************/
5708 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5709 static void free_image P_ ((struct frame *f, struct image *img));
5712 /* Allocate and return a new image structure for image specification
5713 SPEC. SPEC has a hash value of HASH. */
5715 static struct image *
5716 make_image (spec, hash)
5717 Lisp_Object spec;
5718 unsigned hash;
5720 struct image *img = (struct image *) xmalloc (sizeof *img);
5722 xassert (valid_image_p (spec));
5723 bzero (img, sizeof *img);
5724 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5725 xassert (img->type != NULL);
5726 img->spec = spec;
5727 img->data.lisp_val = Qnil;
5728 img->ascent = DEFAULT_IMAGE_ASCENT;
5729 img->hash = hash;
5730 return img;
5734 /* Free image IMG which was used on frame F, including its resources. */
5736 static void
5737 free_image (f, img)
5738 struct frame *f;
5739 struct image *img;
5741 if (img)
5743 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5745 /* Remove IMG from the hash table of its cache. */
5746 if (img->prev)
5747 img->prev->next = img->next;
5748 else
5749 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5751 if (img->next)
5752 img->next->prev = img->prev;
5754 c->images[img->id] = NULL;
5756 /* Free resources, then free IMG. */
5757 img->type->free (f, img);
5758 xfree (img);
5763 /* Prepare image IMG for display on frame F. Must be called before
5764 drawing an image. */
5766 void
5767 prepare_image_for_display (f, img)
5768 struct frame *f;
5769 struct image *img;
5771 EMACS_TIME t;
5773 /* We're about to display IMG, so set its timestamp to `now'. */
5774 EMACS_GET_TIME (t);
5775 img->timestamp = EMACS_SECS (t);
5777 /* If IMG doesn't have a pixmap yet, load it now, using the image
5778 type dependent loader function. */
5779 if (img->pixmap == None && !img->load_failed_p)
5780 img->load_failed_p = img->type->load (f, img) == 0;
5784 /* Value is the number of pixels for the ascent of image IMG when
5785 drawn in face FACE. */
5788 image_ascent (img, face)
5789 struct image *img;
5790 struct face *face;
5792 int height = img->height + img->vmargin;
5793 int ascent;
5795 if (img->ascent == CENTERED_IMAGE_ASCENT)
5797 if (face->font)
5798 /* This expression is arranged so that if the image can't be
5799 exactly centered, it will be moved slightly up. This is
5800 because a typical font is `top-heavy' (due to the presence
5801 uppercase letters), so the image placement should err towards
5802 being top-heavy too. It also just generally looks better. */
5803 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5804 else
5805 ascent = height / 2;
5807 else
5808 ascent = height * img->ascent / 100.0;
5810 return ascent;
5814 /* Image background colors. */
5816 static unsigned long
5817 four_corners_best (ximg, width, height)
5818 XImage *ximg;
5819 unsigned long width, height;
5821 unsigned long corners[4], best;
5822 int i, best_count;
5824 /* Get the colors at the corners of ximg. */
5825 corners[0] = XGetPixel (ximg, 0, 0);
5826 corners[1] = XGetPixel (ximg, width - 1, 0);
5827 corners[2] = XGetPixel (ximg, width - 1, height - 1);
5828 corners[3] = XGetPixel (ximg, 0, height - 1);
5830 /* Choose the most frequently found color as background. */
5831 for (i = best_count = 0; i < 4; ++i)
5833 int j, n;
5835 for (j = n = 0; j < 4; ++j)
5836 if (corners[i] == corners[j])
5837 ++n;
5839 if (n > best_count)
5840 best = corners[i], best_count = n;
5843 return best;
5846 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5847 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5848 object to use for the heuristic. */
5850 unsigned long
5851 image_background (img, f, ximg)
5852 struct image *img;
5853 struct frame *f;
5854 XImage *ximg;
5856 if (! img->background_valid)
5857 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5859 int free_ximg = !ximg;
5861 if (! ximg)
5862 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5863 0, 0, img->width, img->height, ~0, ZPixmap);
5865 img->background = four_corners_best (ximg, img->width, img->height);
5867 if (free_ximg)
5868 XDestroyImage (ximg);
5870 img->background_valid = 1;
5873 return img->background;
5876 /* Return the `background_transparent' field of IMG. If IMG doesn't
5877 have one yet, it is guessed heuristically. If non-zero, MASK is an
5878 existing XImage object to use for the heuristic. */
5881 image_background_transparent (img, f, mask)
5882 struct image *img;
5883 struct frame *f;
5884 XImage *mask;
5886 if (! img->background_transparent_valid)
5887 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5889 if (img->mask)
5891 int free_mask = !mask;
5893 if (! mask)
5894 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
5895 0, 0, img->width, img->height, ~0, ZPixmap);
5897 img->background_transparent
5898 = !four_corners_best (mask, img->width, img->height);
5900 if (free_mask)
5901 XDestroyImage (mask);
5903 else
5904 img->background_transparent = 0;
5906 img->background_transparent_valid = 1;
5909 return img->background_transparent;
5913 /***********************************************************************
5914 Helper functions for X image types
5915 ***********************************************************************/
5917 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5918 int, int));
5919 static void x_clear_image P_ ((struct frame *f, struct image *img));
5920 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5921 struct image *img,
5922 Lisp_Object color_name,
5923 unsigned long dflt));
5926 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5927 free the pixmap if any. MASK_P non-zero means clear the mask
5928 pixmap if any. COLORS_P non-zero means free colors allocated for
5929 the image, if any. */
5931 static void
5932 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5933 struct frame *f;
5934 struct image *img;
5935 int pixmap_p, mask_p, colors_p;
5937 if (pixmap_p && img->pixmap)
5939 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5940 img->pixmap = None;
5941 img->background_valid = 0;
5944 if (mask_p && img->mask)
5946 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5947 img->mask = None;
5948 img->background_transparent_valid = 0;
5951 if (colors_p && img->ncolors)
5953 x_free_colors (f, img->colors, img->ncolors);
5954 xfree (img->colors);
5955 img->colors = NULL;
5956 img->ncolors = 0;
5960 /* Free X resources of image IMG which is used on frame F. */
5962 static void
5963 x_clear_image (f, img)
5964 struct frame *f;
5965 struct image *img;
5967 BLOCK_INPUT;
5968 x_clear_image_1 (f, img, 1, 1, 1);
5969 UNBLOCK_INPUT;
5973 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5974 cannot be allocated, use DFLT. Add a newly allocated color to
5975 IMG->colors, so that it can be freed again. Value is the pixel
5976 color. */
5978 static unsigned long
5979 x_alloc_image_color (f, img, color_name, dflt)
5980 struct frame *f;
5981 struct image *img;
5982 Lisp_Object color_name;
5983 unsigned long dflt;
5985 XColor color;
5986 unsigned long result;
5988 xassert (STRINGP (color_name));
5990 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5992 /* This isn't called frequently so we get away with simply
5993 reallocating the color vector to the needed size, here. */
5994 ++img->ncolors;
5995 img->colors =
5996 (unsigned long *) xrealloc (img->colors,
5997 img->ncolors * sizeof *img->colors);
5998 img->colors[img->ncolors - 1] = color.pixel;
5999 result = color.pixel;
6001 else
6002 result = dflt;
6004 return result;
6009 /***********************************************************************
6010 Image Cache
6011 ***********************************************************************/
6013 static void cache_image P_ ((struct frame *f, struct image *img));
6014 static void postprocess_image P_ ((struct frame *, struct image *));
6017 /* Return a new, initialized image cache that is allocated from the
6018 heap. Call free_image_cache to free an image cache. */
6020 struct image_cache *
6021 make_image_cache ()
6023 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
6024 int size;
6026 bzero (c, sizeof *c);
6027 c->size = 50;
6028 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
6029 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
6030 c->buckets = (struct image **) xmalloc (size);
6031 bzero (c->buckets, size);
6032 return c;
6036 /* Free image cache of frame F. Be aware that X frames share images
6037 caches. */
6039 void
6040 free_image_cache (f)
6041 struct frame *f;
6043 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6044 if (c)
6046 int i;
6048 /* Cache should not be referenced by any frame when freed. */
6049 xassert (c->refcount == 0);
6051 for (i = 0; i < c->used; ++i)
6052 free_image (f, c->images[i]);
6053 xfree (c->images);
6054 xfree (c->buckets);
6055 xfree (c);
6056 FRAME_X_IMAGE_CACHE (f) = NULL;
6061 /* Clear image cache of frame F. FORCE_P non-zero means free all
6062 images. FORCE_P zero means clear only images that haven't been
6063 displayed for some time. Should be called from time to time to
6064 reduce the number of loaded images. If image-eviction-seconds is
6065 non-nil, this frees images in the cache which weren't displayed for
6066 at least that many seconds. */
6068 void
6069 clear_image_cache (f, force_p)
6070 struct frame *f;
6071 int force_p;
6073 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6075 if (c && INTEGERP (Vimage_cache_eviction_delay))
6077 EMACS_TIME t;
6078 unsigned long old;
6079 int i, nfreed;
6081 EMACS_GET_TIME (t);
6082 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
6084 /* Block input so that we won't be interrupted by a SIGIO
6085 while being in an inconsistent state. */
6086 BLOCK_INPUT;
6088 for (i = nfreed = 0; i < c->used; ++i)
6090 struct image *img = c->images[i];
6091 if (img != NULL
6092 && (force_p || img->timestamp < old))
6094 free_image (f, img);
6095 ++nfreed;
6099 /* We may be clearing the image cache because, for example,
6100 Emacs was iconified for a longer period of time. In that
6101 case, current matrices may still contain references to
6102 images freed above. So, clear these matrices. */
6103 if (nfreed)
6105 Lisp_Object tail, frame;
6107 FOR_EACH_FRAME (tail, frame)
6109 struct frame *f = XFRAME (frame);
6110 if (FRAME_X_P (f)
6111 && FRAME_X_IMAGE_CACHE (f) == c)
6112 clear_current_matrices (f);
6115 ++windows_or_buffers_changed;
6118 UNBLOCK_INPUT;
6123 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
6124 0, 1, 0,
6125 doc: /* Clear the image cache of FRAME.
6126 FRAME nil or omitted means use the selected frame.
6127 FRAME t means clear the image caches of all frames. */)
6128 (frame)
6129 Lisp_Object frame;
6131 if (EQ (frame, Qt))
6133 Lisp_Object tail;
6135 FOR_EACH_FRAME (tail, frame)
6136 if (FRAME_X_P (XFRAME (frame)))
6137 clear_image_cache (XFRAME (frame), 1);
6139 else
6140 clear_image_cache (check_x_frame (frame), 1);
6142 return Qnil;
6146 /* Compute masks and transform image IMG on frame F, as specified
6147 by the image's specification, */
6149 static void
6150 postprocess_image (f, img)
6151 struct frame *f;
6152 struct image *img;
6154 /* Manipulation of the image's mask. */
6155 if (img->pixmap)
6157 Lisp_Object conversion, spec;
6158 Lisp_Object mask;
6160 spec = img->spec;
6162 /* `:heuristic-mask t'
6163 `:mask heuristic'
6164 means build a mask heuristically.
6165 `:heuristic-mask (R G B)'
6166 `:mask (heuristic (R G B))'
6167 means build a mask from color (R G B) in the
6168 image.
6169 `:mask nil'
6170 means remove a mask, if any. */
6172 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6173 if (!NILP (mask))
6174 x_build_heuristic_mask (f, img, mask);
6175 else
6177 int found_p;
6179 mask = image_spec_value (spec, QCmask, &found_p);
6181 if (EQ (mask, Qheuristic))
6182 x_build_heuristic_mask (f, img, Qt);
6183 else if (CONSP (mask)
6184 && EQ (XCAR (mask), Qheuristic))
6186 if (CONSP (XCDR (mask)))
6187 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6188 else
6189 x_build_heuristic_mask (f, img, XCDR (mask));
6191 else if (NILP (mask) && found_p && img->mask)
6193 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6194 img->mask = None;
6199 /* Should we apply an image transformation algorithm? */
6200 conversion = image_spec_value (spec, QCconversion, NULL);
6201 if (EQ (conversion, Qdisabled))
6202 x_disable_image (f, img);
6203 else if (EQ (conversion, Qlaplace))
6204 x_laplace (f, img);
6205 else if (EQ (conversion, Qemboss))
6206 x_emboss (f, img);
6207 else if (CONSP (conversion)
6208 && EQ (XCAR (conversion), Qedge_detection))
6210 Lisp_Object tem;
6211 tem = XCDR (conversion);
6212 if (CONSP (tem))
6213 x_edge_detection (f, img,
6214 Fplist_get (tem, QCmatrix),
6215 Fplist_get (tem, QCcolor_adjustment));
6221 /* Return the id of image with Lisp specification SPEC on frame F.
6222 SPEC must be a valid Lisp image specification (see valid_image_p). */
6225 lookup_image (f, spec)
6226 struct frame *f;
6227 Lisp_Object spec;
6229 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6230 struct image *img;
6231 int i;
6232 unsigned hash;
6233 struct gcpro gcpro1;
6234 EMACS_TIME now;
6236 /* F must be a window-system frame, and SPEC must be a valid image
6237 specification. */
6238 xassert (FRAME_WINDOW_P (f));
6239 xassert (valid_image_p (spec));
6241 GCPRO1 (spec);
6243 /* Look up SPEC in the hash table of the image cache. */
6244 hash = sxhash (spec, 0);
6245 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6247 for (img = c->buckets[i]; img; img = img->next)
6248 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6249 break;
6251 /* If not found, create a new image and cache it. */
6252 if (img == NULL)
6254 extern Lisp_Object Qpostscript;
6256 BLOCK_INPUT;
6257 img = make_image (spec, hash);
6258 cache_image (f, img);
6259 img->load_failed_p = img->type->load (f, img) == 0;
6261 /* If we can't load the image, and we don't have a width and
6262 height, use some arbitrary width and height so that we can
6263 draw a rectangle for it. */
6264 if (img->load_failed_p)
6266 Lisp_Object value;
6268 value = image_spec_value (spec, QCwidth, NULL);
6269 img->width = (INTEGERP (value)
6270 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6271 value = image_spec_value (spec, QCheight, NULL);
6272 img->height = (INTEGERP (value)
6273 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6275 else
6277 /* Handle image type independent image attributes
6278 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6279 `:background COLOR'. */
6280 Lisp_Object ascent, margin, relief, bg;
6282 ascent = image_spec_value (spec, QCascent, NULL);
6283 if (INTEGERP (ascent))
6284 img->ascent = XFASTINT (ascent);
6285 else if (EQ (ascent, Qcenter))
6286 img->ascent = CENTERED_IMAGE_ASCENT;
6288 margin = image_spec_value (spec, QCmargin, NULL);
6289 if (INTEGERP (margin) && XINT (margin) >= 0)
6290 img->vmargin = img->hmargin = XFASTINT (margin);
6291 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6292 && INTEGERP (XCDR (margin)))
6294 if (XINT (XCAR (margin)) > 0)
6295 img->hmargin = XFASTINT (XCAR (margin));
6296 if (XINT (XCDR (margin)) > 0)
6297 img->vmargin = XFASTINT (XCDR (margin));
6300 relief = image_spec_value (spec, QCrelief, NULL);
6301 if (INTEGERP (relief))
6303 img->relief = XINT (relief);
6304 img->hmargin += abs (img->relief);
6305 img->vmargin += abs (img->relief);
6308 if (! img->background_valid)
6310 bg = image_spec_value (img->spec, QCbackground, NULL);
6311 if (!NILP (bg))
6313 img->background
6314 = x_alloc_image_color (f, img, bg,
6315 FRAME_BACKGROUND_PIXEL (f));
6316 img->background_valid = 1;
6320 /* Do image transformations and compute masks, unless we
6321 don't have the image yet. */
6322 if (!EQ (*img->type->type, Qpostscript))
6323 postprocess_image (f, img);
6326 UNBLOCK_INPUT;
6327 xassert (!interrupt_input_blocked);
6330 /* We're using IMG, so set its timestamp to `now'. */
6331 EMACS_GET_TIME (now);
6332 img->timestamp = EMACS_SECS (now);
6334 UNGCPRO;
6336 /* Value is the image id. */
6337 return img->id;
6341 /* Cache image IMG in the image cache of frame F. */
6343 static void
6344 cache_image (f, img)
6345 struct frame *f;
6346 struct image *img;
6348 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6349 int i;
6351 /* Find a free slot in c->images. */
6352 for (i = 0; i < c->used; ++i)
6353 if (c->images[i] == NULL)
6354 break;
6356 /* If no free slot found, maybe enlarge c->images. */
6357 if (i == c->used && c->used == c->size)
6359 c->size *= 2;
6360 c->images = (struct image **) xrealloc (c->images,
6361 c->size * sizeof *c->images);
6364 /* Add IMG to c->images, and assign IMG an id. */
6365 c->images[i] = img;
6366 img->id = i;
6367 if (i == c->used)
6368 ++c->used;
6370 /* Add IMG to the cache's hash table. */
6371 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6372 img->next = c->buckets[i];
6373 if (img->next)
6374 img->next->prev = img;
6375 img->prev = NULL;
6376 c->buckets[i] = img;
6380 /* Call FN on every image in the image cache of frame F. Used to mark
6381 Lisp Objects in the image cache. */
6383 void
6384 forall_images_in_image_cache (f, fn)
6385 struct frame *f;
6386 void (*fn) P_ ((struct image *img));
6388 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6390 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6391 if (c)
6393 int i;
6394 for (i = 0; i < c->used; ++i)
6395 if (c->images[i])
6396 fn (c->images[i]);
6403 /***********************************************************************
6404 X support code
6405 ***********************************************************************/
6407 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6408 XImage **, Pixmap *));
6409 static void x_destroy_x_image P_ ((XImage *));
6410 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6413 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6414 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6415 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6416 via xmalloc. Print error messages via image_error if an error
6417 occurs. Value is non-zero if successful. */
6419 static int
6420 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6421 struct frame *f;
6422 int width, height, depth;
6423 XImage **ximg;
6424 Pixmap *pixmap;
6426 Display *display = FRAME_X_DISPLAY (f);
6427 Screen *screen = FRAME_X_SCREEN (f);
6428 Window window = FRAME_X_WINDOW (f);
6430 xassert (interrupt_input_blocked);
6432 if (depth <= 0)
6433 depth = DefaultDepthOfScreen (screen);
6434 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6435 depth, ZPixmap, 0, NULL, width, height,
6436 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6437 if (*ximg == NULL)
6439 image_error ("Unable to allocate X image", Qnil, Qnil);
6440 return 0;
6443 /* Allocate image raster. */
6444 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6446 /* Allocate a pixmap of the same size. */
6447 *pixmap = XCreatePixmap (display, window, width, height, depth);
6448 if (*pixmap == None)
6450 x_destroy_x_image (*ximg);
6451 *ximg = NULL;
6452 image_error ("Unable to create X pixmap", Qnil, Qnil);
6453 return 0;
6456 return 1;
6460 /* Destroy XImage XIMG. Free XIMG->data. */
6462 static void
6463 x_destroy_x_image (ximg)
6464 XImage *ximg;
6466 xassert (interrupt_input_blocked);
6467 if (ximg)
6469 xfree (ximg->data);
6470 ximg->data = NULL;
6471 XDestroyImage (ximg);
6476 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6477 are width and height of both the image and pixmap. */
6479 static void
6480 x_put_x_image (f, ximg, pixmap, width, height)
6481 struct frame *f;
6482 XImage *ximg;
6483 Pixmap pixmap;
6485 GC gc;
6487 xassert (interrupt_input_blocked);
6488 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6489 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6490 XFreeGC (FRAME_X_DISPLAY (f), gc);
6495 /***********************************************************************
6496 File Handling
6497 ***********************************************************************/
6499 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6500 static char *slurp_file P_ ((char *, int *));
6503 /* Find image file FILE. Look in data-directory, then
6504 x-bitmap-file-path. Value is the full name of the file found, or
6505 nil if not found. */
6507 static Lisp_Object
6508 x_find_image_file (file)
6509 Lisp_Object file;
6511 Lisp_Object file_found, search_path;
6512 struct gcpro gcpro1, gcpro2;
6513 int fd;
6515 file_found = Qnil;
6516 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6517 GCPRO2 (file_found, search_path);
6519 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6520 fd = openp (search_path, file, Qnil, &file_found, 0);
6522 if (fd == -1)
6523 file_found = Qnil;
6524 else
6525 close (fd);
6527 UNGCPRO;
6528 return file_found;
6532 /* Read FILE into memory. Value is a pointer to a buffer allocated
6533 with xmalloc holding FILE's contents. Value is null if an error
6534 occurred. *SIZE is set to the size of the file. */
6536 static char *
6537 slurp_file (file, size)
6538 char *file;
6539 int *size;
6541 FILE *fp = NULL;
6542 char *buf = NULL;
6543 struct stat st;
6545 if (stat (file, &st) == 0
6546 && (fp = fopen (file, "r")) != NULL
6547 && (buf = (char *) xmalloc (st.st_size),
6548 fread (buf, 1, st.st_size, fp) == st.st_size))
6550 *size = st.st_size;
6551 fclose (fp);
6553 else
6555 if (fp)
6556 fclose (fp);
6557 if (buf)
6559 xfree (buf);
6560 buf = NULL;
6564 return buf;
6569 /***********************************************************************
6570 XBM images
6571 ***********************************************************************/
6573 static int xbm_scan P_ ((char **, char *, char *, int *));
6574 static int xbm_load P_ ((struct frame *f, struct image *img));
6575 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6576 char *, char *));
6577 static int xbm_image_p P_ ((Lisp_Object object));
6578 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6579 unsigned char **));
6580 static int xbm_file_p P_ ((Lisp_Object));
6583 /* Indices of image specification fields in xbm_format, below. */
6585 enum xbm_keyword_index
6587 XBM_TYPE,
6588 XBM_FILE,
6589 XBM_WIDTH,
6590 XBM_HEIGHT,
6591 XBM_DATA,
6592 XBM_FOREGROUND,
6593 XBM_BACKGROUND,
6594 XBM_ASCENT,
6595 XBM_MARGIN,
6596 XBM_RELIEF,
6597 XBM_ALGORITHM,
6598 XBM_HEURISTIC_MASK,
6599 XBM_MASK,
6600 XBM_LAST
6603 /* Vector of image_keyword structures describing the format
6604 of valid XBM image specifications. */
6606 static struct image_keyword xbm_format[XBM_LAST] =
6608 {":type", IMAGE_SYMBOL_VALUE, 1},
6609 {":file", IMAGE_STRING_VALUE, 0},
6610 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6611 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6612 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6613 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6614 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6615 {":ascent", IMAGE_ASCENT_VALUE, 0},
6616 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6617 {":relief", IMAGE_INTEGER_VALUE, 0},
6618 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6619 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6620 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6623 /* Structure describing the image type XBM. */
6625 static struct image_type xbm_type =
6627 &Qxbm,
6628 xbm_image_p,
6629 xbm_load,
6630 x_clear_image,
6631 NULL
6634 /* Tokens returned from xbm_scan. */
6636 enum xbm_token
6638 XBM_TK_IDENT = 256,
6639 XBM_TK_NUMBER
6643 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6644 A valid specification is a list starting with the symbol `image'
6645 The rest of the list is a property list which must contain an
6646 entry `:type xbm..
6648 If the specification specifies a file to load, it must contain
6649 an entry `:file FILENAME' where FILENAME is a string.
6651 If the specification is for a bitmap loaded from memory it must
6652 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6653 WIDTH and HEIGHT are integers > 0. DATA may be:
6655 1. a string large enough to hold the bitmap data, i.e. it must
6656 have a size >= (WIDTH + 7) / 8 * HEIGHT
6658 2. a bool-vector of size >= WIDTH * HEIGHT
6660 3. a vector of strings or bool-vectors, one for each line of the
6661 bitmap.
6663 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6664 may not be specified in this case because they are defined in the
6665 XBM file.
6667 Both the file and data forms may contain the additional entries
6668 `:background COLOR' and `:foreground COLOR'. If not present,
6669 foreground and background of the frame on which the image is
6670 displayed is used. */
6672 static int
6673 xbm_image_p (object)
6674 Lisp_Object object;
6676 struct image_keyword kw[XBM_LAST];
6678 bcopy (xbm_format, kw, sizeof kw);
6679 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6680 return 0;
6682 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6684 if (kw[XBM_FILE].count)
6686 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6687 return 0;
6689 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6691 /* In-memory XBM file. */
6692 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6693 return 0;
6695 else
6697 Lisp_Object data;
6698 int width, height;
6700 /* Entries for `:width', `:height' and `:data' must be present. */
6701 if (!kw[XBM_WIDTH].count
6702 || !kw[XBM_HEIGHT].count
6703 || !kw[XBM_DATA].count)
6704 return 0;
6706 data = kw[XBM_DATA].value;
6707 width = XFASTINT (kw[XBM_WIDTH].value);
6708 height = XFASTINT (kw[XBM_HEIGHT].value);
6710 /* Check type of data, and width and height against contents of
6711 data. */
6712 if (VECTORP (data))
6714 int i;
6716 /* Number of elements of the vector must be >= height. */
6717 if (XVECTOR (data)->size < height)
6718 return 0;
6720 /* Each string or bool-vector in data must be large enough
6721 for one line of the image. */
6722 for (i = 0; i < height; ++i)
6724 Lisp_Object elt = XVECTOR (data)->contents[i];
6726 if (STRINGP (elt))
6728 if (XSTRING (elt)->size
6729 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6730 return 0;
6732 else if (BOOL_VECTOR_P (elt))
6734 if (XBOOL_VECTOR (elt)->size < width)
6735 return 0;
6737 else
6738 return 0;
6741 else if (STRINGP (data))
6743 if (XSTRING (data)->size
6744 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6745 return 0;
6747 else if (BOOL_VECTOR_P (data))
6749 if (XBOOL_VECTOR (data)->size < width * height)
6750 return 0;
6752 else
6753 return 0;
6756 return 1;
6760 /* Scan a bitmap file. FP is the stream to read from. Value is
6761 either an enumerator from enum xbm_token, or a character for a
6762 single-character token, or 0 at end of file. If scanning an
6763 identifier, store the lexeme of the identifier in SVAL. If
6764 scanning a number, store its value in *IVAL. */
6766 static int
6767 xbm_scan (s, end, sval, ival)
6768 char **s, *end;
6769 char *sval;
6770 int *ival;
6772 int c;
6774 loop:
6776 /* Skip white space. */
6777 while (*s < end && (c = *(*s)++, isspace (c)))
6780 if (*s >= end)
6781 c = 0;
6782 else if (isdigit (c))
6784 int value = 0, digit;
6786 if (c == '0' && *s < end)
6788 c = *(*s)++;
6789 if (c == 'x' || c == 'X')
6791 while (*s < end)
6793 c = *(*s)++;
6794 if (isdigit (c))
6795 digit = c - '0';
6796 else if (c >= 'a' && c <= 'f')
6797 digit = c - 'a' + 10;
6798 else if (c >= 'A' && c <= 'F')
6799 digit = c - 'A' + 10;
6800 else
6801 break;
6802 value = 16 * value + digit;
6805 else if (isdigit (c))
6807 value = c - '0';
6808 while (*s < end
6809 && (c = *(*s)++, isdigit (c)))
6810 value = 8 * value + c - '0';
6813 else
6815 value = c - '0';
6816 while (*s < end
6817 && (c = *(*s)++, isdigit (c)))
6818 value = 10 * value + c - '0';
6821 if (*s < end)
6822 *s = *s - 1;
6823 *ival = value;
6824 c = XBM_TK_NUMBER;
6826 else if (isalpha (c) || c == '_')
6828 *sval++ = c;
6829 while (*s < end
6830 && (c = *(*s)++, (isalnum (c) || c == '_')))
6831 *sval++ = c;
6832 *sval = 0;
6833 if (*s < end)
6834 *s = *s - 1;
6835 c = XBM_TK_IDENT;
6837 else if (c == '/' && **s == '*')
6839 /* C-style comment. */
6840 ++*s;
6841 while (**s && (**s != '*' || *(*s + 1) != '/'))
6842 ++*s;
6843 if (**s)
6845 *s += 2;
6846 goto loop;
6850 return c;
6854 /* Replacement for XReadBitmapFileData which isn't available under old
6855 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6856 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6857 the image. Return in *DATA the bitmap data allocated with xmalloc.
6858 Value is non-zero if successful. DATA null means just test if
6859 CONTENTS looks like an in-memory XBM file. */
6861 static int
6862 xbm_read_bitmap_data (contents, end, width, height, data)
6863 char *contents, *end;
6864 int *width, *height;
6865 unsigned char **data;
6867 char *s = contents;
6868 char buffer[BUFSIZ];
6869 int padding_p = 0;
6870 int v10 = 0;
6871 int bytes_per_line, i, nbytes;
6872 unsigned char *p;
6873 int value;
6874 int LA1;
6876 #define match() \
6877 LA1 = xbm_scan (&s, end, buffer, &value)
6879 #define expect(TOKEN) \
6880 if (LA1 != (TOKEN)) \
6881 goto failure; \
6882 else \
6883 match ()
6885 #define expect_ident(IDENT) \
6886 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6887 match (); \
6888 else \
6889 goto failure
6891 *width = *height = -1;
6892 if (data)
6893 *data = NULL;
6894 LA1 = xbm_scan (&s, end, buffer, &value);
6896 /* Parse defines for width, height and hot-spots. */
6897 while (LA1 == '#')
6899 match ();
6900 expect_ident ("define");
6901 expect (XBM_TK_IDENT);
6903 if (LA1 == XBM_TK_NUMBER);
6905 char *p = strrchr (buffer, '_');
6906 p = p ? p + 1 : buffer;
6907 if (strcmp (p, "width") == 0)
6908 *width = value;
6909 else if (strcmp (p, "height") == 0)
6910 *height = value;
6912 expect (XBM_TK_NUMBER);
6915 if (*width < 0 || *height < 0)
6916 goto failure;
6917 else if (data == NULL)
6918 goto success;
6920 /* Parse bits. Must start with `static'. */
6921 expect_ident ("static");
6922 if (LA1 == XBM_TK_IDENT)
6924 if (strcmp (buffer, "unsigned") == 0)
6926 match ();
6927 expect_ident ("char");
6929 else if (strcmp (buffer, "short") == 0)
6931 match ();
6932 v10 = 1;
6933 if (*width % 16 && *width % 16 < 9)
6934 padding_p = 1;
6936 else if (strcmp (buffer, "char") == 0)
6937 match ();
6938 else
6939 goto failure;
6941 else
6942 goto failure;
6944 expect (XBM_TK_IDENT);
6945 expect ('[');
6946 expect (']');
6947 expect ('=');
6948 expect ('{');
6950 bytes_per_line = (*width + 7) / 8 + padding_p;
6951 nbytes = bytes_per_line * *height;
6952 p = *data = (char *) xmalloc (nbytes);
6954 if (v10)
6956 for (i = 0; i < nbytes; i += 2)
6958 int val = value;
6959 expect (XBM_TK_NUMBER);
6961 *p++ = val;
6962 if (!padding_p || ((i + 2) % bytes_per_line))
6963 *p++ = value >> 8;
6965 if (LA1 == ',' || LA1 == '}')
6966 match ();
6967 else
6968 goto failure;
6971 else
6973 for (i = 0; i < nbytes; ++i)
6975 int val = value;
6976 expect (XBM_TK_NUMBER);
6978 *p++ = val;
6980 if (LA1 == ',' || LA1 == '}')
6981 match ();
6982 else
6983 goto failure;
6987 success:
6988 return 1;
6990 failure:
6992 if (data && *data)
6994 xfree (*data);
6995 *data = NULL;
6997 return 0;
6999 #undef match
7000 #undef expect
7001 #undef expect_ident
7005 /* Load XBM image IMG which will be displayed on frame F from buffer
7006 CONTENTS. END is the end of the buffer. Value is non-zero if
7007 successful. */
7009 static int
7010 xbm_load_image (f, img, contents, end)
7011 struct frame *f;
7012 struct image *img;
7013 char *contents, *end;
7015 int rc;
7016 unsigned char *data;
7017 int success_p = 0;
7019 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
7020 if (rc)
7022 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7023 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7024 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7025 Lisp_Object value;
7027 xassert (img->width > 0 && img->height > 0);
7029 /* Get foreground and background colors, maybe allocate colors. */
7030 value = image_spec_value (img->spec, QCforeground, NULL);
7031 if (!NILP (value))
7032 foreground = x_alloc_image_color (f, img, value, foreground);
7033 value = image_spec_value (img->spec, QCbackground, NULL);
7034 if (!NILP (value))
7036 background = x_alloc_image_color (f, img, value, background);
7037 img->background = background;
7038 img->background_valid = 1;
7041 img->pixmap
7042 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7043 FRAME_X_WINDOW (f),
7044 data,
7045 img->width, img->height,
7046 foreground, background,
7047 depth);
7048 xfree (data);
7050 if (img->pixmap == None)
7052 x_clear_image (f, img);
7053 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
7055 else
7056 success_p = 1;
7058 else
7059 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7061 return success_p;
7065 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7067 static int
7068 xbm_file_p (data)
7069 Lisp_Object data;
7071 int w, h;
7072 return (STRINGP (data)
7073 && xbm_read_bitmap_data (XSTRING (data)->data,
7074 (XSTRING (data)->data
7075 + STRING_BYTES (XSTRING (data))),
7076 &w, &h, NULL));
7080 /* Fill image IMG which is used on frame F with pixmap data. Value is
7081 non-zero if successful. */
7083 static int
7084 xbm_load (f, img)
7085 struct frame *f;
7086 struct image *img;
7088 int success_p = 0;
7089 Lisp_Object file_name;
7091 xassert (xbm_image_p (img->spec));
7093 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7094 file_name = image_spec_value (img->spec, QCfile, NULL);
7095 if (STRINGP (file_name))
7097 Lisp_Object file;
7098 char *contents;
7099 int size;
7100 struct gcpro gcpro1;
7102 file = x_find_image_file (file_name);
7103 GCPRO1 (file);
7104 if (!STRINGP (file))
7106 image_error ("Cannot find image file `%s'", file_name, Qnil);
7107 UNGCPRO;
7108 return 0;
7111 contents = slurp_file (XSTRING (file)->data, &size);
7112 if (contents == NULL)
7114 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7115 UNGCPRO;
7116 return 0;
7119 success_p = xbm_load_image (f, img, contents, contents + size);
7120 UNGCPRO;
7122 else
7124 struct image_keyword fmt[XBM_LAST];
7125 Lisp_Object data;
7126 int depth;
7127 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7128 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7129 char *bits;
7130 int parsed_p;
7131 int in_memory_file_p = 0;
7133 /* See if data looks like an in-memory XBM file. */
7134 data = image_spec_value (img->spec, QCdata, NULL);
7135 in_memory_file_p = xbm_file_p (data);
7137 /* Parse the image specification. */
7138 bcopy (xbm_format, fmt, sizeof fmt);
7139 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
7140 xassert (parsed_p);
7142 /* Get specified width, and height. */
7143 if (!in_memory_file_p)
7145 img->width = XFASTINT (fmt[XBM_WIDTH].value);
7146 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
7147 xassert (img->width > 0 && img->height > 0);
7150 /* Get foreground and background colors, maybe allocate colors. */
7151 if (fmt[XBM_FOREGROUND].count
7152 && STRINGP (fmt[XBM_FOREGROUND].value))
7153 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
7154 foreground);
7155 if (fmt[XBM_BACKGROUND].count
7156 && STRINGP (fmt[XBM_BACKGROUND].value))
7157 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
7158 background);
7160 if (in_memory_file_p)
7161 success_p = xbm_load_image (f, img, XSTRING (data)->data,
7162 (XSTRING (data)->data
7163 + STRING_BYTES (XSTRING (data))));
7164 else
7166 if (VECTORP (data))
7168 int i;
7169 char *p;
7170 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7172 p = bits = (char *) alloca (nbytes * img->height);
7173 for (i = 0; i < img->height; ++i, p += nbytes)
7175 Lisp_Object line = XVECTOR (data)->contents[i];
7176 if (STRINGP (line))
7177 bcopy (XSTRING (line)->data, p, nbytes);
7178 else
7179 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7182 else if (STRINGP (data))
7183 bits = XSTRING (data)->data;
7184 else
7185 bits = XBOOL_VECTOR (data)->data;
7187 /* Create the pixmap. */
7188 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7189 img->pixmap
7190 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7191 FRAME_X_WINDOW (f),
7192 bits,
7193 img->width, img->height,
7194 foreground, background,
7195 depth);
7196 if (img->pixmap)
7197 success_p = 1;
7198 else
7200 image_error ("Unable to create pixmap for XBM image `%s'",
7201 img->spec, Qnil);
7202 x_clear_image (f, img);
7207 return success_p;
7212 /***********************************************************************
7213 XPM images
7214 ***********************************************************************/
7216 #if HAVE_XPM
7218 static int xpm_image_p P_ ((Lisp_Object object));
7219 static int xpm_load P_ ((struct frame *f, struct image *img));
7220 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7222 #include "X11/xpm.h"
7224 /* The symbol `xpm' identifying XPM-format images. */
7226 Lisp_Object Qxpm;
7228 /* Indices of image specification fields in xpm_format, below. */
7230 enum xpm_keyword_index
7232 XPM_TYPE,
7233 XPM_FILE,
7234 XPM_DATA,
7235 XPM_ASCENT,
7236 XPM_MARGIN,
7237 XPM_RELIEF,
7238 XPM_ALGORITHM,
7239 XPM_HEURISTIC_MASK,
7240 XPM_MASK,
7241 XPM_COLOR_SYMBOLS,
7242 XPM_BACKGROUND,
7243 XPM_LAST
7246 /* Vector of image_keyword structures describing the format
7247 of valid XPM image specifications. */
7249 static struct image_keyword xpm_format[XPM_LAST] =
7251 {":type", IMAGE_SYMBOL_VALUE, 1},
7252 {":file", IMAGE_STRING_VALUE, 0},
7253 {":data", IMAGE_STRING_VALUE, 0},
7254 {":ascent", IMAGE_ASCENT_VALUE, 0},
7255 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7256 {":relief", IMAGE_INTEGER_VALUE, 0},
7257 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7258 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7259 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7260 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7261 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7264 /* Structure describing the image type XBM. */
7266 static struct image_type xpm_type =
7268 &Qxpm,
7269 xpm_image_p,
7270 xpm_load,
7271 x_clear_image,
7272 NULL
7276 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7277 functions for allocating image colors. Our own functions handle
7278 color allocation failures more gracefully than the ones on the XPM
7279 lib. */
7281 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7282 #define ALLOC_XPM_COLORS
7283 #endif
7285 #ifdef ALLOC_XPM_COLORS
7287 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7288 static void xpm_free_color_cache P_ ((void));
7289 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7290 static int xpm_color_bucket P_ ((char *));
7291 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7292 XColor *, int));
7294 /* An entry in a hash table used to cache color definitions of named
7295 colors. This cache is necessary to speed up XPM image loading in
7296 case we do color allocations ourselves. Without it, we would need
7297 a call to XParseColor per pixel in the image. */
7299 struct xpm_cached_color
7301 /* Next in collision chain. */
7302 struct xpm_cached_color *next;
7304 /* Color definition (RGB and pixel color). */
7305 XColor color;
7307 /* Color name. */
7308 char name[1];
7311 /* The hash table used for the color cache, and its bucket vector
7312 size. */
7314 #define XPM_COLOR_CACHE_BUCKETS 1001
7315 struct xpm_cached_color **xpm_color_cache;
7317 /* Initialize the color cache. */
7319 static void
7320 xpm_init_color_cache (f, attrs)
7321 struct frame *f;
7322 XpmAttributes *attrs;
7324 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7325 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7326 memset (xpm_color_cache, 0, nbytes);
7327 init_color_table ();
7329 if (attrs->valuemask & XpmColorSymbols)
7331 int i;
7332 XColor color;
7334 for (i = 0; i < attrs->numsymbols; ++i)
7335 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7336 attrs->colorsymbols[i].value, &color))
7338 color.pixel = lookup_rgb_color (f, color.red, color.green,
7339 color.blue);
7340 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7346 /* Free the color cache. */
7348 static void
7349 xpm_free_color_cache ()
7351 struct xpm_cached_color *p, *next;
7352 int i;
7354 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7355 for (p = xpm_color_cache[i]; p; p = next)
7357 next = p->next;
7358 xfree (p);
7361 xfree (xpm_color_cache);
7362 xpm_color_cache = NULL;
7363 free_color_table ();
7367 /* Return the bucket index for color named COLOR_NAME in the color
7368 cache. */
7370 static int
7371 xpm_color_bucket (color_name)
7372 char *color_name;
7374 unsigned h = 0;
7375 char *s;
7377 for (s = color_name; *s; ++s)
7378 h = (h << 2) ^ *s;
7379 return h %= XPM_COLOR_CACHE_BUCKETS;
7383 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7384 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7385 entry added. */
7387 static struct xpm_cached_color *
7388 xpm_cache_color (f, color_name, color, bucket)
7389 struct frame *f;
7390 char *color_name;
7391 XColor *color;
7392 int bucket;
7394 size_t nbytes;
7395 struct xpm_cached_color *p;
7397 if (bucket < 0)
7398 bucket = xpm_color_bucket (color_name);
7400 nbytes = sizeof *p + strlen (color_name);
7401 p = (struct xpm_cached_color *) xmalloc (nbytes);
7402 strcpy (p->name, color_name);
7403 p->color = *color;
7404 p->next = xpm_color_cache[bucket];
7405 xpm_color_cache[bucket] = p;
7406 return p;
7410 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7411 return the cached definition in *COLOR. Otherwise, make a new
7412 entry in the cache and allocate the color. Value is zero if color
7413 allocation failed. */
7415 static int
7416 xpm_lookup_color (f, color_name, color)
7417 struct frame *f;
7418 char *color_name;
7419 XColor *color;
7421 struct xpm_cached_color *p;
7422 int h = xpm_color_bucket (color_name);
7424 for (p = xpm_color_cache[h]; p; p = p->next)
7425 if (strcmp (p->name, color_name) == 0)
7426 break;
7428 if (p != NULL)
7429 *color = p->color;
7430 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7431 color_name, color))
7433 color->pixel = lookup_rgb_color (f, color->red, color->green,
7434 color->blue);
7435 p = xpm_cache_color (f, color_name, color, h);
7438 return p != NULL;
7442 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7443 CLOSURE is a pointer to the frame on which we allocate the
7444 color. Return in *COLOR the allocated color. Value is non-zero
7445 if successful. */
7447 static int
7448 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7449 Display *dpy;
7450 Colormap cmap;
7451 char *color_name;
7452 XColor *color;
7453 void *closure;
7455 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7459 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7460 is a pointer to the frame on which we allocate the color. Value is
7461 non-zero if successful. */
7463 static int
7464 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7465 Display *dpy;
7466 Colormap cmap;
7467 Pixel *pixels;
7468 int npixels;
7469 void *closure;
7471 return 1;
7474 #endif /* ALLOC_XPM_COLORS */
7477 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7478 for XPM images. Such a list must consist of conses whose car and
7479 cdr are strings. */
7481 static int
7482 xpm_valid_color_symbols_p (color_symbols)
7483 Lisp_Object color_symbols;
7485 while (CONSP (color_symbols))
7487 Lisp_Object sym = XCAR (color_symbols);
7488 if (!CONSP (sym)
7489 || !STRINGP (XCAR (sym))
7490 || !STRINGP (XCDR (sym)))
7491 break;
7492 color_symbols = XCDR (color_symbols);
7495 return NILP (color_symbols);
7499 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7501 static int
7502 xpm_image_p (object)
7503 Lisp_Object object;
7505 struct image_keyword fmt[XPM_LAST];
7506 bcopy (xpm_format, fmt, sizeof fmt);
7507 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7508 /* Either `:file' or `:data' must be present. */
7509 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7510 /* Either no `:color-symbols' or it's a list of conses
7511 whose car and cdr are strings. */
7512 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7513 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7517 /* Load image IMG which will be displayed on frame F. Value is
7518 non-zero if successful. */
7520 static int
7521 xpm_load (f, img)
7522 struct frame *f;
7523 struct image *img;
7525 int rc;
7526 XpmAttributes attrs;
7527 Lisp_Object specified_file, color_symbols;
7529 /* Configure the XPM lib. Use the visual of frame F. Allocate
7530 close colors. Return colors allocated. */
7531 bzero (&attrs, sizeof attrs);
7532 attrs.visual = FRAME_X_VISUAL (f);
7533 attrs.colormap = FRAME_X_COLORMAP (f);
7534 attrs.valuemask |= XpmVisual;
7535 attrs.valuemask |= XpmColormap;
7537 #ifdef ALLOC_XPM_COLORS
7538 /* Allocate colors with our own functions which handle
7539 failing color allocation more gracefully. */
7540 attrs.color_closure = f;
7541 attrs.alloc_color = xpm_alloc_color;
7542 attrs.free_colors = xpm_free_colors;
7543 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7544 #else /* not ALLOC_XPM_COLORS */
7545 /* Let the XPM lib allocate colors. */
7546 attrs.valuemask |= XpmReturnAllocPixels;
7547 #ifdef XpmAllocCloseColors
7548 attrs.alloc_close_colors = 1;
7549 attrs.valuemask |= XpmAllocCloseColors;
7550 #else /* not XpmAllocCloseColors */
7551 attrs.closeness = 600;
7552 attrs.valuemask |= XpmCloseness;
7553 #endif /* not XpmAllocCloseColors */
7554 #endif /* ALLOC_XPM_COLORS */
7556 /* If image specification contains symbolic color definitions, add
7557 these to `attrs'. */
7558 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7559 if (CONSP (color_symbols))
7561 Lisp_Object tail;
7562 XpmColorSymbol *xpm_syms;
7563 int i, size;
7565 attrs.valuemask |= XpmColorSymbols;
7567 /* Count number of symbols. */
7568 attrs.numsymbols = 0;
7569 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7570 ++attrs.numsymbols;
7572 /* Allocate an XpmColorSymbol array. */
7573 size = attrs.numsymbols * sizeof *xpm_syms;
7574 xpm_syms = (XpmColorSymbol *) alloca (size);
7575 bzero (xpm_syms, size);
7576 attrs.colorsymbols = xpm_syms;
7578 /* Fill the color symbol array. */
7579 for (tail = color_symbols, i = 0;
7580 CONSP (tail);
7581 ++i, tail = XCDR (tail))
7583 Lisp_Object name = XCAR (XCAR (tail));
7584 Lisp_Object color = XCDR (XCAR (tail));
7585 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7586 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7587 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7588 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7592 /* Create a pixmap for the image, either from a file, or from a
7593 string buffer containing data in the same format as an XPM file. */
7594 #ifdef ALLOC_XPM_COLORS
7595 xpm_init_color_cache (f, &attrs);
7596 #endif
7598 specified_file = image_spec_value (img->spec, QCfile, NULL);
7599 if (STRINGP (specified_file))
7601 Lisp_Object file = x_find_image_file (specified_file);
7602 if (!STRINGP (file))
7604 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7605 return 0;
7608 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7609 XSTRING (file)->data, &img->pixmap, &img->mask,
7610 &attrs);
7612 else
7614 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7615 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7616 XSTRING (buffer)->data,
7617 &img->pixmap, &img->mask,
7618 &attrs);
7621 if (rc == XpmSuccess)
7623 #ifdef ALLOC_XPM_COLORS
7624 img->colors = colors_in_color_table (&img->ncolors);
7625 #else /* not ALLOC_XPM_COLORS */
7626 int i;
7628 img->ncolors = attrs.nalloc_pixels;
7629 img->colors = (unsigned long *) xmalloc (img->ncolors
7630 * sizeof *img->colors);
7631 for (i = 0; i < attrs.nalloc_pixels; ++i)
7633 img->colors[i] = attrs.alloc_pixels[i];
7634 #ifdef DEBUG_X_COLORS
7635 register_color (img->colors[i]);
7636 #endif
7638 #endif /* not ALLOC_XPM_COLORS */
7640 img->width = attrs.width;
7641 img->height = attrs.height;
7642 xassert (img->width > 0 && img->height > 0);
7644 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7645 XpmFreeAttributes (&attrs);
7647 else
7649 switch (rc)
7651 case XpmOpenFailed:
7652 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7653 break;
7655 case XpmFileInvalid:
7656 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7657 break;
7659 case XpmNoMemory:
7660 image_error ("Out of memory (%s)", img->spec, Qnil);
7661 break;
7663 case XpmColorFailed:
7664 image_error ("Color allocation error (%s)", img->spec, Qnil);
7665 break;
7667 default:
7668 image_error ("Unknown error (%s)", img->spec, Qnil);
7669 break;
7673 #ifdef ALLOC_XPM_COLORS
7674 xpm_free_color_cache ();
7675 #endif
7676 return rc == XpmSuccess;
7679 #endif /* HAVE_XPM != 0 */
7682 /***********************************************************************
7683 Color table
7684 ***********************************************************************/
7686 /* An entry in the color table mapping an RGB color to a pixel color. */
7688 struct ct_color
7690 int r, g, b;
7691 unsigned long pixel;
7693 /* Next in color table collision list. */
7694 struct ct_color *next;
7697 /* The bucket vector size to use. Must be prime. */
7699 #define CT_SIZE 101
7701 /* Value is a hash of the RGB color given by R, G, and B. */
7703 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7705 /* The color hash table. */
7707 struct ct_color **ct_table;
7709 /* Number of entries in the color table. */
7711 int ct_colors_allocated;
7713 /* Initialize the color table. */
7715 static void
7716 init_color_table ()
7718 int size = CT_SIZE * sizeof (*ct_table);
7719 ct_table = (struct ct_color **) xmalloc (size);
7720 bzero (ct_table, size);
7721 ct_colors_allocated = 0;
7725 /* Free memory associated with the color table. */
7727 static void
7728 free_color_table ()
7730 int i;
7731 struct ct_color *p, *next;
7733 for (i = 0; i < CT_SIZE; ++i)
7734 for (p = ct_table[i]; p; p = next)
7736 next = p->next;
7737 xfree (p);
7740 xfree (ct_table);
7741 ct_table = NULL;
7745 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7746 entry for that color already is in the color table, return the
7747 pixel color of that entry. Otherwise, allocate a new color for R,
7748 G, B, and make an entry in the color table. */
7750 static unsigned long
7751 lookup_rgb_color (f, r, g, b)
7752 struct frame *f;
7753 int r, g, b;
7755 unsigned hash = CT_HASH_RGB (r, g, b);
7756 int i = hash % CT_SIZE;
7757 struct ct_color *p;
7759 for (p = ct_table[i]; p; p = p->next)
7760 if (p->r == r && p->g == g && p->b == b)
7761 break;
7763 if (p == NULL)
7765 XColor color;
7766 Colormap cmap;
7767 int rc;
7769 color.red = r;
7770 color.green = g;
7771 color.blue = b;
7773 cmap = FRAME_X_COLORMAP (f);
7774 rc = x_alloc_nearest_color (f, cmap, &color);
7776 if (rc)
7778 ++ct_colors_allocated;
7780 p = (struct ct_color *) xmalloc (sizeof *p);
7781 p->r = r;
7782 p->g = g;
7783 p->b = b;
7784 p->pixel = color.pixel;
7785 p->next = ct_table[i];
7786 ct_table[i] = p;
7788 else
7789 return FRAME_FOREGROUND_PIXEL (f);
7792 return p->pixel;
7796 /* Look up pixel color PIXEL which is used on frame F in the color
7797 table. If not already present, allocate it. Value is PIXEL. */
7799 static unsigned long
7800 lookup_pixel_color (f, pixel)
7801 struct frame *f;
7802 unsigned long pixel;
7804 int i = pixel % CT_SIZE;
7805 struct ct_color *p;
7807 for (p = ct_table[i]; p; p = p->next)
7808 if (p->pixel == pixel)
7809 break;
7811 if (p == NULL)
7813 XColor color;
7814 Colormap cmap;
7815 int rc;
7817 cmap = FRAME_X_COLORMAP (f);
7818 color.pixel = pixel;
7819 x_query_color (f, &color);
7820 rc = x_alloc_nearest_color (f, cmap, &color);
7822 if (rc)
7824 ++ct_colors_allocated;
7826 p = (struct ct_color *) xmalloc (sizeof *p);
7827 p->r = color.red;
7828 p->g = color.green;
7829 p->b = color.blue;
7830 p->pixel = pixel;
7831 p->next = ct_table[i];
7832 ct_table[i] = p;
7834 else
7835 return FRAME_FOREGROUND_PIXEL (f);
7838 return p->pixel;
7842 /* Value is a vector of all pixel colors contained in the color table,
7843 allocated via xmalloc. Set *N to the number of colors. */
7845 static unsigned long *
7846 colors_in_color_table (n)
7847 int *n;
7849 int i, j;
7850 struct ct_color *p;
7851 unsigned long *colors;
7853 if (ct_colors_allocated == 0)
7855 *n = 0;
7856 colors = NULL;
7858 else
7860 colors = (unsigned long *) xmalloc (ct_colors_allocated
7861 * sizeof *colors);
7862 *n = ct_colors_allocated;
7864 for (i = j = 0; i < CT_SIZE; ++i)
7865 for (p = ct_table[i]; p; p = p->next)
7866 colors[j++] = p->pixel;
7869 return colors;
7874 /***********************************************************************
7875 Algorithms
7876 ***********************************************************************/
7878 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7879 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7880 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7882 /* Non-zero means draw a cross on images having `:conversion
7883 disabled'. */
7885 int cross_disabled_images;
7887 /* Edge detection matrices for different edge-detection
7888 strategies. */
7890 static int emboss_matrix[9] = {
7891 /* x - 1 x x + 1 */
7892 2, -1, 0, /* y - 1 */
7893 -1, 0, 1, /* y */
7894 0, 1, -2 /* y + 1 */
7897 static int laplace_matrix[9] = {
7898 /* x - 1 x x + 1 */
7899 1, 0, 0, /* y - 1 */
7900 0, 0, 0, /* y */
7901 0, 0, -1 /* y + 1 */
7904 /* Value is the intensity of the color whose red/green/blue values
7905 are R, G, and B. */
7907 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7910 /* On frame F, return an array of XColor structures describing image
7911 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7912 non-zero means also fill the red/green/blue members of the XColor
7913 structures. Value is a pointer to the array of XColors structures,
7914 allocated with xmalloc; it must be freed by the caller. */
7916 static XColor *
7917 x_to_xcolors (f, img, rgb_p)
7918 struct frame *f;
7919 struct image *img;
7920 int rgb_p;
7922 int x, y;
7923 XColor *colors, *p;
7924 XImage *ximg;
7926 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7928 /* Get the X image IMG->pixmap. */
7929 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7930 0, 0, img->width, img->height, ~0, ZPixmap);
7932 /* Fill the `pixel' members of the XColor array. I wished there
7933 were an easy and portable way to circumvent XGetPixel. */
7934 p = colors;
7935 for (y = 0; y < img->height; ++y)
7937 XColor *row = p;
7939 for (x = 0; x < img->width; ++x, ++p)
7940 p->pixel = XGetPixel (ximg, x, y);
7942 if (rgb_p)
7943 x_query_colors (f, row, img->width);
7946 XDestroyImage (ximg);
7947 return colors;
7951 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7952 RGB members are set. F is the frame on which this all happens.
7953 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7955 static void
7956 x_from_xcolors (f, img, colors)
7957 struct frame *f;
7958 struct image *img;
7959 XColor *colors;
7961 int x, y;
7962 XImage *oimg;
7963 Pixmap pixmap;
7964 XColor *p;
7966 init_color_table ();
7968 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7969 &oimg, &pixmap);
7970 p = colors;
7971 for (y = 0; y < img->height; ++y)
7972 for (x = 0; x < img->width; ++x, ++p)
7974 unsigned long pixel;
7975 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7976 XPutPixel (oimg, x, y, pixel);
7979 xfree (colors);
7980 x_clear_image_1 (f, img, 1, 0, 1);
7982 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7983 x_destroy_x_image (oimg);
7984 img->pixmap = pixmap;
7985 img->colors = colors_in_color_table (&img->ncolors);
7986 free_color_table ();
7990 /* On frame F, perform edge-detection on image IMG.
7992 MATRIX is a nine-element array specifying the transformation
7993 matrix. See emboss_matrix for an example.
7995 COLOR_ADJUST is a color adjustment added to each pixel of the
7996 outgoing image. */
7998 static void
7999 x_detect_edges (f, img, matrix, color_adjust)
8000 struct frame *f;
8001 struct image *img;
8002 int matrix[9], color_adjust;
8004 XColor *colors = x_to_xcolors (f, img, 1);
8005 XColor *new, *p;
8006 int x, y, i, sum;
8008 for (i = sum = 0; i < 9; ++i)
8009 sum += abs (matrix[i]);
8011 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8013 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
8015 for (y = 0; y < img->height; ++y)
8017 p = COLOR (new, 0, y);
8018 p->red = p->green = p->blue = 0xffff/2;
8019 p = COLOR (new, img->width - 1, y);
8020 p->red = p->green = p->blue = 0xffff/2;
8023 for (x = 1; x < img->width - 1; ++x)
8025 p = COLOR (new, x, 0);
8026 p->red = p->green = p->blue = 0xffff/2;
8027 p = COLOR (new, x, img->height - 1);
8028 p->red = p->green = p->blue = 0xffff/2;
8031 for (y = 1; y < img->height - 1; ++y)
8033 p = COLOR (new, 1, y);
8035 for (x = 1; x < img->width - 1; ++x, ++p)
8037 int r, g, b, y1, x1;
8039 r = g = b = i = 0;
8040 for (y1 = y - 1; y1 < y + 2; ++y1)
8041 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
8042 if (matrix[i])
8044 XColor *t = COLOR (colors, x1, y1);
8045 r += matrix[i] * t->red;
8046 g += matrix[i] * t->green;
8047 b += matrix[i] * t->blue;
8050 r = (r / sum + color_adjust) & 0xffff;
8051 g = (g / sum + color_adjust) & 0xffff;
8052 b = (b / sum + color_adjust) & 0xffff;
8053 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
8057 xfree (colors);
8058 x_from_xcolors (f, img, new);
8060 #undef COLOR
8064 /* Perform the pre-defined `emboss' edge-detection on image IMG
8065 on frame F. */
8067 static void
8068 x_emboss (f, img)
8069 struct frame *f;
8070 struct image *img;
8072 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
8076 /* Perform the pre-defined `laplace' edge-detection on image IMG
8077 on frame F. */
8079 static void
8080 x_laplace (f, img)
8081 struct frame *f;
8082 struct image *img;
8084 x_detect_edges (f, img, laplace_matrix, 45000);
8088 /* Perform edge-detection on image IMG on frame F, with specified
8089 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8091 MATRIX must be either
8093 - a list of at least 9 numbers in row-major form
8094 - a vector of at least 9 numbers
8096 COLOR_ADJUST nil means use a default; otherwise it must be a
8097 number. */
8099 static void
8100 x_edge_detection (f, img, matrix, color_adjust)
8101 struct frame *f;
8102 struct image *img;
8103 Lisp_Object matrix, color_adjust;
8105 int i = 0;
8106 int trans[9];
8108 if (CONSP (matrix))
8110 for (i = 0;
8111 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
8112 ++i, matrix = XCDR (matrix))
8113 trans[i] = XFLOATINT (XCAR (matrix));
8115 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
8117 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
8118 trans[i] = XFLOATINT (AREF (matrix, i));
8121 if (NILP (color_adjust))
8122 color_adjust = make_number (0xffff / 2);
8124 if (i == 9 && NUMBERP (color_adjust))
8125 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
8129 /* Transform image IMG on frame F so that it looks disabled. */
8131 static void
8132 x_disable_image (f, img)
8133 struct frame *f;
8134 struct image *img;
8136 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8138 if (dpyinfo->n_planes >= 2)
8140 /* Color (or grayscale). Convert to gray, and equalize. Just
8141 drawing such images with a stipple can look very odd, so
8142 we're using this method instead. */
8143 XColor *colors = x_to_xcolors (f, img, 1);
8144 XColor *p, *end;
8145 const int h = 15000;
8146 const int l = 30000;
8148 for (p = colors, end = colors + img->width * img->height;
8149 p < end;
8150 ++p)
8152 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
8153 int i2 = (0xffff - h - l) * i / 0xffff + l;
8154 p->red = p->green = p->blue = i2;
8157 x_from_xcolors (f, img, colors);
8160 /* Draw a cross over the disabled image, if we must or if we
8161 should. */
8162 if (dpyinfo->n_planes < 2 || cross_disabled_images)
8164 Display *dpy = FRAME_X_DISPLAY (f);
8165 GC gc;
8167 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
8168 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
8169 XDrawLine (dpy, img->pixmap, gc, 0, 0,
8170 img->width - 1, img->height - 1);
8171 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
8172 img->width - 1, 0);
8173 XFreeGC (dpy, gc);
8175 if (img->mask)
8177 gc = XCreateGC (dpy, img->mask, 0, NULL);
8178 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8179 XDrawLine (dpy, img->mask, gc, 0, 0,
8180 img->width - 1, img->height - 1);
8181 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8182 img->width - 1, 0);
8183 XFreeGC (dpy, gc);
8189 /* Build a mask for image IMG which is used on frame F. FILE is the
8190 name of an image file, for error messages. HOW determines how to
8191 determine the background color of IMG. If it is a list '(R G B)',
8192 with R, G, and B being integers >= 0, take that as the color of the
8193 background. Otherwise, determine the background color of IMG
8194 heuristically. Value is non-zero if successful. */
8196 static int
8197 x_build_heuristic_mask (f, img, how)
8198 struct frame *f;
8199 struct image *img;
8200 Lisp_Object how;
8202 Display *dpy = FRAME_X_DISPLAY (f);
8203 XImage *ximg, *mask_img;
8204 int x, y, rc, use_img_background;
8205 unsigned long bg = 0;
8207 if (img->mask)
8209 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8210 img->mask = None;
8211 img->background_transparent_valid = 0;
8214 /* Create an image and pixmap serving as mask. */
8215 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8216 &mask_img, &img->mask);
8217 if (!rc)
8218 return 0;
8220 /* Get the X image of IMG->pixmap. */
8221 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8222 ~0, ZPixmap);
8224 /* Determine the background color of ximg. If HOW is `(R G B)'
8225 take that as color. Otherwise, use the image's background color. */
8226 use_img_background = 1;
8228 if (CONSP (how))
8230 int rgb[3], i;
8232 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
8234 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8235 how = XCDR (how);
8238 if (i == 3 && NILP (how))
8240 char color_name[30];
8241 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8242 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
8243 use_img_background = 0;
8247 if (use_img_background)
8248 bg = four_corners_best (ximg, img->width, img->height);
8250 /* Set all bits in mask_img to 1 whose color in ximg is different
8251 from the background color bg. */
8252 for (y = 0; y < img->height; ++y)
8253 for (x = 0; x < img->width; ++x)
8254 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8256 /* Fill in the background_transparent field while we have the mask handy. */
8257 image_background_transparent (img, f, mask_img);
8259 /* Put mask_img into img->mask. */
8260 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8261 x_destroy_x_image (mask_img);
8262 XDestroyImage (ximg);
8264 return 1;
8269 /***********************************************************************
8270 PBM (mono, gray, color)
8271 ***********************************************************************/
8273 static int pbm_image_p P_ ((Lisp_Object object));
8274 static int pbm_load P_ ((struct frame *f, struct image *img));
8275 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8277 /* The symbol `pbm' identifying images of this type. */
8279 Lisp_Object Qpbm;
8281 /* Indices of image specification fields in gs_format, below. */
8283 enum pbm_keyword_index
8285 PBM_TYPE,
8286 PBM_FILE,
8287 PBM_DATA,
8288 PBM_ASCENT,
8289 PBM_MARGIN,
8290 PBM_RELIEF,
8291 PBM_ALGORITHM,
8292 PBM_HEURISTIC_MASK,
8293 PBM_MASK,
8294 PBM_FOREGROUND,
8295 PBM_BACKGROUND,
8296 PBM_LAST
8299 /* Vector of image_keyword structures describing the format
8300 of valid user-defined image specifications. */
8302 static struct image_keyword pbm_format[PBM_LAST] =
8304 {":type", IMAGE_SYMBOL_VALUE, 1},
8305 {":file", IMAGE_STRING_VALUE, 0},
8306 {":data", IMAGE_STRING_VALUE, 0},
8307 {":ascent", IMAGE_ASCENT_VALUE, 0},
8308 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8309 {":relief", IMAGE_INTEGER_VALUE, 0},
8310 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8311 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8312 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8313 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8314 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8317 /* Structure describing the image type `pbm'. */
8319 static struct image_type pbm_type =
8321 &Qpbm,
8322 pbm_image_p,
8323 pbm_load,
8324 x_clear_image,
8325 NULL
8329 /* Return non-zero if OBJECT is a valid PBM image specification. */
8331 static int
8332 pbm_image_p (object)
8333 Lisp_Object object;
8335 struct image_keyword fmt[PBM_LAST];
8337 bcopy (pbm_format, fmt, sizeof fmt);
8339 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8340 return 0;
8342 /* Must specify either :data or :file. */
8343 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8347 /* Scan a decimal number from *S and return it. Advance *S while
8348 reading the number. END is the end of the string. Value is -1 at
8349 end of input. */
8351 static int
8352 pbm_scan_number (s, end)
8353 unsigned char **s, *end;
8355 int c = 0, val = -1;
8357 while (*s < end)
8359 /* Skip white-space. */
8360 while (*s < end && (c = *(*s)++, isspace (c)))
8363 if (c == '#')
8365 /* Skip comment to end of line. */
8366 while (*s < end && (c = *(*s)++, c != '\n'))
8369 else if (isdigit (c))
8371 /* Read decimal number. */
8372 val = c - '0';
8373 while (*s < end && (c = *(*s)++, isdigit (c)))
8374 val = 10 * val + c - '0';
8375 break;
8377 else
8378 break;
8381 return val;
8385 /* Load PBM image IMG for use on frame F. */
8387 static int
8388 pbm_load (f, img)
8389 struct frame *f;
8390 struct image *img;
8392 int raw_p, x, y;
8393 int width, height, max_color_idx = 0;
8394 XImage *ximg;
8395 Lisp_Object file, specified_file;
8396 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8397 struct gcpro gcpro1;
8398 unsigned char *contents = NULL;
8399 unsigned char *end, *p;
8400 int size;
8402 specified_file = image_spec_value (img->spec, QCfile, NULL);
8403 file = Qnil;
8404 GCPRO1 (file);
8406 if (STRINGP (specified_file))
8408 file = x_find_image_file (specified_file);
8409 if (!STRINGP (file))
8411 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8412 UNGCPRO;
8413 return 0;
8416 contents = slurp_file (XSTRING (file)->data, &size);
8417 if (contents == NULL)
8419 image_error ("Error reading `%s'", file, Qnil);
8420 UNGCPRO;
8421 return 0;
8424 p = contents;
8425 end = contents + size;
8427 else
8429 Lisp_Object data;
8430 data = image_spec_value (img->spec, QCdata, NULL);
8431 p = XSTRING (data)->data;
8432 end = p + STRING_BYTES (XSTRING (data));
8435 /* Check magic number. */
8436 if (end - p < 2 || *p++ != 'P')
8438 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8439 error:
8440 xfree (contents);
8441 UNGCPRO;
8442 return 0;
8445 switch (*p++)
8447 case '1':
8448 raw_p = 0, type = PBM_MONO;
8449 break;
8451 case '2':
8452 raw_p = 0, type = PBM_GRAY;
8453 break;
8455 case '3':
8456 raw_p = 0, type = PBM_COLOR;
8457 break;
8459 case '4':
8460 raw_p = 1, type = PBM_MONO;
8461 break;
8463 case '5':
8464 raw_p = 1, type = PBM_GRAY;
8465 break;
8467 case '6':
8468 raw_p = 1, type = PBM_COLOR;
8469 break;
8471 default:
8472 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8473 goto error;
8476 /* Read width, height, maximum color-component. Characters
8477 starting with `#' up to the end of a line are ignored. */
8478 width = pbm_scan_number (&p, end);
8479 height = pbm_scan_number (&p, end);
8481 if (type != PBM_MONO)
8483 max_color_idx = pbm_scan_number (&p, end);
8484 if (raw_p && max_color_idx > 255)
8485 max_color_idx = 255;
8488 if (width < 0
8489 || height < 0
8490 || (type != PBM_MONO && max_color_idx < 0))
8491 goto error;
8493 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8494 &ximg, &img->pixmap))
8495 goto error;
8497 /* Initialize the color hash table. */
8498 init_color_table ();
8500 if (type == PBM_MONO)
8502 int c = 0, g;
8503 struct image_keyword fmt[PBM_LAST];
8504 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8505 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8507 /* Parse the image specification. */
8508 bcopy (pbm_format, fmt, sizeof fmt);
8509 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8511 /* Get foreground and background colors, maybe allocate colors. */
8512 if (fmt[PBM_FOREGROUND].count
8513 && STRINGP (fmt[PBM_FOREGROUND].value))
8514 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8515 if (fmt[PBM_BACKGROUND].count
8516 && STRINGP (fmt[PBM_BACKGROUND].value))
8518 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8519 img->background = bg;
8520 img->background_valid = 1;
8523 for (y = 0; y < height; ++y)
8524 for (x = 0; x < width; ++x)
8526 if (raw_p)
8528 if ((x & 7) == 0)
8529 c = *p++;
8530 g = c & 0x80;
8531 c <<= 1;
8533 else
8534 g = pbm_scan_number (&p, end);
8536 XPutPixel (ximg, x, y, g ? fg : bg);
8539 else
8541 for (y = 0; y < height; ++y)
8542 for (x = 0; x < width; ++x)
8544 int r, g, b;
8546 if (type == PBM_GRAY)
8547 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8548 else if (raw_p)
8550 r = *p++;
8551 g = *p++;
8552 b = *p++;
8554 else
8556 r = pbm_scan_number (&p, end);
8557 g = pbm_scan_number (&p, end);
8558 b = pbm_scan_number (&p, end);
8561 if (r < 0 || g < 0 || b < 0)
8563 xfree (ximg->data);
8564 ximg->data = NULL;
8565 XDestroyImage (ximg);
8566 image_error ("Invalid pixel value in image `%s'",
8567 img->spec, Qnil);
8568 goto error;
8571 /* RGB values are now in the range 0..max_color_idx.
8572 Scale this to the range 0..0xffff supported by X. */
8573 r = (double) r * 65535 / max_color_idx;
8574 g = (double) g * 65535 / max_color_idx;
8575 b = (double) b * 65535 / max_color_idx;
8576 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8580 /* Store in IMG->colors the colors allocated for the image, and
8581 free the color table. */
8582 img->colors = colors_in_color_table (&img->ncolors);
8583 free_color_table ();
8585 /* Maybe fill in the background field while we have ximg handy. */
8586 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8587 IMAGE_BACKGROUND (img, f, ximg);
8589 /* Put the image into a pixmap. */
8590 x_put_x_image (f, ximg, img->pixmap, width, height);
8591 x_destroy_x_image (ximg);
8593 img->width = width;
8594 img->height = height;
8596 UNGCPRO;
8597 xfree (contents);
8598 return 1;
8603 /***********************************************************************
8605 ***********************************************************************/
8607 #if HAVE_PNG
8609 #include <png.h>
8611 /* Function prototypes. */
8613 static int png_image_p P_ ((Lisp_Object object));
8614 static int png_load P_ ((struct frame *f, struct image *img));
8616 /* The symbol `png' identifying images of this type. */
8618 Lisp_Object Qpng;
8620 /* Indices of image specification fields in png_format, below. */
8622 enum png_keyword_index
8624 PNG_TYPE,
8625 PNG_DATA,
8626 PNG_FILE,
8627 PNG_ASCENT,
8628 PNG_MARGIN,
8629 PNG_RELIEF,
8630 PNG_ALGORITHM,
8631 PNG_HEURISTIC_MASK,
8632 PNG_MASK,
8633 PNG_BACKGROUND,
8634 PNG_LAST
8637 /* Vector of image_keyword structures describing the format
8638 of valid user-defined image specifications. */
8640 static struct image_keyword png_format[PNG_LAST] =
8642 {":type", IMAGE_SYMBOL_VALUE, 1},
8643 {":data", IMAGE_STRING_VALUE, 0},
8644 {":file", IMAGE_STRING_VALUE, 0},
8645 {":ascent", IMAGE_ASCENT_VALUE, 0},
8646 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8647 {":relief", IMAGE_INTEGER_VALUE, 0},
8648 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8649 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8650 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8651 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8654 /* Structure describing the image type `png'. */
8656 static struct image_type png_type =
8658 &Qpng,
8659 png_image_p,
8660 png_load,
8661 x_clear_image,
8662 NULL
8666 /* Return non-zero if OBJECT is a valid PNG image specification. */
8668 static int
8669 png_image_p (object)
8670 Lisp_Object object;
8672 struct image_keyword fmt[PNG_LAST];
8673 bcopy (png_format, fmt, sizeof fmt);
8675 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8676 return 0;
8678 /* Must specify either the :data or :file keyword. */
8679 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8683 /* Error and warning handlers installed when the PNG library
8684 is initialized. */
8686 static void
8687 my_png_error (png_ptr, msg)
8688 png_struct *png_ptr;
8689 char *msg;
8691 xassert (png_ptr != NULL);
8692 image_error ("PNG error: %s", build_string (msg), Qnil);
8693 longjmp (png_ptr->jmpbuf, 1);
8697 static void
8698 my_png_warning (png_ptr, msg)
8699 png_struct *png_ptr;
8700 char *msg;
8702 xassert (png_ptr != NULL);
8703 image_error ("PNG warning: %s", build_string (msg), Qnil);
8706 /* Memory source for PNG decoding. */
8708 struct png_memory_storage
8710 unsigned char *bytes; /* The data */
8711 size_t len; /* How big is it? */
8712 int index; /* Where are we? */
8716 /* Function set as reader function when reading PNG image from memory.
8717 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8718 bytes from the input to DATA. */
8720 static void
8721 png_read_from_memory (png_ptr, data, length)
8722 png_structp png_ptr;
8723 png_bytep data;
8724 png_size_t length;
8726 struct png_memory_storage *tbr
8727 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8729 if (length > tbr->len - tbr->index)
8730 png_error (png_ptr, "Read error");
8732 bcopy (tbr->bytes + tbr->index, data, length);
8733 tbr->index = tbr->index + length;
8736 /* Load PNG image IMG for use on frame F. Value is non-zero if
8737 successful. */
8739 static int
8740 png_load (f, img)
8741 struct frame *f;
8742 struct image *img;
8744 Lisp_Object file, specified_file;
8745 Lisp_Object specified_data;
8746 int x, y, i;
8747 XImage *ximg, *mask_img = NULL;
8748 struct gcpro gcpro1;
8749 png_struct *png_ptr = NULL;
8750 png_info *info_ptr = NULL, *end_info = NULL;
8751 FILE *volatile fp = NULL;
8752 png_byte sig[8];
8753 png_byte * volatile pixels = NULL;
8754 png_byte ** volatile rows = NULL;
8755 png_uint_32 width, height;
8756 int bit_depth, color_type, interlace_type;
8757 png_byte channels;
8758 png_uint_32 row_bytes;
8759 int transparent_p;
8760 char *gamma_str;
8761 double screen_gamma, image_gamma;
8762 int intent;
8763 struct png_memory_storage tbr; /* Data to be read */
8765 /* Find out what file to load. */
8766 specified_file = image_spec_value (img->spec, QCfile, NULL);
8767 specified_data = image_spec_value (img->spec, QCdata, NULL);
8768 file = Qnil;
8769 GCPRO1 (file);
8771 if (NILP (specified_data))
8773 file = x_find_image_file (specified_file);
8774 if (!STRINGP (file))
8776 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8777 UNGCPRO;
8778 return 0;
8781 /* Open the image file. */
8782 fp = fopen (XSTRING (file)->data, "rb");
8783 if (!fp)
8785 image_error ("Cannot open image file `%s'", file, Qnil);
8786 UNGCPRO;
8787 fclose (fp);
8788 return 0;
8791 /* Check PNG signature. */
8792 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8793 || !png_check_sig (sig, sizeof sig))
8795 image_error ("Not a PNG file: `%s'", file, Qnil);
8796 UNGCPRO;
8797 fclose (fp);
8798 return 0;
8801 else
8803 /* Read from memory. */
8804 tbr.bytes = XSTRING (specified_data)->data;
8805 tbr.len = STRING_BYTES (XSTRING (specified_data));
8806 tbr.index = 0;
8808 /* Check PNG signature. */
8809 if (tbr.len < sizeof sig
8810 || !png_check_sig (tbr.bytes, sizeof sig))
8812 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8813 UNGCPRO;
8814 return 0;
8817 /* Need to skip past the signature. */
8818 tbr.bytes += sizeof (sig);
8821 /* Initialize read and info structs for PNG lib. */
8822 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8823 my_png_error, my_png_warning);
8824 if (!png_ptr)
8826 if (fp) fclose (fp);
8827 UNGCPRO;
8828 return 0;
8831 info_ptr = png_create_info_struct (png_ptr);
8832 if (!info_ptr)
8834 png_destroy_read_struct (&png_ptr, NULL, NULL);
8835 if (fp) fclose (fp);
8836 UNGCPRO;
8837 return 0;
8840 end_info = png_create_info_struct (png_ptr);
8841 if (!end_info)
8843 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8844 if (fp) fclose (fp);
8845 UNGCPRO;
8846 return 0;
8849 /* Set error jump-back. We come back here when the PNG library
8850 detects an error. */
8851 if (setjmp (png_ptr->jmpbuf))
8853 error:
8854 if (png_ptr)
8855 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8856 xfree (pixels);
8857 xfree (rows);
8858 if (fp) fclose (fp);
8859 UNGCPRO;
8860 return 0;
8863 /* Read image info. */
8864 if (!NILP (specified_data))
8865 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8866 else
8867 png_init_io (png_ptr, fp);
8869 png_set_sig_bytes (png_ptr, sizeof sig);
8870 png_read_info (png_ptr, info_ptr);
8871 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8872 &interlace_type, NULL, NULL);
8874 /* If image contains simply transparency data, we prefer to
8875 construct a clipping mask. */
8876 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8877 transparent_p = 1;
8878 else
8879 transparent_p = 0;
8881 /* This function is easier to write if we only have to handle
8882 one data format: RGB or RGBA with 8 bits per channel. Let's
8883 transform other formats into that format. */
8885 /* Strip more than 8 bits per channel. */
8886 if (bit_depth == 16)
8887 png_set_strip_16 (png_ptr);
8889 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8890 if available. */
8891 png_set_expand (png_ptr);
8893 /* Convert grayscale images to RGB. */
8894 if (color_type == PNG_COLOR_TYPE_GRAY
8895 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8896 png_set_gray_to_rgb (png_ptr);
8898 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8899 gamma_str = getenv ("SCREEN_GAMMA");
8900 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8902 /* Tell the PNG lib to handle gamma correction for us. */
8904 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8905 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8906 /* There is a special chunk in the image specifying the gamma. */
8907 png_set_sRGB (png_ptr, info_ptr, intent);
8908 else
8909 #endif
8910 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8911 /* Image contains gamma information. */
8912 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8913 else
8914 /* Use a default of 0.5 for the image gamma. */
8915 png_set_gamma (png_ptr, screen_gamma, 0.5);
8917 /* Handle alpha channel by combining the image with a background
8918 color. Do this only if a real alpha channel is supplied. For
8919 simple transparency, we prefer a clipping mask. */
8920 if (!transparent_p)
8922 png_color_16 *image_bg;
8923 Lisp_Object specified_bg
8924 = image_spec_value (img->spec, QCbackground, NULL);
8926 if (STRINGP (specified_bg))
8927 /* The user specified `:background', use that. */
8929 XColor color;
8930 if (x_defined_color (f, XSTRING (specified_bg)->data, &color, 0))
8932 png_color_16 user_bg;
8934 bzero (&user_bg, sizeof user_bg);
8935 user_bg.red = color.red;
8936 user_bg.green = color.green;
8937 user_bg.blue = color.blue;
8939 png_set_background (png_ptr, &user_bg,
8940 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8943 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
8944 /* Image contains a background color with which to
8945 combine the image. */
8946 png_set_background (png_ptr, image_bg,
8947 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8948 else
8950 /* Image does not contain a background color with which
8951 to combine the image data via an alpha channel. Use
8952 the frame's background instead. */
8953 XColor color;
8954 Colormap cmap;
8955 png_color_16 frame_background;
8957 cmap = FRAME_X_COLORMAP (f);
8958 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8959 x_query_color (f, &color);
8961 bzero (&frame_background, sizeof frame_background);
8962 frame_background.red = color.red;
8963 frame_background.green = color.green;
8964 frame_background.blue = color.blue;
8966 png_set_background (png_ptr, &frame_background,
8967 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8971 /* Update info structure. */
8972 png_read_update_info (png_ptr, info_ptr);
8974 /* Get number of channels. Valid values are 1 for grayscale images
8975 and images with a palette, 2 for grayscale images with transparency
8976 information (alpha channel), 3 for RGB images, and 4 for RGB
8977 images with alpha channel, i.e. RGBA. If conversions above were
8978 sufficient we should only have 3 or 4 channels here. */
8979 channels = png_get_channels (png_ptr, info_ptr);
8980 xassert (channels == 3 || channels == 4);
8982 /* Number of bytes needed for one row of the image. */
8983 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8985 /* Allocate memory for the image. */
8986 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8987 rows = (png_byte **) xmalloc (height * sizeof *rows);
8988 for (i = 0; i < height; ++i)
8989 rows[i] = pixels + i * row_bytes;
8991 /* Read the entire image. */
8992 png_read_image (png_ptr, rows);
8993 png_read_end (png_ptr, info_ptr);
8994 if (fp)
8996 fclose (fp);
8997 fp = NULL;
9000 /* Create the X image and pixmap. */
9001 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
9002 &img->pixmap))
9003 goto error;
9005 /* Create an image and pixmap serving as mask if the PNG image
9006 contains an alpha channel. */
9007 if (channels == 4
9008 && !transparent_p
9009 && !x_create_x_image_and_pixmap (f, width, height, 1,
9010 &mask_img, &img->mask))
9012 x_destroy_x_image (ximg);
9013 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
9014 img->pixmap = None;
9015 goto error;
9018 /* Fill the X image and mask from PNG data. */
9019 init_color_table ();
9021 for (y = 0; y < height; ++y)
9023 png_byte *p = rows[y];
9025 for (x = 0; x < width; ++x)
9027 unsigned r, g, b;
9029 r = *p++ << 8;
9030 g = *p++ << 8;
9031 b = *p++ << 8;
9032 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
9034 /* An alpha channel, aka mask channel, associates variable
9035 transparency with an image. Where other image formats
9036 support binary transparency---fully transparent or fully
9037 opaque---PNG allows up to 254 levels of partial transparency.
9038 The PNG library implements partial transparency by combining
9039 the image with a specified background color.
9041 I'm not sure how to handle this here nicely: because the
9042 background on which the image is displayed may change, for
9043 real alpha channel support, it would be necessary to create
9044 a new image for each possible background.
9046 What I'm doing now is that a mask is created if we have
9047 boolean transparency information. Otherwise I'm using
9048 the frame's background color to combine the image with. */
9050 if (channels == 4)
9052 if (mask_img)
9053 XPutPixel (mask_img, x, y, *p > 0);
9054 ++p;
9059 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9060 /* Set IMG's background color from the PNG image, unless the user
9061 overrode it. */
9063 png_color_16 *bg;
9064 if (png_get_bKGD (png_ptr, info_ptr, &bg))
9066 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
9067 img->background_valid = 1;
9071 /* Remember colors allocated for this image. */
9072 img->colors = colors_in_color_table (&img->ncolors);
9073 free_color_table ();
9075 /* Clean up. */
9076 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9077 xfree (rows);
9078 xfree (pixels);
9080 img->width = width;
9081 img->height = height;
9083 /* Maybe fill in the background field while we have ximg handy. */
9084 IMAGE_BACKGROUND (img, f, ximg);
9086 /* Put the image into the pixmap, then free the X image and its buffer. */
9087 x_put_x_image (f, ximg, img->pixmap, width, height);
9088 x_destroy_x_image (ximg);
9090 /* Same for the mask. */
9091 if (mask_img)
9093 /* Fill in the background_transparent field while we have the mask
9094 handy. */
9095 image_background_transparent (img, f, mask_img);
9097 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
9098 x_destroy_x_image (mask_img);
9101 UNGCPRO;
9102 return 1;
9105 #endif /* HAVE_PNG != 0 */
9109 /***********************************************************************
9110 JPEG
9111 ***********************************************************************/
9113 #if HAVE_JPEG
9115 /* Work around a warning about HAVE_STDLIB_H being redefined in
9116 jconfig.h. */
9117 #ifdef HAVE_STDLIB_H
9118 #define HAVE_STDLIB_H_1
9119 #undef HAVE_STDLIB_H
9120 #endif /* HAVE_STLIB_H */
9122 #include <jpeglib.h>
9123 #include <jerror.h>
9124 #include <setjmp.h>
9126 #ifdef HAVE_STLIB_H_1
9127 #define HAVE_STDLIB_H 1
9128 #endif
9130 static int jpeg_image_p P_ ((Lisp_Object object));
9131 static int jpeg_load P_ ((struct frame *f, struct image *img));
9133 /* The symbol `jpeg' identifying images of this type. */
9135 Lisp_Object Qjpeg;
9137 /* Indices of image specification fields in gs_format, below. */
9139 enum jpeg_keyword_index
9141 JPEG_TYPE,
9142 JPEG_DATA,
9143 JPEG_FILE,
9144 JPEG_ASCENT,
9145 JPEG_MARGIN,
9146 JPEG_RELIEF,
9147 JPEG_ALGORITHM,
9148 JPEG_HEURISTIC_MASK,
9149 JPEG_MASK,
9150 JPEG_BACKGROUND,
9151 JPEG_LAST
9154 /* Vector of image_keyword structures describing the format
9155 of valid user-defined image specifications. */
9157 static struct image_keyword jpeg_format[JPEG_LAST] =
9159 {":type", IMAGE_SYMBOL_VALUE, 1},
9160 {":data", IMAGE_STRING_VALUE, 0},
9161 {":file", IMAGE_STRING_VALUE, 0},
9162 {":ascent", IMAGE_ASCENT_VALUE, 0},
9163 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9164 {":relief", IMAGE_INTEGER_VALUE, 0},
9165 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9166 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9167 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9168 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9171 /* Structure describing the image type `jpeg'. */
9173 static struct image_type jpeg_type =
9175 &Qjpeg,
9176 jpeg_image_p,
9177 jpeg_load,
9178 x_clear_image,
9179 NULL
9183 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9185 static int
9186 jpeg_image_p (object)
9187 Lisp_Object object;
9189 struct image_keyword fmt[JPEG_LAST];
9191 bcopy (jpeg_format, fmt, sizeof fmt);
9193 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
9194 return 0;
9196 /* Must specify either the :data or :file keyword. */
9197 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9201 struct my_jpeg_error_mgr
9203 struct jpeg_error_mgr pub;
9204 jmp_buf setjmp_buffer;
9208 static void
9209 my_error_exit (cinfo)
9210 j_common_ptr cinfo;
9212 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9213 longjmp (mgr->setjmp_buffer, 1);
9217 /* Init source method for JPEG data source manager. Called by
9218 jpeg_read_header() before any data is actually read. See
9219 libjpeg.doc from the JPEG lib distribution. */
9221 static void
9222 our_init_source (cinfo)
9223 j_decompress_ptr cinfo;
9228 /* Fill input buffer method for JPEG data source manager. Called
9229 whenever more data is needed. We read the whole image in one step,
9230 so this only adds a fake end of input marker at the end. */
9232 static boolean
9233 our_fill_input_buffer (cinfo)
9234 j_decompress_ptr cinfo;
9236 /* Insert a fake EOI marker. */
9237 struct jpeg_source_mgr *src = cinfo->src;
9238 static JOCTET buffer[2];
9240 buffer[0] = (JOCTET) 0xFF;
9241 buffer[1] = (JOCTET) JPEG_EOI;
9243 src->next_input_byte = buffer;
9244 src->bytes_in_buffer = 2;
9245 return TRUE;
9249 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9250 is the JPEG data source manager. */
9252 static void
9253 our_skip_input_data (cinfo, num_bytes)
9254 j_decompress_ptr cinfo;
9255 long num_bytes;
9257 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9259 if (src)
9261 if (num_bytes > src->bytes_in_buffer)
9262 ERREXIT (cinfo, JERR_INPUT_EOF);
9264 src->bytes_in_buffer -= num_bytes;
9265 src->next_input_byte += num_bytes;
9270 /* Method to terminate data source. Called by
9271 jpeg_finish_decompress() after all data has been processed. */
9273 static void
9274 our_term_source (cinfo)
9275 j_decompress_ptr cinfo;
9280 /* Set up the JPEG lib for reading an image from DATA which contains
9281 LEN bytes. CINFO is the decompression info structure created for
9282 reading the image. */
9284 static void
9285 jpeg_memory_src (cinfo, data, len)
9286 j_decompress_ptr cinfo;
9287 JOCTET *data;
9288 unsigned int len;
9290 struct jpeg_source_mgr *src;
9292 if (cinfo->src == NULL)
9294 /* First time for this JPEG object? */
9295 cinfo->src = (struct jpeg_source_mgr *)
9296 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9297 sizeof (struct jpeg_source_mgr));
9298 src = (struct jpeg_source_mgr *) cinfo->src;
9299 src->next_input_byte = data;
9302 src = (struct jpeg_source_mgr *) cinfo->src;
9303 src->init_source = our_init_source;
9304 src->fill_input_buffer = our_fill_input_buffer;
9305 src->skip_input_data = our_skip_input_data;
9306 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9307 src->term_source = our_term_source;
9308 src->bytes_in_buffer = len;
9309 src->next_input_byte = data;
9313 /* Load image IMG for use on frame F. Patterned after example.c
9314 from the JPEG lib. */
9316 static int
9317 jpeg_load (f, img)
9318 struct frame *f;
9319 struct image *img;
9321 struct jpeg_decompress_struct cinfo;
9322 struct my_jpeg_error_mgr mgr;
9323 Lisp_Object file, specified_file;
9324 Lisp_Object specified_data;
9325 FILE * volatile fp = NULL;
9326 JSAMPARRAY buffer;
9327 int row_stride, x, y;
9328 XImage *ximg = NULL;
9329 int rc;
9330 unsigned long *colors;
9331 int width, height;
9332 struct gcpro gcpro1;
9334 /* Open the JPEG file. */
9335 specified_file = image_spec_value (img->spec, QCfile, NULL);
9336 specified_data = image_spec_value (img->spec, QCdata, NULL);
9337 file = Qnil;
9338 GCPRO1 (file);
9340 if (NILP (specified_data))
9342 file = x_find_image_file (specified_file);
9343 if (!STRINGP (file))
9345 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9346 UNGCPRO;
9347 return 0;
9350 fp = fopen (XSTRING (file)->data, "r");
9351 if (fp == NULL)
9353 image_error ("Cannot open `%s'", file, Qnil);
9354 UNGCPRO;
9355 return 0;
9359 /* Customize libjpeg's error handling to call my_error_exit when an
9360 error is detected. This function will perform a longjmp. */
9361 cinfo.err = jpeg_std_error (&mgr.pub);
9362 mgr.pub.error_exit = my_error_exit;
9364 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9366 if (rc == 1)
9368 /* Called from my_error_exit. Display a JPEG error. */
9369 char buffer[JMSG_LENGTH_MAX];
9370 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9371 image_error ("Error reading JPEG image `%s': %s", img->spec,
9372 build_string (buffer));
9375 /* Close the input file and destroy the JPEG object. */
9376 if (fp)
9377 fclose ((FILE *) fp);
9378 jpeg_destroy_decompress (&cinfo);
9380 /* If we already have an XImage, free that. */
9381 x_destroy_x_image (ximg);
9383 /* Free pixmap and colors. */
9384 x_clear_image (f, img);
9386 UNGCPRO;
9387 return 0;
9390 /* Create the JPEG decompression object. Let it read from fp.
9391 Read the JPEG image header. */
9392 jpeg_create_decompress (&cinfo);
9394 if (NILP (specified_data))
9395 jpeg_stdio_src (&cinfo, (FILE *) fp);
9396 else
9397 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
9398 STRING_BYTES (XSTRING (specified_data)));
9400 jpeg_read_header (&cinfo, TRUE);
9402 /* Customize decompression so that color quantization will be used.
9403 Start decompression. */
9404 cinfo.quantize_colors = TRUE;
9405 jpeg_start_decompress (&cinfo);
9406 width = img->width = cinfo.output_width;
9407 height = img->height = cinfo.output_height;
9409 /* Create X image and pixmap. */
9410 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9411 longjmp (mgr.setjmp_buffer, 2);
9413 /* Allocate colors. When color quantization is used,
9414 cinfo.actual_number_of_colors has been set with the number of
9415 colors generated, and cinfo.colormap is a two-dimensional array
9416 of color indices in the range 0..cinfo.actual_number_of_colors.
9417 No more than 255 colors will be generated. */
9419 int i, ir, ig, ib;
9421 if (cinfo.out_color_components > 2)
9422 ir = 0, ig = 1, ib = 2;
9423 else if (cinfo.out_color_components > 1)
9424 ir = 0, ig = 1, ib = 0;
9425 else
9426 ir = 0, ig = 0, ib = 0;
9428 /* Use the color table mechanism because it handles colors that
9429 cannot be allocated nicely. Such colors will be replaced with
9430 a default color, and we don't have to care about which colors
9431 can be freed safely, and which can't. */
9432 init_color_table ();
9433 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9434 * sizeof *colors);
9436 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9438 /* Multiply RGB values with 255 because X expects RGB values
9439 in the range 0..0xffff. */
9440 int r = cinfo.colormap[ir][i] << 8;
9441 int g = cinfo.colormap[ig][i] << 8;
9442 int b = cinfo.colormap[ib][i] << 8;
9443 colors[i] = lookup_rgb_color (f, r, g, b);
9446 /* Remember those colors actually allocated. */
9447 img->colors = colors_in_color_table (&img->ncolors);
9448 free_color_table ();
9451 /* Read pixels. */
9452 row_stride = width * cinfo.output_components;
9453 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9454 row_stride, 1);
9455 for (y = 0; y < height; ++y)
9457 jpeg_read_scanlines (&cinfo, buffer, 1);
9458 for (x = 0; x < cinfo.output_width; ++x)
9459 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9462 /* Clean up. */
9463 jpeg_finish_decompress (&cinfo);
9464 jpeg_destroy_decompress (&cinfo);
9465 if (fp)
9466 fclose ((FILE *) fp);
9468 /* Maybe fill in the background field while we have ximg handy. */
9469 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9470 IMAGE_BACKGROUND (img, f, ximg);
9472 /* Put the image into the pixmap. */
9473 x_put_x_image (f, ximg, img->pixmap, width, height);
9474 x_destroy_x_image (ximg);
9475 UNGCPRO;
9476 return 1;
9479 #endif /* HAVE_JPEG */
9483 /***********************************************************************
9484 TIFF
9485 ***********************************************************************/
9487 #if HAVE_TIFF
9489 #include <tiffio.h>
9491 static int tiff_image_p P_ ((Lisp_Object object));
9492 static int tiff_load P_ ((struct frame *f, struct image *img));
9494 /* The symbol `tiff' identifying images of this type. */
9496 Lisp_Object Qtiff;
9498 /* Indices of image specification fields in tiff_format, below. */
9500 enum tiff_keyword_index
9502 TIFF_TYPE,
9503 TIFF_DATA,
9504 TIFF_FILE,
9505 TIFF_ASCENT,
9506 TIFF_MARGIN,
9507 TIFF_RELIEF,
9508 TIFF_ALGORITHM,
9509 TIFF_HEURISTIC_MASK,
9510 TIFF_MASK,
9511 TIFF_BACKGROUND,
9512 TIFF_LAST
9515 /* Vector of image_keyword structures describing the format
9516 of valid user-defined image specifications. */
9518 static struct image_keyword tiff_format[TIFF_LAST] =
9520 {":type", IMAGE_SYMBOL_VALUE, 1},
9521 {":data", IMAGE_STRING_VALUE, 0},
9522 {":file", IMAGE_STRING_VALUE, 0},
9523 {":ascent", IMAGE_ASCENT_VALUE, 0},
9524 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9525 {":relief", IMAGE_INTEGER_VALUE, 0},
9526 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9527 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9528 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9529 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9532 /* Structure describing the image type `tiff'. */
9534 static struct image_type tiff_type =
9536 &Qtiff,
9537 tiff_image_p,
9538 tiff_load,
9539 x_clear_image,
9540 NULL
9544 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9546 static int
9547 tiff_image_p (object)
9548 Lisp_Object object;
9550 struct image_keyword fmt[TIFF_LAST];
9551 bcopy (tiff_format, fmt, sizeof fmt);
9553 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9554 return 0;
9556 /* Must specify either the :data or :file keyword. */
9557 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9561 /* Reading from a memory buffer for TIFF images Based on the PNG
9562 memory source, but we have to provide a lot of extra functions.
9563 Blah.
9565 We really only need to implement read and seek, but I am not
9566 convinced that the TIFF library is smart enough not to destroy
9567 itself if we only hand it the function pointers we need to
9568 override. */
9570 typedef struct
9572 unsigned char *bytes;
9573 size_t len;
9574 int index;
9576 tiff_memory_source;
9579 static size_t
9580 tiff_read_from_memory (data, buf, size)
9581 thandle_t data;
9582 tdata_t buf;
9583 tsize_t size;
9585 tiff_memory_source *src = (tiff_memory_source *) data;
9587 if (size > src->len - src->index)
9588 return (size_t) -1;
9589 bcopy (src->bytes + src->index, buf, size);
9590 src->index += size;
9591 return size;
9595 static size_t
9596 tiff_write_from_memory (data, buf, size)
9597 thandle_t data;
9598 tdata_t buf;
9599 tsize_t size;
9601 return (size_t) -1;
9605 static toff_t
9606 tiff_seek_in_memory (data, off, whence)
9607 thandle_t data;
9608 toff_t off;
9609 int whence;
9611 tiff_memory_source *src = (tiff_memory_source *) data;
9612 int idx;
9614 switch (whence)
9616 case SEEK_SET: /* Go from beginning of source. */
9617 idx = off;
9618 break;
9620 case SEEK_END: /* Go from end of source. */
9621 idx = src->len + off;
9622 break;
9624 case SEEK_CUR: /* Go from current position. */
9625 idx = src->index + off;
9626 break;
9628 default: /* Invalid `whence'. */
9629 return -1;
9632 if (idx > src->len || idx < 0)
9633 return -1;
9635 src->index = idx;
9636 return src->index;
9640 static int
9641 tiff_close_memory (data)
9642 thandle_t data;
9644 /* NOOP */
9645 return 0;
9649 static int
9650 tiff_mmap_memory (data, pbase, psize)
9651 thandle_t data;
9652 tdata_t *pbase;
9653 toff_t *psize;
9655 /* It is already _IN_ memory. */
9656 return 0;
9660 static void
9661 tiff_unmap_memory (data, base, size)
9662 thandle_t data;
9663 tdata_t base;
9664 toff_t size;
9666 /* We don't need to do this. */
9670 static toff_t
9671 tiff_size_of_memory (data)
9672 thandle_t data;
9674 return ((tiff_memory_source *) data)->len;
9678 static void
9679 tiff_error_handler (title, format, ap)
9680 const char *title, *format;
9681 va_list ap;
9683 char buf[512];
9684 int len;
9686 len = sprintf (buf, "TIFF error: %s ", title);
9687 vsprintf (buf + len, format, ap);
9688 add_to_log (buf, Qnil, Qnil);
9692 static void
9693 tiff_warning_handler (title, format, ap)
9694 const char *title, *format;
9695 va_list ap;
9697 char buf[512];
9698 int len;
9700 len = sprintf (buf, "TIFF warning: %s ", title);
9701 vsprintf (buf + len, format, ap);
9702 add_to_log (buf, Qnil, Qnil);
9706 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9707 successful. */
9709 static int
9710 tiff_load (f, img)
9711 struct frame *f;
9712 struct image *img;
9714 Lisp_Object file, specified_file;
9715 Lisp_Object specified_data;
9716 TIFF *tiff;
9717 int width, height, x, y;
9718 uint32 *buf;
9719 int rc;
9720 XImage *ximg;
9721 struct gcpro gcpro1;
9722 tiff_memory_source memsrc;
9724 specified_file = image_spec_value (img->spec, QCfile, NULL);
9725 specified_data = image_spec_value (img->spec, QCdata, NULL);
9726 file = Qnil;
9727 GCPRO1 (file);
9729 TIFFSetErrorHandler (tiff_error_handler);
9730 TIFFSetWarningHandler (tiff_warning_handler);
9732 if (NILP (specified_data))
9734 /* Read from a file */
9735 file = x_find_image_file (specified_file);
9736 if (!STRINGP (file))
9738 image_error ("Cannot find image file `%s'", file, Qnil);
9739 UNGCPRO;
9740 return 0;
9743 /* Try to open the image file. */
9744 tiff = TIFFOpen (XSTRING (file)->data, "r");
9745 if (tiff == NULL)
9747 image_error ("Cannot open `%s'", file, Qnil);
9748 UNGCPRO;
9749 return 0;
9752 else
9754 /* Memory source! */
9755 memsrc.bytes = XSTRING (specified_data)->data;
9756 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9757 memsrc.index = 0;
9759 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9760 (TIFFReadWriteProc) tiff_read_from_memory,
9761 (TIFFReadWriteProc) tiff_write_from_memory,
9762 tiff_seek_in_memory,
9763 tiff_close_memory,
9764 tiff_size_of_memory,
9765 tiff_mmap_memory,
9766 tiff_unmap_memory);
9768 if (!tiff)
9770 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9771 UNGCPRO;
9772 return 0;
9776 /* Get width and height of the image, and allocate a raster buffer
9777 of width x height 32-bit values. */
9778 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9779 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9780 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9782 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9783 TIFFClose (tiff);
9784 if (!rc)
9786 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9787 xfree (buf);
9788 UNGCPRO;
9789 return 0;
9792 /* Create the X image and pixmap. */
9793 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9795 xfree (buf);
9796 UNGCPRO;
9797 return 0;
9800 /* Initialize the color table. */
9801 init_color_table ();
9803 /* Process the pixel raster. Origin is in the lower-left corner. */
9804 for (y = 0; y < height; ++y)
9806 uint32 *row = buf + y * width;
9808 for (x = 0; x < width; ++x)
9810 uint32 abgr = row[x];
9811 int r = TIFFGetR (abgr) << 8;
9812 int g = TIFFGetG (abgr) << 8;
9813 int b = TIFFGetB (abgr) << 8;
9814 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9818 /* Remember the colors allocated for the image. Free the color table. */
9819 img->colors = colors_in_color_table (&img->ncolors);
9820 free_color_table ();
9822 img->width = width;
9823 img->height = height;
9825 /* Maybe fill in the background field while we have ximg handy. */
9826 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9827 IMAGE_BACKGROUND (img, f, ximg);
9829 /* Put the image into the pixmap, then free the X image and its buffer. */
9830 x_put_x_image (f, ximg, img->pixmap, width, height);
9831 x_destroy_x_image (ximg);
9832 xfree (buf);
9834 UNGCPRO;
9835 return 1;
9838 #endif /* HAVE_TIFF != 0 */
9842 /***********************************************************************
9844 ***********************************************************************/
9846 #if HAVE_GIF
9848 #include <gif_lib.h>
9850 static int gif_image_p P_ ((Lisp_Object object));
9851 static int gif_load P_ ((struct frame *f, struct image *img));
9853 /* The symbol `gif' identifying images of this type. */
9855 Lisp_Object Qgif;
9857 /* Indices of image specification fields in gif_format, below. */
9859 enum gif_keyword_index
9861 GIF_TYPE,
9862 GIF_DATA,
9863 GIF_FILE,
9864 GIF_ASCENT,
9865 GIF_MARGIN,
9866 GIF_RELIEF,
9867 GIF_ALGORITHM,
9868 GIF_HEURISTIC_MASK,
9869 GIF_MASK,
9870 GIF_IMAGE,
9871 GIF_BACKGROUND,
9872 GIF_LAST
9875 /* Vector of image_keyword structures describing the format
9876 of valid user-defined image specifications. */
9878 static struct image_keyword gif_format[GIF_LAST] =
9880 {":type", IMAGE_SYMBOL_VALUE, 1},
9881 {":data", IMAGE_STRING_VALUE, 0},
9882 {":file", IMAGE_STRING_VALUE, 0},
9883 {":ascent", IMAGE_ASCENT_VALUE, 0},
9884 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9885 {":relief", IMAGE_INTEGER_VALUE, 0},
9886 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9887 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9888 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9889 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9890 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9893 /* Structure describing the image type `gif'. */
9895 static struct image_type gif_type =
9897 &Qgif,
9898 gif_image_p,
9899 gif_load,
9900 x_clear_image,
9901 NULL
9905 /* Return non-zero if OBJECT is a valid GIF image specification. */
9907 static int
9908 gif_image_p (object)
9909 Lisp_Object object;
9911 struct image_keyword fmt[GIF_LAST];
9912 bcopy (gif_format, fmt, sizeof fmt);
9914 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9915 return 0;
9917 /* Must specify either the :data or :file keyword. */
9918 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9922 /* Reading a GIF image from memory
9923 Based on the PNG memory stuff to a certain extent. */
9925 typedef struct
9927 unsigned char *bytes;
9928 size_t len;
9929 int index;
9931 gif_memory_source;
9934 /* Make the current memory source available to gif_read_from_memory.
9935 It's done this way because not all versions of libungif support
9936 a UserData field in the GifFileType structure. */
9937 static gif_memory_source *current_gif_memory_src;
9939 static int
9940 gif_read_from_memory (file, buf, len)
9941 GifFileType *file;
9942 GifByteType *buf;
9943 int len;
9945 gif_memory_source *src = current_gif_memory_src;
9947 if (len > src->len - src->index)
9948 return -1;
9950 bcopy (src->bytes + src->index, buf, len);
9951 src->index += len;
9952 return len;
9956 /* Load GIF image IMG for use on frame F. Value is non-zero if
9957 successful. */
9959 static int
9960 gif_load (f, img)
9961 struct frame *f;
9962 struct image *img;
9964 Lisp_Object file, specified_file;
9965 Lisp_Object specified_data;
9966 int rc, width, height, x, y, i;
9967 XImage *ximg;
9968 ColorMapObject *gif_color_map;
9969 unsigned long pixel_colors[256];
9970 GifFileType *gif;
9971 struct gcpro gcpro1;
9972 Lisp_Object image;
9973 int ino, image_left, image_top, image_width, image_height;
9974 gif_memory_source memsrc;
9975 unsigned char *raster;
9977 specified_file = image_spec_value (img->spec, QCfile, NULL);
9978 specified_data = image_spec_value (img->spec, QCdata, NULL);
9979 file = Qnil;
9980 GCPRO1 (file);
9982 if (NILP (specified_data))
9984 file = x_find_image_file (specified_file);
9985 if (!STRINGP (file))
9987 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9988 UNGCPRO;
9989 return 0;
9992 /* Open the GIF file. */
9993 gif = DGifOpenFileName (XSTRING (file)->data);
9994 if (gif == NULL)
9996 image_error ("Cannot open `%s'", file, Qnil);
9997 UNGCPRO;
9998 return 0;
10001 else
10003 /* Read from memory! */
10004 current_gif_memory_src = &memsrc;
10005 memsrc.bytes = XSTRING (specified_data)->data;
10006 memsrc.len = STRING_BYTES (XSTRING (specified_data));
10007 memsrc.index = 0;
10009 gif = DGifOpen(&memsrc, gif_read_from_memory);
10010 if (!gif)
10012 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
10013 UNGCPRO;
10014 return 0;
10018 /* Read entire contents. */
10019 rc = DGifSlurp (gif);
10020 if (rc == GIF_ERROR)
10022 image_error ("Error reading `%s'", img->spec, Qnil);
10023 DGifCloseFile (gif);
10024 UNGCPRO;
10025 return 0;
10028 image = image_spec_value (img->spec, QCindex, NULL);
10029 ino = INTEGERP (image) ? XFASTINT (image) : 0;
10030 if (ino >= gif->ImageCount)
10032 image_error ("Invalid image number `%s' in image `%s'",
10033 image, img->spec);
10034 DGifCloseFile (gif);
10035 UNGCPRO;
10036 return 0;
10039 width = img->width = gif->SWidth;
10040 height = img->height = gif->SHeight;
10042 /* Create the X image and pixmap. */
10043 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10045 DGifCloseFile (gif);
10046 UNGCPRO;
10047 return 0;
10050 /* Allocate colors. */
10051 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
10052 if (!gif_color_map)
10053 gif_color_map = gif->SColorMap;
10054 init_color_table ();
10055 bzero (pixel_colors, sizeof pixel_colors);
10057 for (i = 0; i < gif_color_map->ColorCount; ++i)
10059 int r = gif_color_map->Colors[i].Red << 8;
10060 int g = gif_color_map->Colors[i].Green << 8;
10061 int b = gif_color_map->Colors[i].Blue << 8;
10062 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
10065 img->colors = colors_in_color_table (&img->ncolors);
10066 free_color_table ();
10068 /* Clear the part of the screen image that are not covered by
10069 the image from the GIF file. Full animated GIF support
10070 requires more than can be done here (see the gif89 spec,
10071 disposal methods). Let's simply assume that the part
10072 not covered by a sub-image is in the frame's background color. */
10073 image_top = gif->SavedImages[ino].ImageDesc.Top;
10074 image_left = gif->SavedImages[ino].ImageDesc.Left;
10075 image_width = gif->SavedImages[ino].ImageDesc.Width;
10076 image_height = gif->SavedImages[ino].ImageDesc.Height;
10078 for (y = 0; y < image_top; ++y)
10079 for (x = 0; x < width; ++x)
10080 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10082 for (y = image_top + image_height; y < height; ++y)
10083 for (x = 0; x < width; ++x)
10084 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10086 for (y = image_top; y < image_top + image_height; ++y)
10088 for (x = 0; x < image_left; ++x)
10089 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10090 for (x = image_left + image_width; x < width; ++x)
10091 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10094 /* Read the GIF image into the X image. We use a local variable
10095 `raster' here because RasterBits below is a char *, and invites
10096 problems with bytes >= 0x80. */
10097 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
10099 if (gif->SavedImages[ino].ImageDesc.Interlace)
10101 static int interlace_start[] = {0, 4, 2, 1};
10102 static int interlace_increment[] = {8, 8, 4, 2};
10103 int pass;
10104 int row = interlace_start[0];
10106 pass = 0;
10108 for (y = 0; y < image_height; y++)
10110 if (row >= image_height)
10112 row = interlace_start[++pass];
10113 while (row >= image_height)
10114 row = interlace_start[++pass];
10117 for (x = 0; x < image_width; x++)
10119 int i = raster[(y * image_width) + x];
10120 XPutPixel (ximg, x + image_left, row + image_top,
10121 pixel_colors[i]);
10124 row += interlace_increment[pass];
10127 else
10129 for (y = 0; y < image_height; ++y)
10130 for (x = 0; x < image_width; ++x)
10132 int i = raster[y * image_width + x];
10133 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
10137 DGifCloseFile (gif);
10139 /* Maybe fill in the background field while we have ximg handy. */
10140 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10141 IMAGE_BACKGROUND (img, f, ximg);
10143 /* Put the image into the pixmap, then free the X image and its buffer. */
10144 x_put_x_image (f, ximg, img->pixmap, width, height);
10145 x_destroy_x_image (ximg);
10147 UNGCPRO;
10148 return 1;
10151 #endif /* HAVE_GIF != 0 */
10155 /***********************************************************************
10156 Ghostscript
10157 ***********************************************************************/
10159 static int gs_image_p P_ ((Lisp_Object object));
10160 static int gs_load P_ ((struct frame *f, struct image *img));
10161 static void gs_clear_image P_ ((struct frame *f, struct image *img));
10163 /* The symbol `postscript' identifying images of this type. */
10165 Lisp_Object Qpostscript;
10167 /* Keyword symbols. */
10169 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
10171 /* Indices of image specification fields in gs_format, below. */
10173 enum gs_keyword_index
10175 GS_TYPE,
10176 GS_PT_WIDTH,
10177 GS_PT_HEIGHT,
10178 GS_FILE,
10179 GS_LOADER,
10180 GS_BOUNDING_BOX,
10181 GS_ASCENT,
10182 GS_MARGIN,
10183 GS_RELIEF,
10184 GS_ALGORITHM,
10185 GS_HEURISTIC_MASK,
10186 GS_MASK,
10187 GS_BACKGROUND,
10188 GS_LAST
10191 /* Vector of image_keyword structures describing the format
10192 of valid user-defined image specifications. */
10194 static struct image_keyword gs_format[GS_LAST] =
10196 {":type", IMAGE_SYMBOL_VALUE, 1},
10197 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10198 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10199 {":file", IMAGE_STRING_VALUE, 1},
10200 {":loader", IMAGE_FUNCTION_VALUE, 0},
10201 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
10202 {":ascent", IMAGE_ASCENT_VALUE, 0},
10203 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10204 {":relief", IMAGE_INTEGER_VALUE, 0},
10205 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10206 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10207 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10208 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10211 /* Structure describing the image type `ghostscript'. */
10213 static struct image_type gs_type =
10215 &Qpostscript,
10216 gs_image_p,
10217 gs_load,
10218 gs_clear_image,
10219 NULL
10223 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10225 static void
10226 gs_clear_image (f, img)
10227 struct frame *f;
10228 struct image *img;
10230 /* IMG->data.ptr_val may contain a recorded colormap. */
10231 xfree (img->data.ptr_val);
10232 x_clear_image (f, img);
10236 /* Return non-zero if OBJECT is a valid Ghostscript image
10237 specification. */
10239 static int
10240 gs_image_p (object)
10241 Lisp_Object object;
10243 struct image_keyword fmt[GS_LAST];
10244 Lisp_Object tem;
10245 int i;
10247 bcopy (gs_format, fmt, sizeof fmt);
10249 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10250 return 0;
10252 /* Bounding box must be a list or vector containing 4 integers. */
10253 tem = fmt[GS_BOUNDING_BOX].value;
10254 if (CONSP (tem))
10256 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10257 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10258 return 0;
10259 if (!NILP (tem))
10260 return 0;
10262 else if (VECTORP (tem))
10264 if (XVECTOR (tem)->size != 4)
10265 return 0;
10266 for (i = 0; i < 4; ++i)
10267 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10268 return 0;
10270 else
10271 return 0;
10273 return 1;
10277 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10278 if successful. */
10280 static int
10281 gs_load (f, img)
10282 struct frame *f;
10283 struct image *img;
10285 char buffer[100];
10286 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10287 struct gcpro gcpro1, gcpro2;
10288 Lisp_Object frame;
10289 double in_width, in_height;
10290 Lisp_Object pixel_colors = Qnil;
10292 /* Compute pixel size of pixmap needed from the given size in the
10293 image specification. Sizes in the specification are in pt. 1 pt
10294 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10295 info. */
10296 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10297 in_width = XFASTINT (pt_width) / 72.0;
10298 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10299 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10300 in_height = XFASTINT (pt_height) / 72.0;
10301 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10303 /* Create the pixmap. */
10304 xassert (img->pixmap == None);
10305 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10306 img->width, img->height,
10307 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10309 if (!img->pixmap)
10311 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10312 return 0;
10315 /* Call the loader to fill the pixmap. It returns a process object
10316 if successful. We do not record_unwind_protect here because
10317 other places in redisplay like calling window scroll functions
10318 don't either. Let the Lisp loader use `unwind-protect' instead. */
10319 GCPRO2 (window_and_pixmap_id, pixel_colors);
10321 sprintf (buffer, "%lu %lu",
10322 (unsigned long) FRAME_X_WINDOW (f),
10323 (unsigned long) img->pixmap);
10324 window_and_pixmap_id = build_string (buffer);
10326 sprintf (buffer, "%lu %lu",
10327 FRAME_FOREGROUND_PIXEL (f),
10328 FRAME_BACKGROUND_PIXEL (f));
10329 pixel_colors = build_string (buffer);
10331 XSETFRAME (frame, f);
10332 loader = image_spec_value (img->spec, QCloader, NULL);
10333 if (NILP (loader))
10334 loader = intern ("gs-load-image");
10336 img->data.lisp_val = call6 (loader, frame, img->spec,
10337 make_number (img->width),
10338 make_number (img->height),
10339 window_and_pixmap_id,
10340 pixel_colors);
10341 UNGCPRO;
10342 return PROCESSP (img->data.lisp_val);
10346 /* Kill the Ghostscript process that was started to fill PIXMAP on
10347 frame F. Called from XTread_socket when receiving an event
10348 telling Emacs that Ghostscript has finished drawing. */
10350 void
10351 x_kill_gs_process (pixmap, f)
10352 Pixmap pixmap;
10353 struct frame *f;
10355 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10356 int class, i;
10357 struct image *img;
10359 /* Find the image containing PIXMAP. */
10360 for (i = 0; i < c->used; ++i)
10361 if (c->images[i]->pixmap == pixmap)
10362 break;
10364 /* Should someone in between have cleared the image cache, for
10365 instance, give up. */
10366 if (i == c->used)
10367 return;
10369 /* Kill the GS process. We should have found PIXMAP in the image
10370 cache and its image should contain a process object. */
10371 img = c->images[i];
10372 xassert (PROCESSP (img->data.lisp_val));
10373 Fkill_process (img->data.lisp_val, Qnil);
10374 img->data.lisp_val = Qnil;
10376 /* On displays with a mutable colormap, figure out the colors
10377 allocated for the image by looking at the pixels of an XImage for
10378 img->pixmap. */
10379 class = FRAME_X_VISUAL (f)->class;
10380 if (class != StaticColor && class != StaticGray && class != TrueColor)
10382 XImage *ximg;
10384 BLOCK_INPUT;
10386 /* Try to get an XImage for img->pixmep. */
10387 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10388 0, 0, img->width, img->height, ~0, ZPixmap);
10389 if (ximg)
10391 int x, y;
10393 /* Initialize the color table. */
10394 init_color_table ();
10396 /* For each pixel of the image, look its color up in the
10397 color table. After having done so, the color table will
10398 contain an entry for each color used by the image. */
10399 for (y = 0; y < img->height; ++y)
10400 for (x = 0; x < img->width; ++x)
10402 unsigned long pixel = XGetPixel (ximg, x, y);
10403 lookup_pixel_color (f, pixel);
10406 /* Record colors in the image. Free color table and XImage. */
10407 img->colors = colors_in_color_table (&img->ncolors);
10408 free_color_table ();
10409 XDestroyImage (ximg);
10411 #if 0 /* This doesn't seem to be the case. If we free the colors
10412 here, we get a BadAccess later in x_clear_image when
10413 freeing the colors. */
10414 /* We have allocated colors once, but Ghostscript has also
10415 allocated colors on behalf of us. So, to get the
10416 reference counts right, free them once. */
10417 if (img->ncolors)
10418 x_free_colors (f, img->colors, img->ncolors);
10419 #endif
10421 else
10422 image_error ("Cannot get X image of `%s'; colors will not be freed",
10423 img->spec, Qnil);
10425 UNBLOCK_INPUT;
10428 /* Now that we have the pixmap, compute mask and transform the
10429 image if requested. */
10430 BLOCK_INPUT;
10431 postprocess_image (f, img);
10432 UNBLOCK_INPUT;
10437 /***********************************************************************
10438 Window properties
10439 ***********************************************************************/
10441 DEFUN ("x-change-window-property", Fx_change_window_property,
10442 Sx_change_window_property, 2, 3, 0,
10443 doc: /* Change window property PROP to VALUE on the X window of FRAME.
10444 PROP and VALUE must be strings. FRAME nil or omitted means use the
10445 selected frame. Value is VALUE. */)
10446 (prop, value, frame)
10447 Lisp_Object frame, prop, value;
10449 struct frame *f = check_x_frame (frame);
10450 Atom prop_atom;
10452 CHECK_STRING (prop);
10453 CHECK_STRING (value);
10455 BLOCK_INPUT;
10456 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10457 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10458 prop_atom, XA_STRING, 8, PropModeReplace,
10459 XSTRING (value)->data, XSTRING (value)->size);
10461 /* Make sure the property is set when we return. */
10462 XFlush (FRAME_X_DISPLAY (f));
10463 UNBLOCK_INPUT;
10465 return value;
10469 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10470 Sx_delete_window_property, 1, 2, 0,
10471 doc: /* Remove window property PROP from X window of FRAME.
10472 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10473 (prop, frame)
10474 Lisp_Object prop, frame;
10476 struct frame *f = check_x_frame (frame);
10477 Atom prop_atom;
10479 CHECK_STRING (prop);
10480 BLOCK_INPUT;
10481 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10482 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10484 /* Make sure the property is removed when we return. */
10485 XFlush (FRAME_X_DISPLAY (f));
10486 UNBLOCK_INPUT;
10488 return prop;
10492 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10493 1, 2, 0,
10494 doc: /* Value is the value of window property PROP on FRAME.
10495 If FRAME is nil or omitted, use the selected frame. Value is nil
10496 if FRAME hasn't a property with name PROP or if PROP has no string
10497 value. */)
10498 (prop, frame)
10499 Lisp_Object prop, frame;
10501 struct frame *f = check_x_frame (frame);
10502 Atom prop_atom;
10503 int rc;
10504 Lisp_Object prop_value = Qnil;
10505 char *tmp_data = NULL;
10506 Atom actual_type;
10507 int actual_format;
10508 unsigned long actual_size, bytes_remaining;
10510 CHECK_STRING (prop);
10511 BLOCK_INPUT;
10512 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10513 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10514 prop_atom, 0, 0, False, XA_STRING,
10515 &actual_type, &actual_format, &actual_size,
10516 &bytes_remaining, (unsigned char **) &tmp_data);
10517 if (rc == Success)
10519 int size = bytes_remaining;
10521 XFree (tmp_data);
10522 tmp_data = NULL;
10524 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10525 prop_atom, 0, bytes_remaining,
10526 False, XA_STRING,
10527 &actual_type, &actual_format,
10528 &actual_size, &bytes_remaining,
10529 (unsigned char **) &tmp_data);
10530 if (rc == Success && tmp_data)
10531 prop_value = make_string (tmp_data, size);
10533 XFree (tmp_data);
10536 UNBLOCK_INPUT;
10537 return prop_value;
10542 /***********************************************************************
10543 Busy cursor
10544 ***********************************************************************/
10546 /* If non-null, an asynchronous timer that, when it expires, displays
10547 an hourglass cursor on all frames. */
10549 static struct atimer *hourglass_atimer;
10551 /* Non-zero means an hourglass cursor is currently shown. */
10553 static int hourglass_shown_p;
10555 /* Number of seconds to wait before displaying an hourglass cursor. */
10557 static Lisp_Object Vhourglass_delay;
10559 /* Default number of seconds to wait before displaying an hourglass
10560 cursor. */
10562 #define DEFAULT_HOURGLASS_DELAY 1
10564 /* Function prototypes. */
10566 static void show_hourglass P_ ((struct atimer *));
10567 static void hide_hourglass P_ ((void));
10570 /* Cancel a currently active hourglass timer, and start a new one. */
10572 void
10573 start_hourglass ()
10575 EMACS_TIME delay;
10576 int secs, usecs = 0;
10578 cancel_hourglass ();
10580 if (INTEGERP (Vhourglass_delay)
10581 && XINT (Vhourglass_delay) > 0)
10582 secs = XFASTINT (Vhourglass_delay);
10583 else if (FLOATP (Vhourglass_delay)
10584 && XFLOAT_DATA (Vhourglass_delay) > 0)
10586 Lisp_Object tem;
10587 tem = Ftruncate (Vhourglass_delay, Qnil);
10588 secs = XFASTINT (tem);
10589 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10591 else
10592 secs = DEFAULT_HOURGLASS_DELAY;
10594 EMACS_SET_SECS_USECS (delay, secs, usecs);
10595 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10596 show_hourglass, NULL);
10600 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10601 shown. */
10603 void
10604 cancel_hourglass ()
10606 if (hourglass_atimer)
10608 cancel_atimer (hourglass_atimer);
10609 hourglass_atimer = NULL;
10612 if (hourglass_shown_p)
10613 hide_hourglass ();
10617 /* Timer function of hourglass_atimer. TIMER is equal to
10618 hourglass_atimer.
10620 Display an hourglass pointer on all frames by mapping the frames'
10621 hourglass_window. Set the hourglass_p flag in the frames'
10622 output_data.x structure to indicate that an hourglass cursor is
10623 shown on the frames. */
10625 static void
10626 show_hourglass (timer)
10627 struct atimer *timer;
10629 /* The timer implementation will cancel this timer automatically
10630 after this function has run. Set hourglass_atimer to null
10631 so that we know the timer doesn't have to be canceled. */
10632 hourglass_atimer = NULL;
10634 if (!hourglass_shown_p)
10636 Lisp_Object rest, frame;
10638 BLOCK_INPUT;
10640 FOR_EACH_FRAME (rest, frame)
10642 struct frame *f = XFRAME (frame);
10644 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10646 Display *dpy = FRAME_X_DISPLAY (f);
10648 #ifdef USE_X_TOOLKIT
10649 if (f->output_data.x->widget)
10650 #else
10651 if (FRAME_OUTER_WINDOW (f))
10652 #endif
10654 f->output_data.x->hourglass_p = 1;
10656 if (!f->output_data.x->hourglass_window)
10658 unsigned long mask = CWCursor;
10659 XSetWindowAttributes attrs;
10661 attrs.cursor = f->output_data.x->hourglass_cursor;
10663 f->output_data.x->hourglass_window
10664 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10665 0, 0, 32000, 32000, 0, 0,
10666 InputOnly,
10667 CopyFromParent,
10668 mask, &attrs);
10671 XMapRaised (dpy, f->output_data.x->hourglass_window);
10672 XFlush (dpy);
10677 hourglass_shown_p = 1;
10678 UNBLOCK_INPUT;
10683 /* Hide the hourglass pointer on all frames, if it is currently
10684 shown. */
10686 static void
10687 hide_hourglass ()
10689 if (hourglass_shown_p)
10691 Lisp_Object rest, frame;
10693 BLOCK_INPUT;
10694 FOR_EACH_FRAME (rest, frame)
10696 struct frame *f = XFRAME (frame);
10698 if (FRAME_X_P (f)
10699 /* Watch out for newly created frames. */
10700 && f->output_data.x->hourglass_window)
10702 XUnmapWindow (FRAME_X_DISPLAY (f),
10703 f->output_data.x->hourglass_window);
10704 /* Sync here because XTread_socket looks at the
10705 hourglass_p flag that is reset to zero below. */
10706 XSync (FRAME_X_DISPLAY (f), False);
10707 f->output_data.x->hourglass_p = 0;
10711 hourglass_shown_p = 0;
10712 UNBLOCK_INPUT;
10718 /***********************************************************************
10719 Tool tips
10720 ***********************************************************************/
10722 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10723 Lisp_Object, Lisp_Object));
10724 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10725 Lisp_Object, int, int, int *, int *));
10727 /* The frame of a currently visible tooltip. */
10729 Lisp_Object tip_frame;
10731 /* If non-nil, a timer started that hides the last tooltip when it
10732 fires. */
10734 Lisp_Object tip_timer;
10735 Window tip_window;
10737 /* If non-nil, a vector of 3 elements containing the last args
10738 with which x-show-tip was called. See there. */
10740 Lisp_Object last_show_tip_args;
10742 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10744 Lisp_Object Vx_max_tooltip_size;
10747 static Lisp_Object
10748 unwind_create_tip_frame (frame)
10749 Lisp_Object frame;
10751 Lisp_Object deleted;
10753 deleted = unwind_create_frame (frame);
10754 if (EQ (deleted, Qt))
10756 tip_window = None;
10757 tip_frame = Qnil;
10760 return deleted;
10764 /* Create a frame for a tooltip on the display described by DPYINFO.
10765 PARMS is a list of frame parameters. TEXT is the string to
10766 display in the tip frame. Value is the frame.
10768 Note that functions called here, esp. x_default_parameter can
10769 signal errors, for instance when a specified color name is
10770 undefined. We have to make sure that we're in a consistent state
10771 when this happens. */
10773 static Lisp_Object
10774 x_create_tip_frame (dpyinfo, parms, text)
10775 struct x_display_info *dpyinfo;
10776 Lisp_Object parms, text;
10778 struct frame *f;
10779 Lisp_Object frame, tem;
10780 Lisp_Object name;
10781 long window_prompting = 0;
10782 int width, height;
10783 int count = BINDING_STACK_SIZE ();
10784 struct gcpro gcpro1, gcpro2, gcpro3;
10785 struct kboard *kb;
10786 int face_change_count_before = face_change_count;
10787 Lisp_Object buffer;
10788 struct buffer *old_buffer;
10790 check_x ();
10792 /* Use this general default value to start with until we know if
10793 this frame has a specified name. */
10794 Vx_resource_name = Vinvocation_name;
10796 #ifdef MULTI_KBOARD
10797 kb = dpyinfo->kboard;
10798 #else
10799 kb = &the_only_kboard;
10800 #endif
10802 /* Get the name of the frame to use for resource lookup. */
10803 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10804 if (!STRINGP (name)
10805 && !EQ (name, Qunbound)
10806 && !NILP (name))
10807 error ("Invalid frame name--not a string or nil");
10808 Vx_resource_name = name;
10810 frame = Qnil;
10811 GCPRO3 (parms, name, frame);
10812 f = make_frame (1);
10813 XSETFRAME (frame, f);
10815 buffer = Fget_buffer_create (build_string (" *tip*"));
10816 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10817 old_buffer = current_buffer;
10818 set_buffer_internal_1 (XBUFFER (buffer));
10819 current_buffer->truncate_lines = Qnil;
10820 Ferase_buffer ();
10821 Finsert (1, &text);
10822 set_buffer_internal_1 (old_buffer);
10824 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10825 record_unwind_protect (unwind_create_tip_frame, frame);
10827 /* By setting the output method, we're essentially saying that
10828 the frame is live, as per FRAME_LIVE_P. If we get a signal
10829 from this point on, x_destroy_window might screw up reference
10830 counts etc. */
10831 f->output_method = output_x_window;
10832 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10833 bzero (f->output_data.x, sizeof (struct x_output));
10834 f->output_data.x->icon_bitmap = -1;
10835 f->output_data.x->fontset = -1;
10836 f->output_data.x->scroll_bar_foreground_pixel = -1;
10837 f->output_data.x->scroll_bar_background_pixel = -1;
10838 #ifdef USE_TOOLKIT_SCROLL_BARS
10839 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
10840 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
10841 #endif /* USE_TOOLKIT_SCROLL_BARS */
10842 f->icon_name = Qnil;
10843 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10844 #if GLYPH_DEBUG
10845 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
10846 dpyinfo_refcount = dpyinfo->reference_count;
10847 #endif /* GLYPH_DEBUG */
10848 #ifdef MULTI_KBOARD
10849 FRAME_KBOARD (f) = kb;
10850 #endif
10851 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10852 f->output_data.x->explicit_parent = 0;
10854 /* These colors will be set anyway later, but it's important
10855 to get the color reference counts right, so initialize them! */
10857 Lisp_Object black;
10858 struct gcpro gcpro1;
10860 black = build_string ("black");
10861 GCPRO1 (black);
10862 f->output_data.x->foreground_pixel
10863 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10864 f->output_data.x->background_pixel
10865 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10866 f->output_data.x->cursor_pixel
10867 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10868 f->output_data.x->cursor_foreground_pixel
10869 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10870 f->output_data.x->border_pixel
10871 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10872 f->output_data.x->mouse_pixel
10873 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10874 UNGCPRO;
10877 /* Set the name; the functions to which we pass f expect the name to
10878 be set. */
10879 if (EQ (name, Qunbound) || NILP (name))
10881 f->name = build_string (dpyinfo->x_id_name);
10882 f->explicit_name = 0;
10884 else
10886 f->name = name;
10887 f->explicit_name = 1;
10888 /* use the frame's title when getting resources for this frame. */
10889 specbind (Qx_resource_name, name);
10892 /* Extract the window parameters from the supplied values that are
10893 needed to determine window geometry. */
10895 Lisp_Object font;
10897 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10899 BLOCK_INPUT;
10900 /* First, try whatever font the caller has specified. */
10901 if (STRINGP (font))
10903 tem = Fquery_fontset (font, Qnil);
10904 if (STRINGP (tem))
10905 font = x_new_fontset (f, XSTRING (tem)->data);
10906 else
10907 font = x_new_font (f, XSTRING (font)->data);
10910 /* Try out a font which we hope has bold and italic variations. */
10911 if (!STRINGP (font))
10912 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10913 if (!STRINGP (font))
10914 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10915 if (! STRINGP (font))
10916 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10917 if (! STRINGP (font))
10918 /* This was formerly the first thing tried, but it finds too many fonts
10919 and takes too long. */
10920 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10921 /* If those didn't work, look for something which will at least work. */
10922 if (! STRINGP (font))
10923 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10924 UNBLOCK_INPUT;
10925 if (! STRINGP (font))
10926 font = build_string ("fixed");
10928 x_default_parameter (f, parms, Qfont, font,
10929 "font", "Font", RES_TYPE_STRING);
10932 x_default_parameter (f, parms, Qborder_width, make_number (2),
10933 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10935 /* This defaults to 2 in order to match xterm. We recognize either
10936 internalBorderWidth or internalBorder (which is what xterm calls
10937 it). */
10938 if (NILP (Fassq (Qinternal_border_width, parms)))
10940 Lisp_Object value;
10942 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10943 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10944 if (! EQ (value, Qunbound))
10945 parms = Fcons (Fcons (Qinternal_border_width, value),
10946 parms);
10949 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10950 "internalBorderWidth", "internalBorderWidth",
10951 RES_TYPE_NUMBER);
10953 /* Also do the stuff which must be set before the window exists. */
10954 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10955 "foreground", "Foreground", RES_TYPE_STRING);
10956 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10957 "background", "Background", RES_TYPE_STRING);
10958 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10959 "pointerColor", "Foreground", RES_TYPE_STRING);
10960 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10961 "cursorColor", "Foreground", RES_TYPE_STRING);
10962 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10963 "borderColor", "BorderColor", RES_TYPE_STRING);
10965 /* Init faces before x_default_parameter is called for scroll-bar
10966 parameters because that function calls x_set_scroll_bar_width,
10967 which calls change_frame_size, which calls Fset_window_buffer,
10968 which runs hooks, which call Fvertical_motion. At the end, we
10969 end up in init_iterator with a null face cache, which should not
10970 happen. */
10971 init_frame_faces (f);
10973 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10974 window_prompting = x_figure_window_size (f, parms);
10976 if (window_prompting & XNegative)
10978 if (window_prompting & YNegative)
10979 f->output_data.x->win_gravity = SouthEastGravity;
10980 else
10981 f->output_data.x->win_gravity = NorthEastGravity;
10983 else
10985 if (window_prompting & YNegative)
10986 f->output_data.x->win_gravity = SouthWestGravity;
10987 else
10988 f->output_data.x->win_gravity = NorthWestGravity;
10991 f->output_data.x->size_hint_flags = window_prompting;
10993 XSetWindowAttributes attrs;
10994 unsigned long mask;
10996 BLOCK_INPUT;
10997 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
10998 if (DoesSaveUnders (dpyinfo->screen))
10999 mask |= CWSaveUnder;
11001 /* Window managers look at the override-redirect flag to determine
11002 whether or net to give windows a decoration (Xlib spec, chapter
11003 3.2.8). */
11004 attrs.override_redirect = True;
11005 attrs.save_under = True;
11006 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
11007 /* Arrange for getting MapNotify and UnmapNotify events. */
11008 attrs.event_mask = StructureNotifyMask;
11009 tip_window
11010 = FRAME_X_WINDOW (f)
11011 = XCreateWindow (FRAME_X_DISPLAY (f),
11012 FRAME_X_DISPLAY_INFO (f)->root_window,
11013 /* x, y, width, height */
11014 0, 0, 1, 1,
11015 /* Border. */
11017 CopyFromParent, InputOutput, CopyFromParent,
11018 mask, &attrs);
11019 UNBLOCK_INPUT;
11022 x_make_gc (f);
11024 x_default_parameter (f, parms, Qauto_raise, Qnil,
11025 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11026 x_default_parameter (f, parms, Qauto_lower, Qnil,
11027 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11028 x_default_parameter (f, parms, Qcursor_type, Qbox,
11029 "cursorType", "CursorType", RES_TYPE_SYMBOL);
11031 /* Dimensions, especially f->height, must be done via change_frame_size.
11032 Change will not be effected unless different from the current
11033 f->height. */
11034 width = f->width;
11035 height = f->height;
11036 f->height = 0;
11037 SET_FRAME_WIDTH (f, 0);
11038 change_frame_size (f, height, width, 1, 0, 0);
11040 /* Set up faces after all frame parameters are known. This call
11041 also merges in face attributes specified for new frames.
11043 Frame parameters may be changed if .Xdefaults contains
11044 specifications for the default font. For example, if there is an
11045 `Emacs.default.attributeBackground: pink', the `background-color'
11046 attribute of the frame get's set, which let's the internal border
11047 of the tooltip frame appear in pink. Prevent this. */
11049 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
11051 /* Set tip_frame here, so that */
11052 tip_frame = frame;
11053 call1 (Qface_set_after_frame_default, frame);
11055 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
11056 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
11057 Qnil));
11060 f->no_split = 1;
11062 UNGCPRO;
11064 /* It is now ok to make the frame official even if we get an error
11065 below. And the frame needs to be on Vframe_list or making it
11066 visible won't work. */
11067 Vframe_list = Fcons (frame, Vframe_list);
11069 /* Now that the frame is official, it counts as a reference to
11070 its display. */
11071 FRAME_X_DISPLAY_INFO (f)->reference_count++;
11073 /* Setting attributes of faces of the tooltip frame from resources
11074 and similar will increment face_change_count, which leads to the
11075 clearing of all current matrices. Since this isn't necessary
11076 here, avoid it by resetting face_change_count to the value it
11077 had before we created the tip frame. */
11078 face_change_count = face_change_count_before;
11080 /* Discard the unwind_protect. */
11081 return unbind_to (count, frame);
11085 /* Compute where to display tip frame F. PARMS is the list of frame
11086 parameters for F. DX and DY are specified offsets from the current
11087 location of the mouse. WIDTH and HEIGHT are the width and height
11088 of the tooltip. Return coordinates relative to the root window of
11089 the display in *ROOT_X, and *ROOT_Y. */
11091 static void
11092 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
11093 struct frame *f;
11094 Lisp_Object parms, dx, dy;
11095 int width, height;
11096 int *root_x, *root_y;
11098 Lisp_Object left, top;
11099 int win_x, win_y;
11100 Window root, child;
11101 unsigned pmask;
11103 /* User-specified position? */
11104 left = Fcdr (Fassq (Qleft, parms));
11105 top = Fcdr (Fassq (Qtop, parms));
11107 /* Move the tooltip window where the mouse pointer is. Resize and
11108 show it. */
11109 if (!INTEGERP (left) || !INTEGERP (top))
11111 BLOCK_INPUT;
11112 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
11113 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
11114 UNBLOCK_INPUT;
11117 if (INTEGERP (top))
11118 *root_y = XINT (top);
11119 else if (*root_y + XINT (dy) - height < 0)
11120 *root_y -= XINT (dy);
11121 else
11123 *root_y -= height;
11124 *root_y += XINT (dy);
11127 if (INTEGERP (left))
11128 *root_x = XINT (left);
11129 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
11130 /* It fits to the right of the pointer. */
11131 *root_x += XINT (dx);
11132 else if (width + XINT (dx) <= *root_x)
11133 /* It fits to the left of the pointer. */
11134 *root_x -= width + XINT (dx);
11135 else
11136 /* Put it left-justified on the screen--it ought to fit that way. */
11137 *root_x = 0;
11141 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
11142 doc: /* Show STRING in a "tooltip" window on frame FRAME.
11143 A tooltip window is a small X window displaying a string.
11145 FRAME nil or omitted means use the selected frame.
11147 PARMS is an optional list of frame parameters which can be used to
11148 change the tooltip's appearance.
11150 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11151 means use the default timeout of 5 seconds.
11153 If the list of frame parameters PARAMS contains a `left' parameters,
11154 the tooltip is displayed at that x-position. Otherwise it is
11155 displayed at the mouse position, with offset DX added (default is 5 if
11156 DX isn't specified). Likewise for the y-position; if a `top' frame
11157 parameter is specified, it determines the y-position of the tooltip
11158 window, otherwise it is displayed at the mouse position, with offset
11159 DY added (default is -10).
11161 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11162 Text larger than the specified size is clipped. */)
11163 (string, frame, parms, timeout, dx, dy)
11164 Lisp_Object string, frame, parms, timeout, dx, dy;
11166 struct frame *f;
11167 struct window *w;
11168 int root_x, root_y;
11169 struct buffer *old_buffer;
11170 struct text_pos pos;
11171 int i, width, height;
11172 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
11173 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11174 int count = BINDING_STACK_SIZE ();
11176 specbind (Qinhibit_redisplay, Qt);
11178 GCPRO4 (string, parms, frame, timeout);
11180 CHECK_STRING (string);
11181 f = check_x_frame (frame);
11182 if (NILP (timeout))
11183 timeout = make_number (5);
11184 else
11185 CHECK_NATNUM (timeout);
11187 if (NILP (dx))
11188 dx = make_number (5);
11189 else
11190 CHECK_NUMBER (dx);
11192 if (NILP (dy))
11193 dy = make_number (-10);
11194 else
11195 CHECK_NUMBER (dy);
11197 if (NILP (last_show_tip_args))
11198 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
11200 if (!NILP (tip_frame))
11202 Lisp_Object last_string = AREF (last_show_tip_args, 0);
11203 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
11204 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
11206 if (EQ (frame, last_frame)
11207 && !NILP (Fequal (last_string, string))
11208 && !NILP (Fequal (last_parms, parms)))
11210 struct frame *f = XFRAME (tip_frame);
11212 /* Only DX and DY have changed. */
11213 if (!NILP (tip_timer))
11215 Lisp_Object timer = tip_timer;
11216 tip_timer = Qnil;
11217 call1 (Qcancel_timer, timer);
11220 BLOCK_INPUT;
11221 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
11222 PIXEL_HEIGHT (f), &root_x, &root_y);
11223 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11224 root_x, root_y);
11225 UNBLOCK_INPUT;
11226 goto start_timer;
11230 /* Hide a previous tip, if any. */
11231 Fx_hide_tip ();
11233 ASET (last_show_tip_args, 0, string);
11234 ASET (last_show_tip_args, 1, frame);
11235 ASET (last_show_tip_args, 2, parms);
11237 /* Add default values to frame parameters. */
11238 if (NILP (Fassq (Qname, parms)))
11239 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
11240 if (NILP (Fassq (Qinternal_border_width, parms)))
11241 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
11242 if (NILP (Fassq (Qborder_width, parms)))
11243 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
11244 if (NILP (Fassq (Qborder_color, parms)))
11245 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
11246 if (NILP (Fassq (Qbackground_color, parms)))
11247 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
11248 parms);
11250 /* Create a frame for the tooltip, and record it in the global
11251 variable tip_frame. */
11252 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
11253 f = XFRAME (frame);
11255 /* Set up the frame's root window. */
11256 w = XWINDOW (FRAME_ROOT_WINDOW (f));
11257 w->left = w->top = make_number (0);
11259 if (CONSP (Vx_max_tooltip_size)
11260 && INTEGERP (XCAR (Vx_max_tooltip_size))
11261 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11262 && INTEGERP (XCDR (Vx_max_tooltip_size))
11263 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11265 w->width = XCAR (Vx_max_tooltip_size);
11266 w->height = XCDR (Vx_max_tooltip_size);
11268 else
11270 w->width = make_number (80);
11271 w->height = make_number (40);
11274 f->window_width = XINT (w->width);
11275 adjust_glyphs (f);
11276 w->pseudo_window_p = 1;
11278 /* Display the tooltip text in a temporary buffer. */
11279 old_buffer = current_buffer;
11280 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11281 current_buffer->truncate_lines = Qnil;
11282 clear_glyph_matrix (w->desired_matrix);
11283 clear_glyph_matrix (w->current_matrix);
11284 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11285 try_window (FRAME_ROOT_WINDOW (f), pos);
11287 /* Compute width and height of the tooltip. */
11288 width = height = 0;
11289 for (i = 0; i < w->desired_matrix->nrows; ++i)
11291 struct glyph_row *row = &w->desired_matrix->rows[i];
11292 struct glyph *last;
11293 int row_width;
11295 /* Stop at the first empty row at the end. */
11296 if (!row->enabled_p || !row->displays_text_p)
11297 break;
11299 /* Let the row go over the full width of the frame. */
11300 row->full_width_p = 1;
11302 /* There's a glyph at the end of rows that is used to place
11303 the cursor there. Don't include the width of this glyph. */
11304 if (row->used[TEXT_AREA])
11306 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
11307 row_width = row->pixel_width - last->pixel_width;
11309 else
11310 row_width = row->pixel_width;
11312 height += row->height;
11313 width = max (width, row_width);
11316 /* Add the frame's internal border to the width and height the X
11317 window should have. */
11318 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11319 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11321 /* Move the tooltip window where the mouse pointer is. Resize and
11322 show it. */
11323 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
11325 BLOCK_INPUT;
11326 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11327 root_x, root_y, width, height);
11328 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11329 UNBLOCK_INPUT;
11331 /* Draw into the window. */
11332 w->must_be_updated_p = 1;
11333 update_single_window (w, 1);
11335 /* Restore original current buffer. */
11336 set_buffer_internal_1 (old_buffer);
11337 windows_or_buffers_changed = old_windows_or_buffers_changed;
11339 start_timer:
11340 /* Let the tip disappear after timeout seconds. */
11341 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11342 intern ("x-hide-tip"));
11344 UNGCPRO;
11345 return unbind_to (count, Qnil);
11349 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11350 doc: /* Hide the current tooltip window, if there is any.
11351 Value is t if tooltip was open, nil otherwise. */)
11354 int count;
11355 Lisp_Object deleted, frame, timer;
11356 struct gcpro gcpro1, gcpro2;
11358 /* Return quickly if nothing to do. */
11359 if (NILP (tip_timer) && NILP (tip_frame))
11360 return Qnil;
11362 frame = tip_frame;
11363 timer = tip_timer;
11364 GCPRO2 (frame, timer);
11365 tip_frame = tip_timer = deleted = Qnil;
11367 count = BINDING_STACK_SIZE ();
11368 specbind (Qinhibit_redisplay, Qt);
11369 specbind (Qinhibit_quit, Qt);
11371 if (!NILP (timer))
11372 call1 (Qcancel_timer, timer);
11374 if (FRAMEP (frame))
11376 Fdelete_frame (frame, Qnil);
11377 deleted = Qt;
11379 #ifdef USE_LUCID
11380 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11381 redisplay procedure is not called when a tip frame over menu
11382 items is unmapped. Redisplay the menu manually... */
11384 struct frame *f = SELECTED_FRAME ();
11385 Widget w = f->output_data.x->menubar_widget;
11386 extern void xlwmenu_redisplay P_ ((Widget));
11388 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11389 && w != NULL)
11391 BLOCK_INPUT;
11392 xlwmenu_redisplay (w);
11393 UNBLOCK_INPUT;
11396 #endif /* USE_LUCID */
11399 UNGCPRO;
11400 return unbind_to (count, deleted);
11405 /***********************************************************************
11406 File selection dialog
11407 ***********************************************************************/
11409 #ifdef USE_MOTIF
11411 /* Callback for "OK" and "Cancel" on file selection dialog. */
11413 static void
11414 file_dialog_cb (widget, client_data, call_data)
11415 Widget widget;
11416 XtPointer call_data, client_data;
11418 int *result = (int *) client_data;
11419 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11420 *result = cb->reason;
11424 /* Callback for unmapping a file selection dialog. This is used to
11425 capture the case where a dialog is closed via a window manager's
11426 closer button, for example. Using a XmNdestroyCallback didn't work
11427 in this case. */
11429 static void
11430 file_dialog_unmap_cb (widget, client_data, call_data)
11431 Widget widget;
11432 XtPointer call_data, client_data;
11434 int *result = (int *) client_data;
11435 *result = XmCR_CANCEL;
11439 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11440 doc: /* Read file name, prompting with PROMPT in directory DIR.
11441 Use a file selection dialog.
11442 Select DEFAULT-FILENAME in the dialog's file selection box, if
11443 specified. Don't let the user enter a file name in the file
11444 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11445 (prompt, dir, default_filename, mustmatch)
11446 Lisp_Object prompt, dir, default_filename, mustmatch;
11448 int result;
11449 struct frame *f = SELECTED_FRAME ();
11450 Lisp_Object file = Qnil;
11451 Widget dialog, text, list, help;
11452 Arg al[10];
11453 int ac = 0;
11454 extern XtAppContext Xt_app_con;
11455 XmString dir_xmstring, pattern_xmstring;
11456 int count = specpdl_ptr - specpdl;
11457 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11459 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11460 CHECK_STRING (prompt);
11461 CHECK_STRING (dir);
11463 /* Prevent redisplay. */
11464 specbind (Qinhibit_redisplay, Qt);
11466 BLOCK_INPUT;
11468 /* Create the dialog with PROMPT as title, using DIR as initial
11469 directory and using "*" as pattern. */
11470 dir = Fexpand_file_name (dir, Qnil);
11471 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
11472 pattern_xmstring = XmStringCreateLocalized ("*");
11474 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
11475 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11476 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11477 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11478 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11479 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11480 "fsb", al, ac);
11481 XmStringFree (dir_xmstring);
11482 XmStringFree (pattern_xmstring);
11484 /* Add callbacks for OK and Cancel. */
11485 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11486 (XtPointer) &result);
11487 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11488 (XtPointer) &result);
11489 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11490 (XtPointer) &result);
11492 /* Disable the help button since we can't display help. */
11493 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11494 XtSetSensitive (help, False);
11496 /* Mark OK button as default. */
11497 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11498 XmNshowAsDefault, True, NULL);
11500 /* If MUSTMATCH is non-nil, disable the file entry field of the
11501 dialog, so that the user must select a file from the files list
11502 box. We can't remove it because we wouldn't have a way to get at
11503 the result file name, then. */
11504 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11505 if (!NILP (mustmatch))
11507 Widget label;
11508 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11509 XtSetSensitive (text, False);
11510 XtSetSensitive (label, False);
11513 /* Manage the dialog, so that list boxes get filled. */
11514 XtManageChild (dialog);
11516 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11517 must include the path for this to work. */
11518 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11519 if (STRINGP (default_filename))
11521 XmString default_xmstring;
11522 int item_pos;
11524 default_xmstring
11525 = XmStringCreateLocalized (XSTRING (default_filename)->data);
11527 if (!XmListItemExists (list, default_xmstring))
11529 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11530 XmListAddItem (list, default_xmstring, 0);
11531 item_pos = 0;
11533 else
11534 item_pos = XmListItemPos (list, default_xmstring);
11535 XmStringFree (default_xmstring);
11537 /* Select the item and scroll it into view. */
11538 XmListSelectPos (list, item_pos, True);
11539 XmListSetPos (list, item_pos);
11542 /* Process events until the user presses Cancel or OK. Block
11543 and unblock input here so that we get a chance of processing
11544 expose events. */
11545 UNBLOCK_INPUT;
11546 result = 0;
11547 while (result == 0)
11549 BLOCK_INPUT;
11550 XtAppProcessEvent (Xt_app_con, XtIMAll);
11551 UNBLOCK_INPUT;
11553 BLOCK_INPUT;
11555 /* Get the result. */
11556 if (result == XmCR_OK)
11558 XmString text;
11559 String data;
11561 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11562 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11563 XmStringFree (text);
11564 file = build_string (data);
11565 XtFree (data);
11567 else
11568 file = Qnil;
11570 /* Clean up. */
11571 XtUnmanageChild (dialog);
11572 XtDestroyWidget (dialog);
11573 UNBLOCK_INPUT;
11574 UNGCPRO;
11576 /* Make "Cancel" equivalent to C-g. */
11577 if (NILP (file))
11578 Fsignal (Qquit, Qnil);
11580 return unbind_to (count, file);
11583 #endif /* USE_MOTIF */
11587 /***********************************************************************
11588 Keyboard
11589 ***********************************************************************/
11591 #ifdef HAVE_XKBGETKEYBOARD
11592 #include <X11/XKBlib.h>
11593 #include <X11/keysym.h>
11594 #endif
11596 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11597 Sx_backspace_delete_keys_p, 0, 1, 0,
11598 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11599 FRAME nil means use the selected frame.
11600 Value is t if we know that both keys are present, and are mapped to the
11601 usual X keysyms. */)
11602 (frame)
11603 Lisp_Object frame;
11605 #ifdef HAVE_XKBGETKEYBOARD
11606 XkbDescPtr kb;
11607 struct frame *f = check_x_frame (frame);
11608 Display *dpy = FRAME_X_DISPLAY (f);
11609 Lisp_Object have_keys;
11610 int major, minor, op, event, error;
11612 BLOCK_INPUT;
11614 /* Check library version in case we're dynamically linked. */
11615 major = XkbMajorVersion;
11616 minor = XkbMinorVersion;
11617 if (!XkbLibraryVersion (&major, &minor))
11619 UNBLOCK_INPUT;
11620 return Qnil;
11623 /* Check that the server supports XKB. */
11624 major = XkbMajorVersion;
11625 minor = XkbMinorVersion;
11626 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11628 UNBLOCK_INPUT;
11629 return Qnil;
11632 have_keys = Qnil;
11633 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11634 if (kb)
11636 int delete_keycode = 0, backspace_keycode = 0, i;
11638 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11640 for (i = kb->min_key_code;
11641 (i < kb->max_key_code
11642 && (delete_keycode == 0 || backspace_keycode == 0));
11643 ++i)
11645 /* The XKB symbolic key names can be seen most easily in
11646 the PS file generated by `xkbprint -label name
11647 $DISPLAY'. */
11648 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11649 delete_keycode = i;
11650 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11651 backspace_keycode = i;
11654 XkbFreeNames (kb, 0, True);
11657 XkbFreeClientMap (kb, 0, True);
11659 if (delete_keycode
11660 && backspace_keycode
11661 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11662 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11663 have_keys = Qt;
11665 UNBLOCK_INPUT;
11666 return have_keys;
11667 #else /* not HAVE_XKBGETKEYBOARD */
11668 return Qnil;
11669 #endif /* not HAVE_XKBGETKEYBOARD */
11674 /***********************************************************************
11675 Initialization
11676 ***********************************************************************/
11678 void
11679 syms_of_xfns ()
11681 /* This is zero if not using X windows. */
11682 x_in_use = 0;
11684 /* The section below is built by the lisp expression at the top of the file,
11685 just above where these variables are declared. */
11686 /*&&& init symbols here &&&*/
11687 Qauto_raise = intern ("auto-raise");
11688 staticpro (&Qauto_raise);
11689 Qauto_lower = intern ("auto-lower");
11690 staticpro (&Qauto_lower);
11691 Qbar = intern ("bar");
11692 staticpro (&Qbar);
11693 Qborder_color = intern ("border-color");
11694 staticpro (&Qborder_color);
11695 Qborder_width = intern ("border-width");
11696 staticpro (&Qborder_width);
11697 Qbox = intern ("box");
11698 staticpro (&Qbox);
11699 Qcursor_color = intern ("cursor-color");
11700 staticpro (&Qcursor_color);
11701 Qcursor_type = intern ("cursor-type");
11702 staticpro (&Qcursor_type);
11703 Qgeometry = intern ("geometry");
11704 staticpro (&Qgeometry);
11705 Qicon_left = intern ("icon-left");
11706 staticpro (&Qicon_left);
11707 Qicon_top = intern ("icon-top");
11708 staticpro (&Qicon_top);
11709 Qicon_type = intern ("icon-type");
11710 staticpro (&Qicon_type);
11711 Qicon_name = intern ("icon-name");
11712 staticpro (&Qicon_name);
11713 Qinternal_border_width = intern ("internal-border-width");
11714 staticpro (&Qinternal_border_width);
11715 Qleft = intern ("left");
11716 staticpro (&Qleft);
11717 Qright = intern ("right");
11718 staticpro (&Qright);
11719 Qmouse_color = intern ("mouse-color");
11720 staticpro (&Qmouse_color);
11721 Qnone = intern ("none");
11722 staticpro (&Qnone);
11723 Qparent_id = intern ("parent-id");
11724 staticpro (&Qparent_id);
11725 Qscroll_bar_width = intern ("scroll-bar-width");
11726 staticpro (&Qscroll_bar_width);
11727 Qsuppress_icon = intern ("suppress-icon");
11728 staticpro (&Qsuppress_icon);
11729 Qundefined_color = intern ("undefined-color");
11730 staticpro (&Qundefined_color);
11731 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11732 staticpro (&Qvertical_scroll_bars);
11733 Qvisibility = intern ("visibility");
11734 staticpro (&Qvisibility);
11735 Qwindow_id = intern ("window-id");
11736 staticpro (&Qwindow_id);
11737 Qouter_window_id = intern ("outer-window-id");
11738 staticpro (&Qouter_window_id);
11739 Qx_frame_parameter = intern ("x-frame-parameter");
11740 staticpro (&Qx_frame_parameter);
11741 Qx_resource_name = intern ("x-resource-name");
11742 staticpro (&Qx_resource_name);
11743 Quser_position = intern ("user-position");
11744 staticpro (&Quser_position);
11745 Quser_size = intern ("user-size");
11746 staticpro (&Quser_size);
11747 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11748 staticpro (&Qscroll_bar_foreground);
11749 Qscroll_bar_background = intern ("scroll-bar-background");
11750 staticpro (&Qscroll_bar_background);
11751 Qscreen_gamma = intern ("screen-gamma");
11752 staticpro (&Qscreen_gamma);
11753 Qline_spacing = intern ("line-spacing");
11754 staticpro (&Qline_spacing);
11755 Qcenter = intern ("center");
11756 staticpro (&Qcenter);
11757 Qcompound_text = intern ("compound-text");
11758 staticpro (&Qcompound_text);
11759 Qcancel_timer = intern ("cancel-timer");
11760 staticpro (&Qcancel_timer);
11761 Qwait_for_wm = intern ("wait-for-wm");
11762 staticpro (&Qwait_for_wm);
11763 /* This is the end of symbol initialization. */
11765 /* Text property `display' should be nonsticky by default. */
11766 Vtext_property_default_nonsticky
11767 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11770 Qlaplace = intern ("laplace");
11771 staticpro (&Qlaplace);
11772 Qemboss = intern ("emboss");
11773 staticpro (&Qemboss);
11774 Qedge_detection = intern ("edge-detection");
11775 staticpro (&Qedge_detection);
11776 Qheuristic = intern ("heuristic");
11777 staticpro (&Qheuristic);
11778 QCmatrix = intern (":matrix");
11779 staticpro (&QCmatrix);
11780 QCcolor_adjustment = intern (":color-adjustment");
11781 staticpro (&QCcolor_adjustment);
11782 QCmask = intern (":mask");
11783 staticpro (&QCmask);
11785 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11786 staticpro (&Qface_set_after_frame_default);
11788 Fput (Qundefined_color, Qerror_conditions,
11789 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11790 Fput (Qundefined_color, Qerror_message,
11791 build_string ("Undefined color"));
11793 init_x_parm_symbols ();
11795 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11796 doc: /* Non-nil means always draw a cross over disabled images.
11797 Disabled images are those having an `:conversion disabled' property.
11798 A cross is always drawn on black & white displays. */);
11799 cross_disabled_images = 0;
11801 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11802 doc: /* List of directories to search for bitmap files for X. */);
11803 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11805 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11806 doc: /* The shape of the pointer when over text.
11807 Changing the value does not affect existing frames
11808 unless you set the mouse color. */);
11809 Vx_pointer_shape = Qnil;
11811 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11812 doc: /* The name Emacs uses to look up X resources.
11813 `x-get-resource' uses this as the first component of the instance name
11814 when requesting resource values.
11815 Emacs initially sets `x-resource-name' to the name under which Emacs
11816 was invoked, or to the value specified with the `-name' or `-rn'
11817 switches, if present.
11819 It may be useful to bind this variable locally around a call
11820 to `x-get-resource'. See also the variable `x-resource-class'. */);
11821 Vx_resource_name = Qnil;
11823 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11824 doc: /* The class Emacs uses to look up X resources.
11825 `x-get-resource' uses this as the first component of the instance class
11826 when requesting resource values.
11828 Emacs initially sets `x-resource-class' to "Emacs".
11830 Setting this variable permanently is not a reasonable thing to do,
11831 but binding this variable locally around a call to `x-get-resource'
11832 is a reasonable practice. See also the variable `x-resource-name'. */);
11833 Vx_resource_class = build_string (EMACS_CLASS);
11835 #if 0 /* This doesn't really do anything. */
11836 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11837 doc: /* The shape of the pointer when not over text.
11838 This variable takes effect when you create a new frame
11839 or when you set the mouse color. */);
11840 #endif
11841 Vx_nontext_pointer_shape = Qnil;
11843 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
11844 doc: /* The shape of the pointer when Emacs is busy.
11845 This variable takes effect when you create a new frame
11846 or when you set the mouse color. */);
11847 Vx_hourglass_pointer_shape = Qnil;
11849 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
11850 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11851 display_hourglass_p = 1;
11853 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
11854 doc: /* *Seconds to wait before displaying an hourglass pointer.
11855 Value must be an integer or float. */);
11856 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
11858 #if 0 /* This doesn't really do anything. */
11859 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11860 doc: /* The shape of the pointer when over the mode line.
11861 This variable takes effect when you create a new frame
11862 or when you set the mouse color. */);
11863 #endif
11864 Vx_mode_pointer_shape = Qnil;
11866 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11867 &Vx_sensitive_text_pointer_shape,
11868 doc: /* The shape of the pointer when over mouse-sensitive text.
11869 This variable takes effect when you create a new frame
11870 or when you set the mouse color. */);
11871 Vx_sensitive_text_pointer_shape = Qnil;
11873 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11874 &Vx_window_horizontal_drag_shape,
11875 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
11876 This variable takes effect when you create a new frame
11877 or when you set the mouse color. */);
11878 Vx_window_horizontal_drag_shape = Qnil;
11880 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11881 doc: /* A string indicating the foreground color of the cursor box. */);
11882 Vx_cursor_fore_pixel = Qnil;
11884 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
11885 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
11886 Text larger than this is clipped. */);
11887 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
11889 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11890 doc: /* Non-nil if no X window manager is in use.
11891 Emacs doesn't try to figure this out; this is always nil
11892 unless you set it to something else. */);
11893 /* We don't have any way to find this out, so set it to nil
11894 and maybe the user would like to set it to t. */
11895 Vx_no_window_manager = Qnil;
11897 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11898 &Vx_pixel_size_width_font_regexp,
11899 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
11901 Since Emacs gets width of a font matching with this regexp from
11902 PIXEL_SIZE field of the name, font finding mechanism gets faster for
11903 such a font. This is especially effective for such large fonts as
11904 Chinese, Japanese, and Korean. */);
11905 Vx_pixel_size_width_font_regexp = Qnil;
11907 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11908 doc: /* Time after which cached images are removed from the cache.
11909 When an image has not been displayed this many seconds, remove it
11910 from the image cache. Value must be an integer or nil with nil
11911 meaning don't clear the cache. */);
11912 Vimage_cache_eviction_delay = make_number (30 * 60);
11914 #ifdef USE_X_TOOLKIT
11915 Fprovide (intern ("x-toolkit"), Qnil);
11916 #ifdef USE_MOTIF
11917 Fprovide (intern ("motif"), Qnil);
11919 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
11920 doc: /* Version info for LessTif/Motif. */);
11921 Vmotif_version_string = build_string (XmVERSION_STRING);
11922 #endif /* USE_MOTIF */
11923 #endif /* USE_X_TOOLKIT */
11925 defsubr (&Sx_get_resource);
11927 /* X window properties. */
11928 defsubr (&Sx_change_window_property);
11929 defsubr (&Sx_delete_window_property);
11930 defsubr (&Sx_window_property);
11932 defsubr (&Sxw_display_color_p);
11933 defsubr (&Sx_display_grayscale_p);
11934 defsubr (&Sxw_color_defined_p);
11935 defsubr (&Sxw_color_values);
11936 defsubr (&Sx_server_max_request_size);
11937 defsubr (&Sx_server_vendor);
11938 defsubr (&Sx_server_version);
11939 defsubr (&Sx_display_pixel_width);
11940 defsubr (&Sx_display_pixel_height);
11941 defsubr (&Sx_display_mm_width);
11942 defsubr (&Sx_display_mm_height);
11943 defsubr (&Sx_display_screens);
11944 defsubr (&Sx_display_planes);
11945 defsubr (&Sx_display_color_cells);
11946 defsubr (&Sx_display_visual_class);
11947 defsubr (&Sx_display_backing_store);
11948 defsubr (&Sx_display_save_under);
11949 defsubr (&Sx_parse_geometry);
11950 defsubr (&Sx_create_frame);
11951 defsubr (&Sx_open_connection);
11952 defsubr (&Sx_close_connection);
11953 defsubr (&Sx_display_list);
11954 defsubr (&Sx_synchronize);
11955 defsubr (&Sx_focus_frame);
11956 defsubr (&Sx_backspace_delete_keys_p);
11958 /* Setting callback functions for fontset handler. */
11959 get_font_info_func = x_get_font_info;
11961 #if 0 /* This function pointer doesn't seem to be used anywhere.
11962 And the pointer assigned has the wrong type, anyway. */
11963 list_fonts_func = x_list_fonts;
11964 #endif
11966 load_font_func = x_load_font;
11967 find_ccl_program_func = x_find_ccl_program;
11968 query_font_func = x_query_font;
11969 set_frame_fontset_func = x_set_font;
11970 check_window_system_func = check_x;
11972 /* Images. */
11973 Qxbm = intern ("xbm");
11974 staticpro (&Qxbm);
11975 QCtype = intern (":type");
11976 staticpro (&QCtype);
11977 QCconversion = intern (":conversion");
11978 staticpro (&QCconversion);
11979 QCheuristic_mask = intern (":heuristic-mask");
11980 staticpro (&QCheuristic_mask);
11981 QCcolor_symbols = intern (":color-symbols");
11982 staticpro (&QCcolor_symbols);
11983 QCascent = intern (":ascent");
11984 staticpro (&QCascent);
11985 QCmargin = intern (":margin");
11986 staticpro (&QCmargin);
11987 QCrelief = intern (":relief");
11988 staticpro (&QCrelief);
11989 Qpostscript = intern ("postscript");
11990 staticpro (&Qpostscript);
11991 QCloader = intern (":loader");
11992 staticpro (&QCloader);
11993 QCbounding_box = intern (":bounding-box");
11994 staticpro (&QCbounding_box);
11995 QCpt_width = intern (":pt-width");
11996 staticpro (&QCpt_width);
11997 QCpt_height = intern (":pt-height");
11998 staticpro (&QCpt_height);
11999 QCindex = intern (":index");
12000 staticpro (&QCindex);
12001 Qpbm = intern ("pbm");
12002 staticpro (&Qpbm);
12004 #if HAVE_XPM
12005 Qxpm = intern ("xpm");
12006 staticpro (&Qxpm);
12007 #endif
12009 #if HAVE_JPEG
12010 Qjpeg = intern ("jpeg");
12011 staticpro (&Qjpeg);
12012 #endif
12014 #if HAVE_TIFF
12015 Qtiff = intern ("tiff");
12016 staticpro (&Qtiff);
12017 #endif
12019 #if HAVE_GIF
12020 Qgif = intern ("gif");
12021 staticpro (&Qgif);
12022 #endif
12024 #if HAVE_PNG
12025 Qpng = intern ("png");
12026 staticpro (&Qpng);
12027 #endif
12029 defsubr (&Sclear_image_cache);
12030 defsubr (&Simage_size);
12031 defsubr (&Simage_mask_p);
12033 hourglass_atimer = NULL;
12034 hourglass_shown_p = 0;
12036 defsubr (&Sx_show_tip);
12037 defsubr (&Sx_hide_tip);
12038 tip_timer = Qnil;
12039 staticpro (&tip_timer);
12040 tip_frame = Qnil;
12041 staticpro (&tip_frame);
12043 last_show_tip_args = Qnil;
12044 staticpro (&last_show_tip_args);
12046 #ifdef USE_MOTIF
12047 defsubr (&Sx_file_dialog);
12048 #endif
12052 void
12053 init_xfns ()
12055 image_types = NULL;
12056 Vimage_types = Qnil;
12058 define_image_type (&xbm_type);
12059 define_image_type (&gs_type);
12060 define_image_type (&pbm_type);
12062 #if HAVE_XPM
12063 define_image_type (&xpm_type);
12064 #endif
12066 #if HAVE_JPEG
12067 define_image_type (&jpeg_type);
12068 #endif
12070 #if HAVE_TIFF
12071 define_image_type (&tiff_type);
12072 #endif
12074 #if HAVE_GIF
12075 define_image_type (&gif_type);
12076 #endif
12078 #if HAVE_PNG
12079 define_image_type (&png_type);
12080 #endif
12083 #endif /* HAVE_X_WINDOWS */