(ffap): Don't hide it behind the autoload-cookie.
[emacs.git] / src / xfns.c
blob7bf02c286a316b948c295bf4a91ca15cb9946722
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, Qhbar;
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;
222 Lisp_Object Qfullscreen;
223 Lisp_Object Qfullwidth;
224 Lisp_Object Qfullheight;
225 Lisp_Object Qfullboth;
227 /* The below are defined in frame.c. */
229 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
230 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
231 extern Lisp_Object Qtool_bar_lines;
233 extern Lisp_Object Vwindow_system_version;
235 Lisp_Object Qface_set_after_frame_default;
237 #if GLYPH_DEBUG
238 int image_cache_refcount, dpyinfo_refcount;
239 #endif
243 /* Error if we are not connected to X. */
245 void
246 check_x ()
248 if (! x_in_use)
249 error ("X windows are not in use or not initialized");
252 /* Nonzero if we can use mouse menus.
253 You should not call this unless HAVE_MENUS is defined. */
256 have_menus_p ()
258 return x_in_use;
261 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
262 and checking validity for X. */
264 FRAME_PTR
265 check_x_frame (frame)
266 Lisp_Object frame;
268 FRAME_PTR f;
270 if (NILP (frame))
271 frame = selected_frame;
272 CHECK_LIVE_FRAME (frame);
273 f = XFRAME (frame);
274 if (! FRAME_X_P (f))
275 error ("Non-X frame used");
276 return f;
279 /* Let the user specify an X display with a frame.
280 nil stands for the selected frame--or, if that is not an X frame,
281 the first X display on the list. */
283 static struct x_display_info *
284 check_x_display_info (frame)
285 Lisp_Object frame;
287 struct x_display_info *dpyinfo = NULL;
289 if (NILP (frame))
291 struct frame *sf = XFRAME (selected_frame);
293 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
294 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
295 else if (x_display_list != 0)
296 dpyinfo = x_display_list;
297 else
298 error ("X windows are not in use or not initialized");
300 else if (STRINGP (frame))
301 dpyinfo = x_display_info_for_name (frame);
302 else
304 FRAME_PTR f;
306 CHECK_LIVE_FRAME (frame);
307 f = XFRAME (frame);
308 if (! FRAME_X_P (f))
309 error ("Non-X frame used");
310 dpyinfo = FRAME_X_DISPLAY_INFO (f);
313 return dpyinfo;
317 /* Return the Emacs frame-object corresponding to an X window.
318 It could be the frame's main window or an icon window. */
320 /* This function can be called during GC, so use GC_xxx type test macros. */
322 struct frame *
323 x_window_to_frame (dpyinfo, wdesc)
324 struct x_display_info *dpyinfo;
325 int wdesc;
327 Lisp_Object tail, frame;
328 struct frame *f;
330 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
332 frame = XCAR (tail);
333 if (!GC_FRAMEP (frame))
334 continue;
335 f = XFRAME (frame);
336 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
337 continue;
338 if (f->output_data.x->hourglass_window == wdesc)
339 return f;
340 #ifdef USE_X_TOOLKIT
341 if ((f->output_data.x->edit_widget
342 && XtWindow (f->output_data.x->edit_widget) == wdesc)
343 /* A tooltip frame? */
344 || (!f->output_data.x->edit_widget
345 && FRAME_X_WINDOW (f) == wdesc)
346 || f->output_data.x->icon_desc == wdesc)
347 return f;
348 #else /* not USE_X_TOOLKIT */
349 if (FRAME_X_WINDOW (f) == wdesc
350 || f->output_data.x->icon_desc == wdesc)
351 return f;
352 #endif /* not USE_X_TOOLKIT */
354 return 0;
357 #ifdef USE_X_TOOLKIT
358 /* Like x_window_to_frame but also compares the window with the widget's
359 windows. */
361 struct frame *
362 x_any_window_to_frame (dpyinfo, wdesc)
363 struct x_display_info *dpyinfo;
364 int wdesc;
366 Lisp_Object tail, frame;
367 struct frame *f, *found;
368 struct x_output *x;
370 found = NULL;
371 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
373 frame = XCAR (tail);
374 if (!GC_FRAMEP (frame))
375 continue;
377 f = XFRAME (frame);
378 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
380 /* This frame matches if the window is any of its widgets. */
381 x = f->output_data.x;
382 if (x->hourglass_window == wdesc)
383 found = f;
384 else if (x->widget)
386 if (wdesc == XtWindow (x->widget)
387 || wdesc == XtWindow (x->column_widget)
388 || wdesc == XtWindow (x->edit_widget))
389 found = f;
390 /* Match if the window is this frame's menubar. */
391 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
392 found = f;
394 else if (FRAME_X_WINDOW (f) == wdesc)
395 /* A tooltip frame. */
396 found = f;
400 return found;
403 /* Likewise, but exclude the menu bar widget. */
405 struct frame *
406 x_non_menubar_window_to_frame (dpyinfo, wdesc)
407 struct x_display_info *dpyinfo;
408 int wdesc;
410 Lisp_Object tail, frame;
411 struct frame *f;
412 struct x_output *x;
414 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
416 frame = XCAR (tail);
417 if (!GC_FRAMEP (frame))
418 continue;
419 f = XFRAME (frame);
420 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
421 continue;
422 x = f->output_data.x;
423 /* This frame matches if the window is any of its widgets. */
424 if (x->hourglass_window == wdesc)
425 return f;
426 else if (x->widget)
428 if (wdesc == XtWindow (x->widget)
429 || wdesc == XtWindow (x->column_widget)
430 || wdesc == XtWindow (x->edit_widget))
431 return f;
433 else if (FRAME_X_WINDOW (f) == wdesc)
434 /* A tooltip frame. */
435 return f;
437 return 0;
440 /* Likewise, but consider only the menu bar widget. */
442 struct frame *
443 x_menubar_window_to_frame (dpyinfo, wdesc)
444 struct x_display_info *dpyinfo;
445 int wdesc;
447 Lisp_Object tail, frame;
448 struct frame *f;
449 struct x_output *x;
451 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
453 frame = XCAR (tail);
454 if (!GC_FRAMEP (frame))
455 continue;
456 f = XFRAME (frame);
457 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
458 continue;
459 x = f->output_data.x;
460 /* Match if the window is this frame's menubar. */
461 if (x->menubar_widget
462 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
463 return f;
465 return 0;
468 /* Return the frame whose principal (outermost) window is WDESC.
469 If WDESC is some other (smaller) window, we return 0. */
471 struct frame *
472 x_top_window_to_frame (dpyinfo, wdesc)
473 struct x_display_info *dpyinfo;
474 int wdesc;
476 Lisp_Object tail, frame;
477 struct frame *f;
478 struct x_output *x;
480 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
482 frame = XCAR (tail);
483 if (!GC_FRAMEP (frame))
484 continue;
485 f = XFRAME (frame);
486 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
487 continue;
488 x = f->output_data.x;
490 if (x->widget)
492 /* This frame matches if the window is its topmost widget. */
493 if (wdesc == XtWindow (x->widget))
494 return f;
495 #if 0 /* I don't know why it did this,
496 but it seems logically wrong,
497 and it causes trouble for MapNotify events. */
498 /* Match if the window is this frame's menubar. */
499 if (x->menubar_widget
500 && wdesc == XtWindow (x->menubar_widget))
501 return f;
502 #endif
504 else if (FRAME_X_WINDOW (f) == wdesc)
505 /* Tooltip frame. */
506 return f;
508 return 0;
510 #endif /* USE_X_TOOLKIT */
514 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
515 id, which is just an int that this section returns. Bitmaps are
516 reference counted so they can be shared among frames.
518 Bitmap indices are guaranteed to be > 0, so a negative number can
519 be used to indicate no bitmap.
521 If you use x_create_bitmap_from_data, then you must keep track of
522 the bitmaps yourself. That is, creating a bitmap from the same
523 data more than once will not be caught. */
526 /* Functions to access the contents of a bitmap, given an id. */
529 x_bitmap_height (f, id)
530 FRAME_PTR f;
531 int id;
533 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
537 x_bitmap_width (f, id)
538 FRAME_PTR f;
539 int id;
541 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
545 x_bitmap_pixmap (f, id)
546 FRAME_PTR f;
547 int id;
549 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
553 /* Allocate a new bitmap record. Returns index of new record. */
555 static int
556 x_allocate_bitmap_record (f)
557 FRAME_PTR f;
559 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
560 int i;
562 if (dpyinfo->bitmaps == NULL)
564 dpyinfo->bitmaps_size = 10;
565 dpyinfo->bitmaps
566 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
567 dpyinfo->bitmaps_last = 1;
568 return 1;
571 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
572 return ++dpyinfo->bitmaps_last;
574 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
575 if (dpyinfo->bitmaps[i].refcount == 0)
576 return i + 1;
578 dpyinfo->bitmaps_size *= 2;
579 dpyinfo->bitmaps
580 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
581 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
582 return ++dpyinfo->bitmaps_last;
585 /* Add one reference to the reference count of the bitmap with id ID. */
587 void
588 x_reference_bitmap (f, id)
589 FRAME_PTR f;
590 int id;
592 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
595 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
598 x_create_bitmap_from_data (f, bits, width, height)
599 struct frame *f;
600 char *bits;
601 unsigned int width, height;
603 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
604 Pixmap bitmap;
605 int id;
607 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
608 bits, width, height);
610 if (! bitmap)
611 return -1;
613 id = x_allocate_bitmap_record (f);
614 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
615 dpyinfo->bitmaps[id - 1].file = NULL;
616 dpyinfo->bitmaps[id - 1].refcount = 1;
617 dpyinfo->bitmaps[id - 1].depth = 1;
618 dpyinfo->bitmaps[id - 1].height = height;
619 dpyinfo->bitmaps[id - 1].width = width;
621 return id;
624 /* Create bitmap from file FILE for frame F. */
627 x_create_bitmap_from_file (f, file)
628 struct frame *f;
629 Lisp_Object file;
631 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
632 unsigned int width, height;
633 Pixmap bitmap;
634 int xhot, yhot, result, id;
635 Lisp_Object found;
636 int fd;
637 char *filename;
639 /* Look for an existing bitmap with the same name. */
640 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
642 if (dpyinfo->bitmaps[id].refcount
643 && dpyinfo->bitmaps[id].file
644 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
646 ++dpyinfo->bitmaps[id].refcount;
647 return id + 1;
651 /* Search bitmap-file-path for the file, if appropriate. */
652 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
653 if (fd < 0)
654 return -1;
655 emacs_close (fd);
657 filename = (char *) XSTRING (found)->data;
659 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
660 filename, &width, &height, &bitmap, &xhot, &yhot);
661 if (result != BitmapSuccess)
662 return -1;
664 id = x_allocate_bitmap_record (f);
665 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
666 dpyinfo->bitmaps[id - 1].refcount = 1;
667 dpyinfo->bitmaps[id - 1].file
668 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
669 dpyinfo->bitmaps[id - 1].depth = 1;
670 dpyinfo->bitmaps[id - 1].height = height;
671 dpyinfo->bitmaps[id - 1].width = width;
672 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
674 return id;
677 /* Remove reference to bitmap with id number ID. */
679 void
680 x_destroy_bitmap (f, id)
681 FRAME_PTR f;
682 int id;
684 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
686 if (id > 0)
688 --dpyinfo->bitmaps[id - 1].refcount;
689 if (dpyinfo->bitmaps[id - 1].refcount == 0)
691 BLOCK_INPUT;
692 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
693 if (dpyinfo->bitmaps[id - 1].file)
695 xfree (dpyinfo->bitmaps[id - 1].file);
696 dpyinfo->bitmaps[id - 1].file = NULL;
698 UNBLOCK_INPUT;
703 /* Free all the bitmaps for the display specified by DPYINFO. */
705 static void
706 x_destroy_all_bitmaps (dpyinfo)
707 struct x_display_info *dpyinfo;
709 int i;
710 for (i = 0; i < dpyinfo->bitmaps_last; i++)
711 if (dpyinfo->bitmaps[i].refcount > 0)
713 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
714 if (dpyinfo->bitmaps[i].file)
715 xfree (dpyinfo->bitmaps[i].file);
717 dpyinfo->bitmaps_last = 0;
720 /* Connect the frame-parameter names for X frames
721 to the ways of passing the parameter values to the window system.
723 The name of a parameter, as a Lisp symbol,
724 has an `x-frame-parameter' property which is an integer in Lisp
725 that is an index in this table. */
727 struct x_frame_parm_table
729 char *name;
730 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
733 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
734 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
735 static void x_change_window_heights P_ ((Lisp_Object, int));
736 static void x_disable_image P_ ((struct frame *, struct image *));
737 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
750 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
752 Lisp_Object));
753 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
757 Lisp_Object));
758 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
760 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
761 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
762 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
763 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
764 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
765 Lisp_Object));
766 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
767 Lisp_Object));
768 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
769 Lisp_Object,
770 Lisp_Object,
771 char *, char *,
772 int));
773 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
774 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
775 Lisp_Object));
776 static void init_color_table P_ ((void));
777 static void free_color_table P_ ((void));
778 static unsigned long *colors_in_color_table P_ ((int *n));
779 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
780 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
784 static struct x_frame_parm_table x_frame_parms[] =
786 {"auto-raise", x_set_autoraise},
787 {"auto-lower", x_set_autolower},
788 {"background-color", x_set_background_color},
789 {"border-color", x_set_border_color},
790 {"border-width", x_set_border_width},
791 {"cursor-color", x_set_cursor_color},
792 {"cursor-type", x_set_cursor_type},
793 {"font", x_set_font},
794 {"foreground-color", x_set_foreground_color},
795 {"icon-name", x_set_icon_name},
796 {"icon-type", x_set_icon_type},
797 {"internal-border-width", x_set_internal_border_width},
798 {"menu-bar-lines", x_set_menu_bar_lines},
799 {"mouse-color", x_set_mouse_color},
800 {"name", x_explicitly_set_name},
801 {"scroll-bar-width", x_set_scroll_bar_width},
802 {"title", x_set_title},
803 {"unsplittable", x_set_unsplittable},
804 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
805 {"visibility", x_set_visibility},
806 {"tool-bar-lines", x_set_tool_bar_lines},
807 {"scroll-bar-foreground", x_set_scroll_bar_foreground},
808 {"scroll-bar-background", x_set_scroll_bar_background},
809 {"screen-gamma", x_set_screen_gamma},
810 {"line-spacing", x_set_line_spacing},
811 {"left-fringe", x_set_fringe_width},
812 {"right-fringe", x_set_fringe_width},
813 {"wait-for-wm", x_set_wait_for_wm},
814 {"fullscreen", x_set_fullscreen},
818 /* Attach the `x-frame-parameter' properties to
819 the Lisp symbol names of parameters relevant to X. */
821 void
822 init_x_parm_symbols ()
824 int i;
826 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
827 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
828 make_number (i));
832 /* Really try to move where we want to be in case of fullscreen. Some WMs
833 moves the window where we tell them. Some (mwm, twm) moves the outer
834 window manager window there instead.
835 Try to compensate for those WM here. */
836 static void
837 x_fullscreen_move (f, new_top, new_left)
838 struct frame *f;
839 int new_top;
840 int new_left;
842 if (new_top != f->output_data.x->top_pos
843 || new_left != f->output_data.x->left_pos)
845 int move_x = new_left + f->output_data.x->x_pixels_outer_diff;
846 int move_y = new_top + f->output_data.x->y_pixels_outer_diff;
848 f->output_data.x->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
849 x_set_offset (f, move_x, move_y, 1);
853 /* Change the parameters of frame F as specified by ALIST.
854 If a parameter is not specially recognized, do nothing special;
855 otherwise call the `x_set_...' function for that parameter.
856 Except for certain geometry properties, always call store_frame_param
857 to store the new value in the parameter alist. */
859 void
860 x_set_frame_parameters (f, alist)
861 FRAME_PTR f;
862 Lisp_Object alist;
864 Lisp_Object tail;
866 /* If both of these parameters are present, it's more efficient to
867 set them both at once. So we wait until we've looked at the
868 entire list before we set them. */
869 int width, height;
871 /* Same here. */
872 Lisp_Object left, top;
874 /* Same with these. */
875 Lisp_Object icon_left, icon_top;
877 /* Record in these vectors all the parms specified. */
878 Lisp_Object *parms;
879 Lisp_Object *values;
880 int i, p;
881 int left_no_change = 0, top_no_change = 0;
882 int icon_left_no_change = 0, icon_top_no_change = 0;
883 int fullscreen_is_being_set = 0;
885 struct gcpro gcpro1, gcpro2;
887 i = 0;
888 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
889 i++;
891 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
892 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
894 /* Extract parm names and values into those vectors. */
896 i = 0;
897 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
899 Lisp_Object elt;
901 elt = Fcar (tail);
902 parms[i] = Fcar (elt);
903 values[i] = Fcdr (elt);
904 i++;
906 /* TAIL and ALIST are not used again below here. */
907 alist = tail = Qnil;
909 GCPRO2 (*parms, *values);
910 gcpro1.nvars = i;
911 gcpro2.nvars = i;
913 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
914 because their values appear in VALUES and strings are not valid. */
915 top = left = Qunbound;
916 icon_left = icon_top = Qunbound;
918 /* Provide default values for HEIGHT and WIDTH. */
919 if (FRAME_NEW_WIDTH (f))
920 width = FRAME_NEW_WIDTH (f);
921 else
922 width = FRAME_WIDTH (f);
924 if (FRAME_NEW_HEIGHT (f))
925 height = FRAME_NEW_HEIGHT (f);
926 else
927 height = FRAME_HEIGHT (f);
929 /* Process foreground_color and background_color before anything else.
930 They are independent of other properties, but other properties (e.g.,
931 cursor_color) are dependent upon them. */
932 /* Process default font as well, since fringe widths depends on it. */
933 /* Also, process fullscreen, width and height depend upon that */
934 for (p = 0; p < i; p++)
936 Lisp_Object prop, val;
938 prop = parms[p];
939 val = values[p];
940 if (EQ (prop, Qforeground_color)
941 || EQ (prop, Qbackground_color)
942 || EQ (prop, Qfont)
943 || EQ (prop, Qfullscreen))
945 register Lisp_Object param_index, old_value;
947 old_value = get_frame_param (f, prop);
948 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
950 if (NILP (Fequal (val, old_value)))
952 store_frame_param (f, prop, val);
954 param_index = Fget (prop, Qx_frame_parameter);
955 if (NATNUMP (param_index)
956 && (XFASTINT (param_index)
957 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
958 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
963 /* Now process them in reverse of specified order. */
964 for (i--; i >= 0; i--)
966 Lisp_Object prop, val;
968 prop = parms[i];
969 val = values[i];
971 if (EQ (prop, Qwidth) && NUMBERP (val))
972 width = XFASTINT (val);
973 else if (EQ (prop, Qheight) && NUMBERP (val))
974 height = XFASTINT (val);
975 else if (EQ (prop, Qtop))
976 top = val;
977 else if (EQ (prop, Qleft))
978 left = val;
979 else if (EQ (prop, Qicon_top))
980 icon_top = val;
981 else if (EQ (prop, Qicon_left))
982 icon_left = val;
983 else if (EQ (prop, Qforeground_color)
984 || EQ (prop, Qbackground_color)
985 || EQ (prop, Qfont)
986 || EQ (prop, Qfullscreen))
987 /* Processed above. */
988 continue;
989 else
991 register Lisp_Object param_index, old_value;
993 old_value = get_frame_param (f, prop);
995 store_frame_param (f, prop, val);
997 param_index = Fget (prop, Qx_frame_parameter);
998 if (NATNUMP (param_index)
999 && (XFASTINT (param_index)
1000 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
1001 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
1005 /* Don't die if just one of these was set. */
1006 if (EQ (left, Qunbound))
1008 left_no_change = 1;
1009 if (f->output_data.x->left_pos < 0)
1010 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
1011 else
1012 XSETINT (left, f->output_data.x->left_pos);
1014 if (EQ (top, Qunbound))
1016 top_no_change = 1;
1017 if (f->output_data.x->top_pos < 0)
1018 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
1019 else
1020 XSETINT (top, f->output_data.x->top_pos);
1023 /* If one of the icon positions was not set, preserve or default it. */
1024 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
1026 icon_left_no_change = 1;
1027 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
1028 if (NILP (icon_left))
1029 XSETINT (icon_left, 0);
1031 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
1033 icon_top_no_change = 1;
1034 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
1035 if (NILP (icon_top))
1036 XSETINT (icon_top, 0);
1039 if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
1041 /* If the frame is visible already and the fullscreen parameter is
1042 being set, it is too late to set WM manager hints to specify
1043 size and position.
1044 Here we first get the width, height and position that applies to
1045 fullscreen. We then move the frame to the appropriate
1046 position. Resize of the frame is taken care of in the code after
1047 this if-statement. */
1048 int new_left, new_top;
1050 x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
1051 x_fullscreen_move (f, new_top, new_left);
1054 /* Don't set these parameters unless they've been explicitly
1055 specified. The window might be mapped or resized while we're in
1056 this function, and we don't want to override that unless the lisp
1057 code has asked for it.
1059 Don't set these parameters unless they actually differ from the
1060 window's current parameters; the window may not actually exist
1061 yet. */
1063 Lisp_Object frame;
1065 check_frame_size (f, &height, &width);
1067 XSETFRAME (frame, f);
1069 if (width != FRAME_WIDTH (f)
1070 || height != FRAME_HEIGHT (f)
1071 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1072 Fset_frame_size (frame, make_number (width), make_number (height));
1074 if ((!NILP (left) || !NILP (top))
1075 && ! (left_no_change && top_no_change)
1076 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1077 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1079 int leftpos = 0;
1080 int toppos = 0;
1082 /* Record the signs. */
1083 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1084 if (EQ (left, Qminus))
1085 f->output_data.x->size_hint_flags |= XNegative;
1086 else if (INTEGERP (left))
1088 leftpos = XINT (left);
1089 if (leftpos < 0)
1090 f->output_data.x->size_hint_flags |= XNegative;
1092 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1093 && CONSP (XCDR (left))
1094 && INTEGERP (XCAR (XCDR (left))))
1096 leftpos = - XINT (XCAR (XCDR (left)));
1097 f->output_data.x->size_hint_flags |= XNegative;
1099 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1100 && CONSP (XCDR (left))
1101 && INTEGERP (XCAR (XCDR (left))))
1103 leftpos = XINT (XCAR (XCDR (left)));
1106 if (EQ (top, Qminus))
1107 f->output_data.x->size_hint_flags |= YNegative;
1108 else if (INTEGERP (top))
1110 toppos = XINT (top);
1111 if (toppos < 0)
1112 f->output_data.x->size_hint_flags |= YNegative;
1114 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1115 && CONSP (XCDR (top))
1116 && INTEGERP (XCAR (XCDR (top))))
1118 toppos = - XINT (XCAR (XCDR (top)));
1119 f->output_data.x->size_hint_flags |= YNegative;
1121 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1122 && CONSP (XCDR (top))
1123 && INTEGERP (XCAR (XCDR (top))))
1125 toppos = XINT (XCAR (XCDR (top)));
1129 /* Store the numeric value of the position. */
1130 f->output_data.x->top_pos = toppos;
1131 f->output_data.x->left_pos = leftpos;
1133 f->output_data.x->win_gravity = NorthWestGravity;
1135 /* Actually set that position, and convert to absolute. */
1136 x_set_offset (f, leftpos, toppos, -1);
1139 if ((!NILP (icon_left) || !NILP (icon_top))
1140 && ! (icon_left_no_change && icon_top_no_change))
1141 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1144 UNGCPRO;
1147 /* Store the screen positions of frame F into XPTR and YPTR.
1148 These are the positions of the containing window manager window,
1149 not Emacs's own window. */
1151 void
1152 x_real_positions (f, xptr, yptr)
1153 FRAME_PTR f;
1154 int *xptr, *yptr;
1156 int win_x, win_y, outer_x, outer_y;
1157 int real_x = 0, real_y = 0;
1158 int had_errors = 0;
1159 Window win = f->output_data.x->parent_desc;
1161 int count;
1163 BLOCK_INPUT;
1165 count = x_catch_errors (FRAME_X_DISPLAY (f));
1167 if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
1168 win = FRAME_OUTER_WINDOW (f);
1170 /* This loop traverses up the containment tree until we hit the root
1171 window. Window managers may intersect many windows between our window
1172 and the root window. The window we find just before the root window
1173 should be the outer WM window. */
1174 for (;;)
1176 Window wm_window, rootw;
1177 Window *tmp_children;
1178 unsigned int tmp_nchildren;
1179 int success;
1181 success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
1182 &wm_window, &tmp_children, &tmp_nchildren);
1184 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
1186 /* Don't free tmp_children if XQueryTree failed. */
1187 if (! success)
1188 break;
1190 XFree ((char *) tmp_children);
1192 if (wm_window == rootw || had_errors)
1193 break;
1195 win = wm_window;
1198 if (! had_errors)
1200 int ign;
1201 Window child, rootw;
1203 /* Get the real coordinates for the WM window upper left corner */
1204 XGetGeometry (FRAME_X_DISPLAY (f), win,
1205 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
1207 /* Translate real coordinates to coordinates relative to our
1208 window. For our window, the upper left corner is 0, 0.
1209 Since the upper left corner of the WM window is outside
1210 our window, win_x and win_y will be negative:
1212 ------------------ ---> x
1213 | title |
1214 | ----------------- v y
1215 | | our window
1217 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1219 /* From-window, to-window. */
1220 FRAME_X_DISPLAY_INFO (f)->root_window,
1221 FRAME_X_WINDOW (f),
1223 /* From-position, to-position. */
1224 real_x, real_y, &win_x, &win_y,
1226 /* Child of win. */
1227 &child);
1229 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
1231 outer_x = win_x;
1232 outer_y = win_y;
1234 else
1236 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1238 /* From-window, to-window. */
1239 FRAME_X_DISPLAY_INFO (f)->root_window,
1240 FRAME_OUTER_WINDOW (f),
1242 /* From-position, to-position. */
1243 real_x, real_y, &outer_x, &outer_y,
1245 /* Child of win. */
1246 &child);
1249 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
1252 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1254 UNBLOCK_INPUT;
1256 if (had_errors) return;
1258 f->output_data.x->x_pixels_diff = -win_x;
1259 f->output_data.x->y_pixels_diff = -win_y;
1260 f->output_data.x->x_pixels_outer_diff = -outer_x;
1261 f->output_data.x->y_pixels_outer_diff = -outer_y;
1263 *xptr = real_x;
1264 *yptr = real_y;
1267 /* Insert a description of internally-recorded parameters of frame X
1268 into the parameter alist *ALISTPTR that is to be given to the user.
1269 Only parameters that are specific to the X window system
1270 and whose values are not correctly recorded in the frame's
1271 param_alist need to be considered here. */
1273 void
1274 x_report_frame_params (f, alistptr)
1275 struct frame *f;
1276 Lisp_Object *alistptr;
1278 char buf[16];
1279 Lisp_Object tem;
1281 /* Represent negative positions (off the top or left screen edge)
1282 in a way that Fmodify_frame_parameters will understand correctly. */
1283 XSETINT (tem, f->output_data.x->left_pos);
1284 if (f->output_data.x->left_pos >= 0)
1285 store_in_alist (alistptr, Qleft, tem);
1286 else
1287 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1289 XSETINT (tem, f->output_data.x->top_pos);
1290 if (f->output_data.x->top_pos >= 0)
1291 store_in_alist (alistptr, Qtop, tem);
1292 else
1293 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1295 store_in_alist (alistptr, Qborder_width,
1296 make_number (f->output_data.x->border_width));
1297 store_in_alist (alistptr, Qinternal_border_width,
1298 make_number (f->output_data.x->internal_border_width));
1299 store_in_alist (alistptr, Qleft_fringe,
1300 make_number (f->output_data.x->left_fringe_width));
1301 store_in_alist (alistptr, Qright_fringe,
1302 make_number (f->output_data.x->right_fringe_width));
1303 store_in_alist (alistptr, Qscroll_bar_width,
1304 make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1305 ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
1306 : 0));
1307 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1308 store_in_alist (alistptr, Qwindow_id,
1309 build_string (buf));
1310 #ifdef USE_X_TOOLKIT
1311 /* Tooltip frame may not have this widget. */
1312 if (f->output_data.x->widget)
1313 #endif
1314 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1315 store_in_alist (alistptr, Qouter_window_id,
1316 build_string (buf));
1317 store_in_alist (alistptr, Qicon_name, f->icon_name);
1318 FRAME_SAMPLE_VISIBILITY (f);
1319 store_in_alist (alistptr, Qvisibility,
1320 (FRAME_VISIBLE_P (f) ? Qt
1321 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1322 store_in_alist (alistptr, Qdisplay,
1323 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1325 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1326 tem = Qnil;
1327 else
1328 XSETFASTINT (tem, f->output_data.x->parent_desc);
1329 store_in_alist (alistptr, Qparent_id, tem);
1334 /* Gamma-correct COLOR on frame F. */
1336 void
1337 gamma_correct (f, color)
1338 struct frame *f;
1339 XColor *color;
1341 if (f->gamma)
1343 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1344 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1345 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1350 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1351 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1352 allocate the color. Value is zero if COLOR_NAME is invalid, or
1353 no color could be allocated. */
1356 x_defined_color (f, color_name, color, alloc_p)
1357 struct frame *f;
1358 char *color_name;
1359 XColor *color;
1360 int alloc_p;
1362 int success_p;
1363 Display *dpy = FRAME_X_DISPLAY (f);
1364 Colormap cmap = FRAME_X_COLORMAP (f);
1366 BLOCK_INPUT;
1367 success_p = XParseColor (dpy, cmap, color_name, color);
1368 if (success_p && alloc_p)
1369 success_p = x_alloc_nearest_color (f, cmap, color);
1370 UNBLOCK_INPUT;
1372 return success_p;
1376 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1377 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1378 Signal an error if color can't be allocated. */
1381 x_decode_color (f, color_name, mono_color)
1382 FRAME_PTR f;
1383 Lisp_Object color_name;
1384 int mono_color;
1386 XColor cdef;
1388 CHECK_STRING (color_name);
1390 #if 0 /* Don't do this. It's wrong when we're not using the default
1391 colormap, it makes freeing difficult, and it's probably not
1392 an important optimization. */
1393 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1394 return BLACK_PIX_DEFAULT (f);
1395 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1396 return WHITE_PIX_DEFAULT (f);
1397 #endif
1399 /* Return MONO_COLOR for monochrome frames. */
1400 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1401 return mono_color;
1403 /* x_defined_color is responsible for coping with failures
1404 by looking for a near-miss. */
1405 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1406 return cdef.pixel;
1408 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1409 Fcons (color_name, Qnil)));
1410 return 0;
1415 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1416 the previous value of that parameter, NEW_VALUE is the new value. */
1418 static void
1419 x_set_line_spacing (f, new_value, old_value)
1420 struct frame *f;
1421 Lisp_Object new_value, old_value;
1423 if (NILP (new_value))
1424 f->extra_line_spacing = 0;
1425 else if (NATNUMP (new_value))
1426 f->extra_line_spacing = XFASTINT (new_value);
1427 else
1428 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1429 Fcons (new_value, Qnil)));
1430 if (FRAME_VISIBLE_P (f))
1431 redraw_frame (f);
1435 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1436 the previous value of that parameter, NEW_VALUE is the new value.
1437 See also the comment of wait_for_wm in struct x_output. */
1439 static void
1440 x_set_wait_for_wm (f, new_value, old_value)
1441 struct frame *f;
1442 Lisp_Object new_value, old_value;
1444 f->output_data.x->wait_for_wm = !NILP (new_value);
1448 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1449 the previous value of that parameter, NEW_VALUE is the new value. */
1451 static void
1452 x_set_fullscreen (f, new_value, old_value)
1453 struct frame *f;
1454 Lisp_Object new_value, old_value;
1456 if (NILP (new_value))
1457 f->output_data.x->want_fullscreen = FULLSCREEN_NONE;
1458 else if (EQ (new_value, Qfullboth))
1459 f->output_data.x->want_fullscreen = FULLSCREEN_BOTH;
1460 else if (EQ (new_value, Qfullwidth))
1461 f->output_data.x->want_fullscreen = FULLSCREEN_WIDTH;
1462 else if (EQ (new_value, Qfullheight))
1463 f->output_data.x->want_fullscreen = FULLSCREEN_HEIGHT;
1467 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1468 the previous value of that parameter, NEW_VALUE is the new
1469 value. */
1471 static void
1472 x_set_screen_gamma (f, new_value, old_value)
1473 struct frame *f;
1474 Lisp_Object new_value, old_value;
1476 if (NILP (new_value))
1477 f->gamma = 0;
1478 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1479 /* The value 0.4545 is the normal viewing gamma. */
1480 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1481 else
1482 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1483 Fcons (new_value, Qnil)));
1485 clear_face_cache (0);
1489 /* Functions called only from `x_set_frame_param'
1490 to set individual parameters.
1492 If FRAME_X_WINDOW (f) is 0,
1493 the frame is being created and its X-window does not exist yet.
1494 In that case, just record the parameter's new value
1495 in the standard place; do not attempt to change the window. */
1497 void
1498 x_set_foreground_color (f, arg, oldval)
1499 struct frame *f;
1500 Lisp_Object arg, oldval;
1502 struct x_output *x = f->output_data.x;
1503 unsigned long fg, old_fg;
1505 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1506 old_fg = x->foreground_pixel;
1507 x->foreground_pixel = fg;
1509 if (FRAME_X_WINDOW (f) != 0)
1511 Display *dpy = FRAME_X_DISPLAY (f);
1513 BLOCK_INPUT;
1514 XSetForeground (dpy, x->normal_gc, fg);
1515 XSetBackground (dpy, x->reverse_gc, fg);
1517 if (x->cursor_pixel == old_fg)
1519 unload_color (f, x->cursor_pixel);
1520 x->cursor_pixel = x_copy_color (f, fg);
1521 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1524 UNBLOCK_INPUT;
1526 update_face_from_frame_parameter (f, Qforeground_color, arg);
1528 if (FRAME_VISIBLE_P (f))
1529 redraw_frame (f);
1532 unload_color (f, old_fg);
1535 void
1536 x_set_background_color (f, arg, oldval)
1537 struct frame *f;
1538 Lisp_Object arg, oldval;
1540 struct x_output *x = f->output_data.x;
1541 unsigned long bg;
1543 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1544 unload_color (f, x->background_pixel);
1545 x->background_pixel = bg;
1547 if (FRAME_X_WINDOW (f) != 0)
1549 Display *dpy = FRAME_X_DISPLAY (f);
1551 BLOCK_INPUT;
1552 XSetBackground (dpy, x->normal_gc, bg);
1553 XSetForeground (dpy, x->reverse_gc, bg);
1554 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1555 XSetForeground (dpy, x->cursor_gc, bg);
1557 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1558 toolkit scroll bars. */
1560 Lisp_Object bar;
1561 for (bar = FRAME_SCROLL_BARS (f);
1562 !NILP (bar);
1563 bar = XSCROLL_BAR (bar)->next)
1565 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1566 XSetWindowBackground (dpy, window, bg);
1569 #endif /* USE_TOOLKIT_SCROLL_BARS */
1571 UNBLOCK_INPUT;
1572 update_face_from_frame_parameter (f, Qbackground_color, arg);
1574 if (FRAME_VISIBLE_P (f))
1575 redraw_frame (f);
1579 void
1580 x_set_mouse_color (f, arg, oldval)
1581 struct frame *f;
1582 Lisp_Object arg, oldval;
1584 struct x_output *x = f->output_data.x;
1585 Display *dpy = FRAME_X_DISPLAY (f);
1586 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1587 Cursor hourglass_cursor, horizontal_drag_cursor;
1588 int count;
1589 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1590 unsigned long mask_color = x->background_pixel;
1592 /* Don't let pointers be invisible. */
1593 if (mask_color == pixel)
1595 x_free_colors (f, &pixel, 1);
1596 pixel = x_copy_color (f, x->foreground_pixel);
1599 unload_color (f, x->mouse_pixel);
1600 x->mouse_pixel = pixel;
1602 BLOCK_INPUT;
1604 /* It's not okay to crash if the user selects a screwy cursor. */
1605 count = x_catch_errors (dpy);
1607 if (!NILP (Vx_pointer_shape))
1609 CHECK_NUMBER (Vx_pointer_shape);
1610 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1612 else
1613 cursor = XCreateFontCursor (dpy, XC_xterm);
1614 x_check_errors (dpy, "bad text pointer cursor: %s");
1616 if (!NILP (Vx_nontext_pointer_shape))
1618 CHECK_NUMBER (Vx_nontext_pointer_shape);
1619 nontext_cursor
1620 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1622 else
1623 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1624 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1626 if (!NILP (Vx_hourglass_pointer_shape))
1628 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1629 hourglass_cursor
1630 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1632 else
1633 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1634 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1636 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1637 if (!NILP (Vx_mode_pointer_shape))
1639 CHECK_NUMBER (Vx_mode_pointer_shape);
1640 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1642 else
1643 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1644 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1646 if (!NILP (Vx_sensitive_text_pointer_shape))
1648 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1649 cross_cursor
1650 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1652 else
1653 cross_cursor = XCreateFontCursor (dpy, XC_hand2);
1655 if (!NILP (Vx_window_horizontal_drag_shape))
1657 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1658 horizontal_drag_cursor
1659 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1661 else
1662 horizontal_drag_cursor
1663 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1665 /* Check and report errors with the above calls. */
1666 x_check_errors (dpy, "can't set cursor shape: %s");
1667 x_uncatch_errors (dpy, count);
1670 XColor fore_color, back_color;
1672 fore_color.pixel = x->mouse_pixel;
1673 x_query_color (f, &fore_color);
1674 back_color.pixel = mask_color;
1675 x_query_color (f, &back_color);
1677 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1678 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1679 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1680 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1681 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1682 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1685 if (FRAME_X_WINDOW (f) != 0)
1686 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1688 if (cursor != x->text_cursor
1689 && x->text_cursor != 0)
1690 XFreeCursor (dpy, x->text_cursor);
1691 x->text_cursor = cursor;
1693 if (nontext_cursor != x->nontext_cursor
1694 && x->nontext_cursor != 0)
1695 XFreeCursor (dpy, x->nontext_cursor);
1696 x->nontext_cursor = nontext_cursor;
1698 if (hourglass_cursor != x->hourglass_cursor
1699 && x->hourglass_cursor != 0)
1700 XFreeCursor (dpy, x->hourglass_cursor);
1701 x->hourglass_cursor = hourglass_cursor;
1703 if (mode_cursor != x->modeline_cursor
1704 && x->modeline_cursor != 0)
1705 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1706 x->modeline_cursor = mode_cursor;
1708 if (cross_cursor != x->cross_cursor
1709 && x->cross_cursor != 0)
1710 XFreeCursor (dpy, x->cross_cursor);
1711 x->cross_cursor = cross_cursor;
1713 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1714 && x->horizontal_drag_cursor != 0)
1715 XFreeCursor (dpy, x->horizontal_drag_cursor);
1716 x->horizontal_drag_cursor = horizontal_drag_cursor;
1718 XFlush (dpy);
1719 UNBLOCK_INPUT;
1721 update_face_from_frame_parameter (f, Qmouse_color, arg);
1724 void
1725 x_set_cursor_color (f, arg, oldval)
1726 struct frame *f;
1727 Lisp_Object arg, oldval;
1729 unsigned long fore_pixel, pixel;
1730 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1731 struct x_output *x = f->output_data.x;
1733 if (!NILP (Vx_cursor_fore_pixel))
1735 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1736 WHITE_PIX_DEFAULT (f));
1737 fore_pixel_allocated_p = 1;
1739 else
1740 fore_pixel = x->background_pixel;
1742 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1743 pixel_allocated_p = 1;
1745 /* Make sure that the cursor color differs from the background color. */
1746 if (pixel == x->background_pixel)
1748 if (pixel_allocated_p)
1750 x_free_colors (f, &pixel, 1);
1751 pixel_allocated_p = 0;
1754 pixel = x->mouse_pixel;
1755 if (pixel == fore_pixel)
1757 if (fore_pixel_allocated_p)
1759 x_free_colors (f, &fore_pixel, 1);
1760 fore_pixel_allocated_p = 0;
1762 fore_pixel = x->background_pixel;
1766 unload_color (f, x->cursor_foreground_pixel);
1767 if (!fore_pixel_allocated_p)
1768 fore_pixel = x_copy_color (f, fore_pixel);
1769 x->cursor_foreground_pixel = fore_pixel;
1771 unload_color (f, x->cursor_pixel);
1772 if (!pixel_allocated_p)
1773 pixel = x_copy_color (f, pixel);
1774 x->cursor_pixel = pixel;
1776 if (FRAME_X_WINDOW (f) != 0)
1778 BLOCK_INPUT;
1779 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1780 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1781 UNBLOCK_INPUT;
1783 if (FRAME_VISIBLE_P (f))
1785 x_update_cursor (f, 0);
1786 x_update_cursor (f, 1);
1790 update_face_from_frame_parameter (f, Qcursor_color, arg);
1793 /* Set the border-color of frame F to value described by ARG.
1794 ARG can be a string naming a color.
1795 The border-color is used for the border that is drawn by the X server.
1796 Note that this does not fully take effect if done before
1797 F has an x-window; it must be redone when the window is created.
1799 Note: this is done in two routines because of the way X10 works.
1801 Note: under X11, this is normally the province of the window manager,
1802 and so emacs' border colors may be overridden. */
1804 void
1805 x_set_border_color (f, arg, oldval)
1806 struct frame *f;
1807 Lisp_Object arg, oldval;
1809 int pix;
1811 CHECK_STRING (arg);
1812 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1813 x_set_border_pixel (f, pix);
1814 update_face_from_frame_parameter (f, Qborder_color, arg);
1817 /* Set the border-color of frame F to pixel value PIX.
1818 Note that this does not fully take effect if done before
1819 F has an x-window. */
1821 void
1822 x_set_border_pixel (f, pix)
1823 struct frame *f;
1824 int pix;
1826 unload_color (f, f->output_data.x->border_pixel);
1827 f->output_data.x->border_pixel = pix;
1829 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1831 BLOCK_INPUT;
1832 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1833 (unsigned long)pix);
1834 UNBLOCK_INPUT;
1836 if (FRAME_VISIBLE_P (f))
1837 redraw_frame (f);
1842 /* Value is the internal representation of the specified cursor type
1843 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1844 of the bar cursor. */
1846 enum text_cursor_kinds
1847 x_specified_cursor_type (arg, width)
1848 Lisp_Object arg;
1849 int *width;
1851 enum text_cursor_kinds type;
1853 if (EQ (arg, Qbar))
1855 type = BAR_CURSOR;
1856 *width = 2;
1858 else if (CONSP (arg)
1859 && EQ (XCAR (arg), Qbar)
1860 && INTEGERP (XCDR (arg))
1861 && XINT (XCDR (arg)) >= 0)
1863 type = BAR_CURSOR;
1864 *width = XINT (XCDR (arg));
1866 else if (EQ (arg, Qhbar))
1868 type = HBAR_CURSOR;
1869 *width = 2;
1871 else if (CONSP (arg)
1872 && EQ (XCAR (arg), Qhbar)
1873 && INTEGERP (XCDR (arg))
1874 && XINT (XCDR (arg)) >= 0)
1876 type = HBAR_CURSOR;
1877 *width = XINT (XCDR (arg));
1879 else if (NILP (arg))
1880 type = NO_CURSOR;
1881 else
1882 /* Treat anything unknown as "box cursor".
1883 It was bad to signal an error; people have trouble fixing
1884 .Xdefaults with Emacs, when it has something bad in it. */
1885 type = FILLED_BOX_CURSOR;
1887 return type;
1890 void
1891 x_set_cursor_type (f, arg, oldval)
1892 FRAME_PTR f;
1893 Lisp_Object arg, oldval;
1895 int width;
1897 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1898 f->output_data.x->cursor_width = width;
1900 /* Make sure the cursor gets redrawn. */
1901 cursor_type_changed = 1;
1904 void
1905 x_set_icon_type (f, arg, oldval)
1906 struct frame *f;
1907 Lisp_Object arg, oldval;
1909 int result;
1911 if (STRINGP (arg))
1913 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1914 return;
1916 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1917 return;
1919 BLOCK_INPUT;
1920 if (NILP (arg))
1921 result = x_text_icon (f,
1922 (char *) XSTRING ((!NILP (f->icon_name)
1923 ? f->icon_name
1924 : f->name))->data);
1925 else
1926 result = x_bitmap_icon (f, arg);
1928 if (result)
1930 UNBLOCK_INPUT;
1931 error ("No icon window available");
1934 XFlush (FRAME_X_DISPLAY (f));
1935 UNBLOCK_INPUT;
1938 /* Return non-nil if frame F wants a bitmap icon. */
1940 Lisp_Object
1941 x_icon_type (f)
1942 FRAME_PTR f;
1944 Lisp_Object tem;
1946 tem = assq_no_quit (Qicon_type, f->param_alist);
1947 if (CONSP (tem))
1948 return XCDR (tem);
1949 else
1950 return Qnil;
1953 void
1954 x_set_icon_name (f, arg, oldval)
1955 struct frame *f;
1956 Lisp_Object arg, oldval;
1958 int result;
1960 if (STRINGP (arg))
1962 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1963 return;
1965 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1966 return;
1968 f->icon_name = arg;
1970 if (f->output_data.x->icon_bitmap != 0)
1971 return;
1973 BLOCK_INPUT;
1975 result = x_text_icon (f,
1976 (char *) XSTRING ((!NILP (f->icon_name)
1977 ? f->icon_name
1978 : !NILP (f->title)
1979 ? f->title
1980 : f->name))->data);
1982 if (result)
1984 UNBLOCK_INPUT;
1985 error ("No icon window available");
1988 XFlush (FRAME_X_DISPLAY (f));
1989 UNBLOCK_INPUT;
1992 void
1993 x_set_font (f, arg, oldval)
1994 struct frame *f;
1995 Lisp_Object arg, oldval;
1997 Lisp_Object result;
1998 Lisp_Object fontset_name;
1999 Lisp_Object frame;
2000 int old_fontset = f->output_data.x->fontset;
2002 CHECK_STRING (arg);
2004 fontset_name = Fquery_fontset (arg, Qnil);
2006 BLOCK_INPUT;
2007 result = (STRINGP (fontset_name)
2008 ? x_new_fontset (f, XSTRING (fontset_name)->data)
2009 : x_new_font (f, XSTRING (arg)->data));
2010 UNBLOCK_INPUT;
2012 if (EQ (result, Qnil))
2013 error ("Font `%s' is not defined", XSTRING (arg)->data);
2014 else if (EQ (result, Qt))
2015 error ("The characters of the given font have varying widths");
2016 else if (STRINGP (result))
2018 if (STRINGP (fontset_name))
2020 /* Fontset names are built from ASCII font names, so the
2021 names may be equal despite there was a change. */
2022 if (old_fontset == f->output_data.x->fontset)
2023 return;
2025 else if (!NILP (Fequal (result, oldval)))
2026 return;
2028 store_frame_param (f, Qfont, result);
2029 recompute_basic_faces (f);
2031 else
2032 abort ();
2034 do_pending_window_change (0);
2036 /* Don't call `face-set-after-frame-default' when faces haven't been
2037 initialized yet. This is the case when called from
2038 Fx_create_frame. In that case, the X widget or window doesn't
2039 exist either, and we can end up in x_report_frame_params with a
2040 null widget which gives a segfault. */
2041 if (FRAME_FACE_CACHE (f))
2043 XSETFRAME (frame, f);
2044 call1 (Qface_set_after_frame_default, frame);
2048 static void
2049 x_set_fringe_width (f, new_value, old_value)
2050 struct frame *f;
2051 Lisp_Object new_value, old_value;
2053 x_compute_fringe_widths (f, 1);
2056 void
2057 x_set_border_width (f, arg, oldval)
2058 struct frame *f;
2059 Lisp_Object arg, oldval;
2061 CHECK_NUMBER (arg);
2063 if (XINT (arg) == f->output_data.x->border_width)
2064 return;
2066 if (FRAME_X_WINDOW (f) != 0)
2067 error ("Cannot change the border width of a window");
2069 f->output_data.x->border_width = XINT (arg);
2072 void
2073 x_set_internal_border_width (f, arg, oldval)
2074 struct frame *f;
2075 Lisp_Object arg, oldval;
2077 int old = f->output_data.x->internal_border_width;
2079 CHECK_NUMBER (arg);
2080 f->output_data.x->internal_border_width = XINT (arg);
2081 if (f->output_data.x->internal_border_width < 0)
2082 f->output_data.x->internal_border_width = 0;
2084 #ifdef USE_X_TOOLKIT
2085 if (f->output_data.x->edit_widget)
2086 widget_store_internal_border (f->output_data.x->edit_widget);
2087 #endif
2089 if (f->output_data.x->internal_border_width == old)
2090 return;
2092 if (FRAME_X_WINDOW (f) != 0)
2094 x_set_window_size (f, 0, f->width, f->height);
2095 SET_FRAME_GARBAGED (f);
2096 do_pending_window_change (0);
2098 else
2099 SET_FRAME_GARBAGED (f);
2102 void
2103 x_set_visibility (f, value, oldval)
2104 struct frame *f;
2105 Lisp_Object value, oldval;
2107 Lisp_Object frame;
2108 XSETFRAME (frame, f);
2110 if (NILP (value))
2111 Fmake_frame_invisible (frame, Qt);
2112 else if (EQ (value, Qicon))
2113 Ficonify_frame (frame);
2114 else
2115 Fmake_frame_visible (frame);
2119 /* Change window heights in windows rooted in WINDOW by N lines. */
2121 static void
2122 x_change_window_heights (window, n)
2123 Lisp_Object window;
2124 int n;
2126 struct window *w = XWINDOW (window);
2128 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2129 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2131 if (INTEGERP (w->orig_top))
2132 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2133 if (INTEGERP (w->orig_height))
2134 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2136 /* Handle just the top child in a vertical split. */
2137 if (!NILP (w->vchild))
2138 x_change_window_heights (w->vchild, n);
2140 /* Adjust all children in a horizontal split. */
2141 for (window = w->hchild; !NILP (window); window = w->next)
2143 w = XWINDOW (window);
2144 x_change_window_heights (window, n);
2148 void
2149 x_set_menu_bar_lines (f, value, oldval)
2150 struct frame *f;
2151 Lisp_Object value, oldval;
2153 int nlines;
2154 #ifndef USE_X_TOOLKIT
2155 int olines = FRAME_MENU_BAR_LINES (f);
2156 #endif
2158 /* Right now, menu bars don't work properly in minibuf-only frames;
2159 most of the commands try to apply themselves to the minibuffer
2160 frame itself, and get an error because you can't switch buffers
2161 in or split the minibuffer window. */
2162 if (FRAME_MINIBUF_ONLY_P (f))
2163 return;
2165 if (INTEGERP (value))
2166 nlines = XINT (value);
2167 else
2168 nlines = 0;
2170 /* Make sure we redisplay all windows in this frame. */
2171 windows_or_buffers_changed++;
2173 #ifdef USE_X_TOOLKIT
2174 FRAME_MENU_BAR_LINES (f) = 0;
2175 if (nlines)
2177 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2178 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
2179 /* Make sure next redisplay shows the menu bar. */
2180 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2182 else
2184 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2185 free_frame_menubar (f);
2186 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2187 if (FRAME_X_P (f))
2188 f->output_data.x->menubar_widget = 0;
2190 #else /* not USE_X_TOOLKIT */
2191 FRAME_MENU_BAR_LINES (f) = nlines;
2192 x_change_window_heights (f->root_window, nlines - olines);
2193 #endif /* not USE_X_TOOLKIT */
2194 adjust_glyphs (f);
2198 /* Set the number of lines used for the tool bar of frame F to VALUE.
2199 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2200 is the old number of tool bar lines. This function changes the
2201 height of all windows on frame F to match the new tool bar height.
2202 The frame's height doesn't change. */
2204 void
2205 x_set_tool_bar_lines (f, value, oldval)
2206 struct frame *f;
2207 Lisp_Object value, oldval;
2209 int delta, nlines, root_height;
2210 Lisp_Object root_window;
2212 /* Treat tool bars like menu bars. */
2213 if (FRAME_MINIBUF_ONLY_P (f))
2214 return;
2216 /* Use VALUE only if an integer >= 0. */
2217 if (INTEGERP (value) && XINT (value) >= 0)
2218 nlines = XFASTINT (value);
2219 else
2220 nlines = 0;
2222 /* Make sure we redisplay all windows in this frame. */
2223 ++windows_or_buffers_changed;
2225 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2227 /* Don't resize the tool-bar to more than we have room for. */
2228 root_window = FRAME_ROOT_WINDOW (f);
2229 root_height = XINT (XWINDOW (root_window)->height);
2230 if (root_height - delta < 1)
2232 delta = root_height - 1;
2233 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2236 FRAME_TOOL_BAR_LINES (f) = nlines;
2237 x_change_window_heights (root_window, delta);
2238 adjust_glyphs (f);
2240 /* We also have to make sure that the internal border at the top of
2241 the frame, below the menu bar or tool bar, is redrawn when the
2242 tool bar disappears. This is so because the internal border is
2243 below the tool bar if one is displayed, but is below the menu bar
2244 if there isn't a tool bar. The tool bar draws into the area
2245 below the menu bar. */
2246 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2248 updating_frame = f;
2249 clear_frame ();
2250 clear_current_matrices (f);
2251 updating_frame = NULL;
2254 /* If the tool bar gets smaller, the internal border below it
2255 has to be cleared. It was formerly part of the display
2256 of the larger tool bar, and updating windows won't clear it. */
2257 if (delta < 0)
2259 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2260 int width = PIXEL_WIDTH (f);
2261 int y = nlines * CANON_Y_UNIT (f);
2263 BLOCK_INPUT;
2264 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2265 0, y, width, height, False);
2266 UNBLOCK_INPUT;
2268 if (WINDOWP (f->tool_bar_window))
2269 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2274 /* Set the foreground color for scroll bars on frame F to VALUE.
2275 VALUE should be a string, a color name. If it isn't a string or
2276 isn't a valid color name, do nothing. OLDVAL is the old value of
2277 the frame parameter. */
2279 void
2280 x_set_scroll_bar_foreground (f, value, oldval)
2281 struct frame *f;
2282 Lisp_Object value, oldval;
2284 unsigned long pixel;
2286 if (STRINGP (value))
2287 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2288 else
2289 pixel = -1;
2291 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2292 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2294 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2295 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2297 /* Remove all scroll bars because they have wrong colors. */
2298 if (condemn_scroll_bars_hook)
2299 (*condemn_scroll_bars_hook) (f);
2300 if (judge_scroll_bars_hook)
2301 (*judge_scroll_bars_hook) (f);
2303 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2304 redraw_frame (f);
2309 /* Set the background color for scroll bars on frame F to VALUE VALUE
2310 should be a string, a color name. If it isn't a string or isn't a
2311 valid color name, do nothing. OLDVAL is the old value of the frame
2312 parameter. */
2314 void
2315 x_set_scroll_bar_background (f, value, oldval)
2316 struct frame *f;
2317 Lisp_Object value, oldval;
2319 unsigned long pixel;
2321 if (STRINGP (value))
2322 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2323 else
2324 pixel = -1;
2326 if (f->output_data.x->scroll_bar_background_pixel != -1)
2327 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2329 #ifdef USE_TOOLKIT_SCROLL_BARS
2330 /* Scrollbar shadow colors. */
2331 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
2333 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
2334 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2336 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
2338 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
2339 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2341 #endif /* USE_TOOLKIT_SCROLL_BARS */
2343 f->output_data.x->scroll_bar_background_pixel = pixel;
2344 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2346 /* Remove all scroll bars because they have wrong colors. */
2347 if (condemn_scroll_bars_hook)
2348 (*condemn_scroll_bars_hook) (f);
2349 if (judge_scroll_bars_hook)
2350 (*judge_scroll_bars_hook) (f);
2352 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2353 redraw_frame (f);
2358 /* Encode Lisp string STRING as a text in a format appropriate for
2359 XICCC (X Inter Client Communication Conventions).
2361 If STRING contains only ASCII characters, do no conversion and
2362 return the string data of STRING. Otherwise, encode the text by
2363 CODING_SYSTEM, and return a newly allocated memory area which
2364 should be freed by `xfree' by a caller.
2366 SELECTIONP non-zero means the string is being encoded for an X
2367 selection, so it is safe to run pre-write conversions (which
2368 may run Lisp code).
2370 Store the byte length of resulting text in *TEXT_BYTES.
2372 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2373 which means that the `encoding' of the result can be `STRING'.
2374 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2375 the result should be `COMPOUND_TEXT'. */
2377 unsigned char *
2378 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
2379 Lisp_Object string, coding_system;
2380 int *text_bytes, *stringp;
2381 int selectionp;
2383 unsigned char *str = XSTRING (string)->data;
2384 int chars = XSTRING (string)->size;
2385 int bytes = STRING_BYTES (XSTRING (string));
2386 int charset_info;
2387 int bufsize;
2388 unsigned char *buf;
2389 struct coding_system coding;
2391 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2392 if (charset_info == 0)
2394 /* No multibyte character in OBJ. We need not encode it. */
2395 *text_bytes = bytes;
2396 *stringp = 1;
2397 return str;
2400 setup_coding_system (coding_system, &coding);
2401 if (selectionp
2402 && SYMBOLP (coding.pre_write_conversion)
2403 && !NILP (Ffboundp (coding.pre_write_conversion)))
2405 string = run_pre_post_conversion_on_str (string, &coding, 1);
2406 str = XSTRING (string)->data;
2407 chars = XSTRING (string)->size;
2408 bytes = STRING_BYTES (XSTRING (string));
2410 coding.src_multibyte = 1;
2411 coding.dst_multibyte = 0;
2412 coding.mode |= CODING_MODE_LAST_BLOCK;
2413 if (coding.type == coding_type_iso2022)
2414 coding.flags |= CODING_FLAG_ISO_SAFE;
2415 /* We suppress producing escape sequences for composition. */
2416 coding.composing = COMPOSITION_DISABLED;
2417 bufsize = encoding_buffer_size (&coding, bytes);
2418 buf = (unsigned char *) xmalloc (bufsize);
2419 encode_coding (&coding, str, buf, bytes, bufsize);
2420 *text_bytes = coding.produced;
2421 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2422 return buf;
2426 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2427 x_id_name.
2429 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2430 name; if NAME is a string, set F's name to NAME and set
2431 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2433 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2434 suggesting a new name, which lisp code should override; if
2435 F->explicit_name is set, ignore the new name; otherwise, set it. */
2437 void
2438 x_set_name (f, name, explicit)
2439 struct frame *f;
2440 Lisp_Object name;
2441 int explicit;
2443 /* Make sure that requests from lisp code override requests from
2444 Emacs redisplay code. */
2445 if (explicit)
2447 /* If we're switching from explicit to implicit, we had better
2448 update the mode lines and thereby update the title. */
2449 if (f->explicit_name && NILP (name))
2450 update_mode_lines = 1;
2452 f->explicit_name = ! NILP (name);
2454 else if (f->explicit_name)
2455 return;
2457 /* If NAME is nil, set the name to the x_id_name. */
2458 if (NILP (name))
2460 /* Check for no change needed in this very common case
2461 before we do any consing. */
2462 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2463 XSTRING (f->name)->data))
2464 return;
2465 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2467 else
2468 CHECK_STRING (name);
2470 /* Don't change the name if it's already NAME. */
2471 if (! NILP (Fstring_equal (name, f->name)))
2472 return;
2474 f->name = name;
2476 /* For setting the frame title, the title parameter should override
2477 the name parameter. */
2478 if (! NILP (f->title))
2479 name = f->title;
2481 if (FRAME_X_WINDOW (f))
2483 BLOCK_INPUT;
2484 #ifdef HAVE_X11R4
2486 XTextProperty text, icon;
2487 int bytes, stringp;
2488 Lisp_Object coding_system;
2490 coding_system = Vlocale_coding_system;
2491 if (NILP (coding_system))
2492 coding_system = Qcompound_text;
2493 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2494 text.encoding = (stringp ? XA_STRING
2495 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2496 text.format = 8;
2497 text.nitems = bytes;
2499 if (NILP (f->icon_name))
2501 icon = text;
2503 else
2505 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2506 &bytes, &stringp);
2507 icon.encoding = (stringp ? XA_STRING
2508 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2509 icon.format = 8;
2510 icon.nitems = bytes;
2512 #ifdef USE_X_TOOLKIT
2513 XSetWMName (FRAME_X_DISPLAY (f),
2514 XtWindow (f->output_data.x->widget), &text);
2515 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2516 &icon);
2517 #else /* not USE_X_TOOLKIT */
2518 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2519 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2520 #endif /* not USE_X_TOOLKIT */
2521 if (!NILP (f->icon_name)
2522 && icon.value != XSTRING (f->icon_name)->data)
2523 xfree (icon.value);
2524 if (text.value != XSTRING (name)->data)
2525 xfree (text.value);
2527 #else /* not HAVE_X11R4 */
2528 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2529 XSTRING (name)->data);
2530 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2531 XSTRING (name)->data);
2532 #endif /* not HAVE_X11R4 */
2533 UNBLOCK_INPUT;
2537 /* This function should be called when the user's lisp code has
2538 specified a name for the frame; the name will override any set by the
2539 redisplay code. */
2540 void
2541 x_explicitly_set_name (f, arg, oldval)
2542 FRAME_PTR f;
2543 Lisp_Object arg, oldval;
2545 x_set_name (f, arg, 1);
2548 /* This function should be called by Emacs redisplay code to set the
2549 name; names set this way will never override names set by the user's
2550 lisp code. */
2551 void
2552 x_implicitly_set_name (f, arg, oldval)
2553 FRAME_PTR f;
2554 Lisp_Object arg, oldval;
2556 x_set_name (f, arg, 0);
2559 /* Change the title of frame F to NAME.
2560 If NAME is nil, use the frame name as the title.
2562 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2563 name; if NAME is a string, set F's name to NAME and set
2564 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2566 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2567 suggesting a new name, which lisp code should override; if
2568 F->explicit_name is set, ignore the new name; otherwise, set it. */
2570 void
2571 x_set_title (f, name, old_name)
2572 struct frame *f;
2573 Lisp_Object name, old_name;
2575 /* Don't change the title if it's already NAME. */
2576 if (EQ (name, f->title))
2577 return;
2579 update_mode_lines = 1;
2581 f->title = name;
2583 if (NILP (name))
2584 name = f->name;
2585 else
2586 CHECK_STRING (name);
2588 if (FRAME_X_WINDOW (f))
2590 BLOCK_INPUT;
2591 #ifdef HAVE_X11R4
2593 XTextProperty text, icon;
2594 int bytes, stringp;
2595 Lisp_Object coding_system;
2597 coding_system = Vlocale_coding_system;
2598 if (NILP (coding_system))
2599 coding_system = Qcompound_text;
2600 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2601 text.encoding = (stringp ? XA_STRING
2602 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2603 text.format = 8;
2604 text.nitems = bytes;
2606 if (NILP (f->icon_name))
2608 icon = text;
2610 else
2612 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2613 &bytes, &stringp);
2614 icon.encoding = (stringp ? XA_STRING
2615 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2616 icon.format = 8;
2617 icon.nitems = bytes;
2619 #ifdef USE_X_TOOLKIT
2620 XSetWMName (FRAME_X_DISPLAY (f),
2621 XtWindow (f->output_data.x->widget), &text);
2622 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2623 &icon);
2624 #else /* not USE_X_TOOLKIT */
2625 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2626 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2627 #endif /* not USE_X_TOOLKIT */
2628 if (!NILP (f->icon_name)
2629 && icon.value != XSTRING (f->icon_name)->data)
2630 xfree (icon.value);
2631 if (text.value != XSTRING (name)->data)
2632 xfree (text.value);
2634 #else /* not HAVE_X11R4 */
2635 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2636 XSTRING (name)->data);
2637 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2638 XSTRING (name)->data);
2639 #endif /* not HAVE_X11R4 */
2640 UNBLOCK_INPUT;
2644 void
2645 x_set_autoraise (f, arg, oldval)
2646 struct frame *f;
2647 Lisp_Object arg, oldval;
2649 f->auto_raise = !EQ (Qnil, arg);
2652 void
2653 x_set_autolower (f, arg, oldval)
2654 struct frame *f;
2655 Lisp_Object arg, oldval;
2657 f->auto_lower = !EQ (Qnil, arg);
2660 void
2661 x_set_unsplittable (f, arg, oldval)
2662 struct frame *f;
2663 Lisp_Object arg, oldval;
2665 f->no_split = !NILP (arg);
2668 void
2669 x_set_vertical_scroll_bars (f, arg, oldval)
2670 struct frame *f;
2671 Lisp_Object arg, oldval;
2673 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2674 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2675 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2676 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2678 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2679 = (NILP (arg)
2680 ? vertical_scroll_bar_none
2681 : EQ (Qright, arg)
2682 ? vertical_scroll_bar_right
2683 : vertical_scroll_bar_left);
2685 /* We set this parameter before creating the X window for the
2686 frame, so we can get the geometry right from the start.
2687 However, if the window hasn't been created yet, we shouldn't
2688 call x_set_window_size. */
2689 if (FRAME_X_WINDOW (f))
2690 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2691 do_pending_window_change (0);
2695 void
2696 x_set_scroll_bar_width (f, arg, oldval)
2697 struct frame *f;
2698 Lisp_Object arg, oldval;
2700 int wid = FONT_WIDTH (f->output_data.x->font);
2702 if (NILP (arg))
2704 #ifdef USE_TOOLKIT_SCROLL_BARS
2705 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2706 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2707 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2708 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2709 #else
2710 /* Make the actual width at least 14 pixels and a multiple of a
2711 character width. */
2712 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2714 /* Use all of that space (aside from required margins) for the
2715 scroll bar. */
2716 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2717 #endif
2719 if (FRAME_X_WINDOW (f))
2720 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2721 do_pending_window_change (0);
2723 else if (INTEGERP (arg) && XINT (arg) > 0
2724 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2726 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2727 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2729 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2730 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2731 if (FRAME_X_WINDOW (f))
2732 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2735 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2736 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2737 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2742 /* Subroutines of creating an X frame. */
2744 /* Make sure that Vx_resource_name is set to a reasonable value.
2745 Fix it up, or set it to `emacs' if it is too hopeless. */
2747 static void
2748 validate_x_resource_name ()
2750 int len = 0;
2751 /* Number of valid characters in the resource name. */
2752 int good_count = 0;
2753 /* Number of invalid characters in the resource name. */
2754 int bad_count = 0;
2755 Lisp_Object new;
2756 int i;
2758 if (!STRINGP (Vx_resource_class))
2759 Vx_resource_class = build_string (EMACS_CLASS);
2761 if (STRINGP (Vx_resource_name))
2763 unsigned char *p = XSTRING (Vx_resource_name)->data;
2764 int i;
2766 len = STRING_BYTES (XSTRING (Vx_resource_name));
2768 /* Only letters, digits, - and _ are valid in resource names.
2769 Count the valid characters and count the invalid ones. */
2770 for (i = 0; i < len; i++)
2772 int c = p[i];
2773 if (! ((c >= 'a' && c <= 'z')
2774 || (c >= 'A' && c <= 'Z')
2775 || (c >= '0' && c <= '9')
2776 || c == '-' || c == '_'))
2777 bad_count++;
2778 else
2779 good_count++;
2782 else
2783 /* Not a string => completely invalid. */
2784 bad_count = 5, good_count = 0;
2786 /* If name is valid already, return. */
2787 if (bad_count == 0)
2788 return;
2790 /* If name is entirely invalid, or nearly so, use `emacs'. */
2791 if (good_count == 0
2792 || (good_count == 1 && bad_count > 0))
2794 Vx_resource_name = build_string ("emacs");
2795 return;
2798 /* Name is partly valid. Copy it and replace the invalid characters
2799 with underscores. */
2801 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2803 for (i = 0; i < len; i++)
2805 int c = XSTRING (new)->data[i];
2806 if (! ((c >= 'a' && c <= 'z')
2807 || (c >= 'A' && c <= 'Z')
2808 || (c >= '0' && c <= '9')
2809 || c == '-' || c == '_'))
2810 XSTRING (new)->data[i] = '_';
2815 extern char *x_get_string_resource ();
2817 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2818 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2819 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2820 class, where INSTANCE is the name under which Emacs was invoked, or
2821 the name specified by the `-name' or `-rn' command-line arguments.
2823 The optional arguments COMPONENT and SUBCLASS add to the key and the
2824 class, respectively. You must specify both of them or neither.
2825 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2826 and the class is `Emacs.CLASS.SUBCLASS'. */)
2827 (attribute, class, component, subclass)
2828 Lisp_Object attribute, class, component, subclass;
2830 register char *value;
2831 char *name_key;
2832 char *class_key;
2834 check_x ();
2836 CHECK_STRING (attribute);
2837 CHECK_STRING (class);
2839 if (!NILP (component))
2840 CHECK_STRING (component);
2841 if (!NILP (subclass))
2842 CHECK_STRING (subclass);
2843 if (NILP (component) != NILP (subclass))
2844 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2846 validate_x_resource_name ();
2848 /* Allocate space for the components, the dots which separate them,
2849 and the final '\0'. Make them big enough for the worst case. */
2850 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2851 + (STRINGP (component)
2852 ? STRING_BYTES (XSTRING (component)) : 0)
2853 + STRING_BYTES (XSTRING (attribute))
2854 + 3);
2856 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2857 + STRING_BYTES (XSTRING (class))
2858 + (STRINGP (subclass)
2859 ? STRING_BYTES (XSTRING (subclass)) : 0)
2860 + 3);
2862 /* Start with emacs.FRAMENAME for the name (the specific one)
2863 and with `Emacs' for the class key (the general one). */
2864 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2865 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2867 strcat (class_key, ".");
2868 strcat (class_key, XSTRING (class)->data);
2870 if (!NILP (component))
2872 strcat (class_key, ".");
2873 strcat (class_key, XSTRING (subclass)->data);
2875 strcat (name_key, ".");
2876 strcat (name_key, XSTRING (component)->data);
2879 strcat (name_key, ".");
2880 strcat (name_key, XSTRING (attribute)->data);
2882 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2883 name_key, class_key);
2885 if (value != (char *) 0)
2886 return build_string (value);
2887 else
2888 return Qnil;
2891 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2893 Lisp_Object
2894 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2895 struct x_display_info *dpyinfo;
2896 Lisp_Object attribute, class, component, subclass;
2898 register char *value;
2899 char *name_key;
2900 char *class_key;
2902 CHECK_STRING (attribute);
2903 CHECK_STRING (class);
2905 if (!NILP (component))
2906 CHECK_STRING (component);
2907 if (!NILP (subclass))
2908 CHECK_STRING (subclass);
2909 if (NILP (component) != NILP (subclass))
2910 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2912 validate_x_resource_name ();
2914 /* Allocate space for the components, the dots which separate them,
2915 and the final '\0'. Make them big enough for the worst case. */
2916 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2917 + (STRINGP (component)
2918 ? STRING_BYTES (XSTRING (component)) : 0)
2919 + STRING_BYTES (XSTRING (attribute))
2920 + 3);
2922 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2923 + STRING_BYTES (XSTRING (class))
2924 + (STRINGP (subclass)
2925 ? STRING_BYTES (XSTRING (subclass)) : 0)
2926 + 3);
2928 /* Start with emacs.FRAMENAME for the name (the specific one)
2929 and with `Emacs' for the class key (the general one). */
2930 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2931 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2933 strcat (class_key, ".");
2934 strcat (class_key, XSTRING (class)->data);
2936 if (!NILP (component))
2938 strcat (class_key, ".");
2939 strcat (class_key, XSTRING (subclass)->data);
2941 strcat (name_key, ".");
2942 strcat (name_key, XSTRING (component)->data);
2945 strcat (name_key, ".");
2946 strcat (name_key, XSTRING (attribute)->data);
2948 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2950 if (value != (char *) 0)
2951 return build_string (value);
2952 else
2953 return Qnil;
2956 /* Used when C code wants a resource value. */
2958 char *
2959 x_get_resource_string (attribute, class)
2960 char *attribute, *class;
2962 char *name_key;
2963 char *class_key;
2964 struct frame *sf = SELECTED_FRAME ();
2966 /* Allocate space for the components, the dots which separate them,
2967 and the final '\0'. */
2968 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2969 + strlen (attribute) + 2);
2970 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2971 + strlen (class) + 2);
2973 sprintf (name_key, "%s.%s",
2974 XSTRING (Vinvocation_name)->data,
2975 attribute);
2976 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2978 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2979 name_key, class_key);
2982 /* Types we might convert a resource string into. */
2983 enum resource_types
2985 RES_TYPE_NUMBER,
2986 RES_TYPE_FLOAT,
2987 RES_TYPE_BOOLEAN,
2988 RES_TYPE_STRING,
2989 RES_TYPE_SYMBOL
2992 /* Return the value of parameter PARAM.
2994 First search ALIST, then Vdefault_frame_alist, then the X defaults
2995 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2997 Convert the resource to the type specified by desired_type.
2999 If no default is specified, return Qunbound. If you call
3000 x_get_arg, make sure you deal with Qunbound in a reasonable way,
3001 and don't let it get stored in any Lisp-visible variables! */
3003 static Lisp_Object
3004 x_get_arg (dpyinfo, alist, param, attribute, class, type)
3005 struct x_display_info *dpyinfo;
3006 Lisp_Object alist, param;
3007 char *attribute;
3008 char *class;
3009 enum resource_types type;
3011 register Lisp_Object tem;
3013 tem = Fassq (param, alist);
3014 if (EQ (tem, Qnil))
3015 tem = Fassq (param, Vdefault_frame_alist);
3016 if (EQ (tem, Qnil))
3019 if (attribute)
3021 tem = display_x_get_resource (dpyinfo,
3022 build_string (attribute),
3023 build_string (class),
3024 Qnil, Qnil);
3026 if (NILP (tem))
3027 return Qunbound;
3029 switch (type)
3031 case RES_TYPE_NUMBER:
3032 return make_number (atoi (XSTRING (tem)->data));
3034 case RES_TYPE_FLOAT:
3035 return make_float (atof (XSTRING (tem)->data));
3037 case RES_TYPE_BOOLEAN:
3038 tem = Fdowncase (tem);
3039 if (!strcmp (XSTRING (tem)->data, "on")
3040 || !strcmp (XSTRING (tem)->data, "true"))
3041 return Qt;
3042 else
3043 return Qnil;
3045 case RES_TYPE_STRING:
3046 return tem;
3048 case RES_TYPE_SYMBOL:
3049 /* As a special case, we map the values `true' and `on'
3050 to Qt, and `false' and `off' to Qnil. */
3052 Lisp_Object lower;
3053 lower = Fdowncase (tem);
3054 if (!strcmp (XSTRING (lower)->data, "on")
3055 || !strcmp (XSTRING (lower)->data, "true"))
3056 return Qt;
3057 else if (!strcmp (XSTRING (lower)->data, "off")
3058 || !strcmp (XSTRING (lower)->data, "false"))
3059 return Qnil;
3060 else
3061 return Fintern (tem, Qnil);
3064 default:
3065 abort ();
3068 else
3069 return Qunbound;
3071 return Fcdr (tem);
3074 /* Like x_get_arg, but also record the value in f->param_alist. */
3076 static Lisp_Object
3077 x_get_and_record_arg (f, alist, param, attribute, class, type)
3078 struct frame *f;
3079 Lisp_Object alist, param;
3080 char *attribute;
3081 char *class;
3082 enum resource_types type;
3084 Lisp_Object value;
3086 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3087 attribute, class, type);
3088 if (! NILP (value))
3089 store_frame_param (f, param, value);
3091 return value;
3094 /* Record in frame F the specified or default value according to ALIST
3095 of the parameter named PROP (a Lisp symbol).
3096 If no value is specified for PROP, look for an X default for XPROP
3097 on the frame named NAME.
3098 If that is not found either, use the value DEFLT. */
3100 static Lisp_Object
3101 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3102 struct frame *f;
3103 Lisp_Object alist;
3104 Lisp_Object prop;
3105 Lisp_Object deflt;
3106 char *xprop;
3107 char *xclass;
3108 enum resource_types type;
3110 Lisp_Object tem;
3112 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
3113 if (EQ (tem, Qunbound))
3114 tem = deflt;
3115 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3116 return tem;
3120 /* Record in frame F the specified or default value according to ALIST
3121 of the parameter named PROP (a Lisp symbol). If no value is
3122 specified for PROP, look for an X default for XPROP on the frame
3123 named NAME. If that is not found either, use the value DEFLT. */
3125 static Lisp_Object
3126 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
3127 foreground_p)
3128 struct frame *f;
3129 Lisp_Object alist;
3130 Lisp_Object prop;
3131 char *xprop;
3132 char *xclass;
3133 int foreground_p;
3135 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3136 Lisp_Object tem;
3138 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
3139 if (EQ (tem, Qunbound))
3141 #ifdef USE_TOOLKIT_SCROLL_BARS
3143 /* See if an X resource for the scroll bar color has been
3144 specified. */
3145 tem = display_x_get_resource (dpyinfo,
3146 build_string (foreground_p
3147 ? "foreground"
3148 : "background"),
3149 empty_string,
3150 build_string ("verticalScrollBar"),
3151 empty_string);
3152 if (!STRINGP (tem))
3154 /* If nothing has been specified, scroll bars will use a
3155 toolkit-dependent default. Because these defaults are
3156 difficult to get at without actually creating a scroll
3157 bar, use nil to indicate that no color has been
3158 specified. */
3159 tem = Qnil;
3162 #else /* not USE_TOOLKIT_SCROLL_BARS */
3164 tem = Qnil;
3166 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3169 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3170 return tem;
3175 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3176 doc: /* Parse an X-style geometry string STRING.
3177 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3178 The properties returned may include `top', `left', `height', and `width'.
3179 The value of `left' or `top' may be an integer,
3180 or a list (+ N) meaning N pixels relative to top/left corner,
3181 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3182 (string)
3183 Lisp_Object string;
3185 int geometry, x, y;
3186 unsigned int width, height;
3187 Lisp_Object result;
3189 CHECK_STRING (string);
3191 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3192 &x, &y, &width, &height);
3194 #if 0
3195 if (!!(geometry & XValue) != !!(geometry & YValue))
3196 error ("Must specify both x and y position, or neither");
3197 #endif
3199 result = Qnil;
3200 if (geometry & XValue)
3202 Lisp_Object element;
3204 if (x >= 0 && (geometry & XNegative))
3205 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3206 else if (x < 0 && ! (geometry & XNegative))
3207 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3208 else
3209 element = Fcons (Qleft, make_number (x));
3210 result = Fcons (element, result);
3213 if (geometry & YValue)
3215 Lisp_Object element;
3217 if (y >= 0 && (geometry & YNegative))
3218 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3219 else if (y < 0 && ! (geometry & YNegative))
3220 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3221 else
3222 element = Fcons (Qtop, make_number (y));
3223 result = Fcons (element, result);
3226 if (geometry & WidthValue)
3227 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3228 if (geometry & HeightValue)
3229 result = Fcons (Fcons (Qheight, make_number (height)), result);
3231 return result;
3234 /* Calculate the desired size and position of this window,
3235 and return the flags saying which aspects were specified.
3237 This function does not make the coordinates positive. */
3239 #define DEFAULT_ROWS 40
3240 #define DEFAULT_COLS 80
3242 static int
3243 x_figure_window_size (f, parms)
3244 struct frame *f;
3245 Lisp_Object parms;
3247 register Lisp_Object tem0, tem1, tem2;
3248 long window_prompting = 0;
3249 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3251 /* Default values if we fall through.
3252 Actually, if that happens we should get
3253 window manager prompting. */
3254 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3255 f->height = DEFAULT_ROWS;
3256 /* Window managers expect that if program-specified
3257 positions are not (0,0), they're intentional, not defaults. */
3258 f->output_data.x->top_pos = 0;
3259 f->output_data.x->left_pos = 0;
3261 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3262 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3263 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3264 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3266 if (!EQ (tem0, Qunbound))
3268 CHECK_NUMBER (tem0);
3269 f->height = XINT (tem0);
3271 if (!EQ (tem1, Qunbound))
3273 CHECK_NUMBER (tem1);
3274 SET_FRAME_WIDTH (f, XINT (tem1));
3276 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3277 window_prompting |= USSize;
3278 else
3279 window_prompting |= PSize;
3282 f->output_data.x->vertical_scroll_bar_extra
3283 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3285 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3287 x_compute_fringe_widths (f, 0);
3289 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3290 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3292 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3293 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3294 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3295 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3297 if (EQ (tem0, Qminus))
3299 f->output_data.x->top_pos = 0;
3300 window_prompting |= YNegative;
3302 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3303 && CONSP (XCDR (tem0))
3304 && INTEGERP (XCAR (XCDR (tem0))))
3306 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3307 window_prompting |= YNegative;
3309 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3310 && CONSP (XCDR (tem0))
3311 && INTEGERP (XCAR (XCDR (tem0))))
3313 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3315 else if (EQ (tem0, Qunbound))
3316 f->output_data.x->top_pos = 0;
3317 else
3319 CHECK_NUMBER (tem0);
3320 f->output_data.x->top_pos = XINT (tem0);
3321 if (f->output_data.x->top_pos < 0)
3322 window_prompting |= YNegative;
3325 if (EQ (tem1, Qminus))
3327 f->output_data.x->left_pos = 0;
3328 window_prompting |= XNegative;
3330 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3331 && CONSP (XCDR (tem1))
3332 && INTEGERP (XCAR (XCDR (tem1))))
3334 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3335 window_prompting |= XNegative;
3337 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3338 && CONSP (XCDR (tem1))
3339 && INTEGERP (XCAR (XCDR (tem1))))
3341 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3343 else if (EQ (tem1, Qunbound))
3344 f->output_data.x->left_pos = 0;
3345 else
3347 CHECK_NUMBER (tem1);
3348 f->output_data.x->left_pos = XINT (tem1);
3349 if (f->output_data.x->left_pos < 0)
3350 window_prompting |= XNegative;
3353 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3354 window_prompting |= USPosition;
3355 else
3356 window_prompting |= PPosition;
3359 if (f->output_data.x->want_fullscreen != FULLSCREEN_NONE)
3361 int left, top;
3362 int width, height;
3364 /* It takes both for some WM:s to place it where we want */
3365 window_prompting = USPosition | PPosition;
3366 x_fullscreen_adjust (f, &width, &height, &top, &left);
3367 f->width = width;
3368 f->height = height;
3369 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3370 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3371 f->output_data.x->left_pos = left;
3372 f->output_data.x->top_pos = top;
3375 return window_prompting;
3378 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3380 Status
3381 XSetWMProtocols (dpy, w, protocols, count)
3382 Display *dpy;
3383 Window w;
3384 Atom *protocols;
3385 int count;
3387 Atom prop;
3388 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3389 if (prop == None) return False;
3390 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3391 (unsigned char *) protocols, count);
3392 return True;
3394 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3396 #ifdef USE_X_TOOLKIT
3398 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3399 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3400 already be present because of the toolkit (Motif adds some of them,
3401 for example, but Xt doesn't). */
3403 static void
3404 hack_wm_protocols (f, widget)
3405 FRAME_PTR f;
3406 Widget widget;
3408 Display *dpy = XtDisplay (widget);
3409 Window w = XtWindow (widget);
3410 int need_delete = 1;
3411 int need_focus = 1;
3412 int need_save = 1;
3414 BLOCK_INPUT;
3416 Atom type, *atoms = 0;
3417 int format = 0;
3418 unsigned long nitems = 0;
3419 unsigned long bytes_after;
3421 if ((XGetWindowProperty (dpy, w,
3422 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3423 (long)0, (long)100, False, XA_ATOM,
3424 &type, &format, &nitems, &bytes_after,
3425 (unsigned char **) &atoms)
3426 == Success)
3427 && format == 32 && type == XA_ATOM)
3428 while (nitems > 0)
3430 nitems--;
3431 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3432 need_delete = 0;
3433 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3434 need_focus = 0;
3435 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3436 need_save = 0;
3438 if (atoms) XFree ((char *) atoms);
3441 Atom props [10];
3442 int count = 0;
3443 if (need_delete)
3444 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3445 if (need_focus)
3446 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3447 if (need_save)
3448 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3449 if (count)
3450 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3451 XA_ATOM, 32, PropModeAppend,
3452 (unsigned char *) props, count);
3454 UNBLOCK_INPUT;
3456 #endif
3460 /* Support routines for XIC (X Input Context). */
3462 #ifdef HAVE_X_I18N
3464 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3465 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3468 /* Supported XIM styles, ordered by preferenc. */
3470 static XIMStyle supported_xim_styles[] =
3472 XIMPreeditPosition | XIMStatusArea,
3473 XIMPreeditPosition | XIMStatusNothing,
3474 XIMPreeditPosition | XIMStatusNone,
3475 XIMPreeditNothing | XIMStatusArea,
3476 XIMPreeditNothing | XIMStatusNothing,
3477 XIMPreeditNothing | XIMStatusNone,
3478 XIMPreeditNone | XIMStatusArea,
3479 XIMPreeditNone | XIMStatusNothing,
3480 XIMPreeditNone | XIMStatusNone,
3485 /* Create an X fontset on frame F with base font name
3486 BASE_FONTNAME.. */
3488 static XFontSet
3489 xic_create_xfontset (f, base_fontname)
3490 struct frame *f;
3491 char *base_fontname;
3493 XFontSet xfs;
3494 char **missing_list;
3495 int missing_count;
3496 char *def_string;
3498 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3499 base_fontname, &missing_list,
3500 &missing_count, &def_string);
3501 if (missing_list)
3502 XFreeStringList (missing_list);
3504 /* No need to free def_string. */
3505 return xfs;
3509 /* Value is the best input style, given user preferences USER (already
3510 checked to be supported by Emacs), and styles supported by the
3511 input method XIM. */
3513 static XIMStyle
3514 best_xim_style (user, xim)
3515 XIMStyles *user;
3516 XIMStyles *xim;
3518 int i, j;
3520 for (i = 0; i < user->count_styles; ++i)
3521 for (j = 0; j < xim->count_styles; ++j)
3522 if (user->supported_styles[i] == xim->supported_styles[j])
3523 return user->supported_styles[i];
3525 /* Return the default style. */
3526 return XIMPreeditNothing | XIMStatusNothing;
3529 /* Create XIC for frame F. */
3531 static XIMStyle xic_style;
3533 void
3534 create_frame_xic (f)
3535 struct frame *f;
3537 XIM xim;
3538 XIC xic = NULL;
3539 XFontSet xfs = NULL;
3541 if (FRAME_XIC (f))
3542 return;
3544 xim = FRAME_X_XIM (f);
3545 if (xim)
3547 XRectangle s_area;
3548 XPoint spot;
3549 XVaNestedList preedit_attr;
3550 XVaNestedList status_attr;
3551 char *base_fontname;
3552 int fontset;
3554 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3555 spot.x = 0; spot.y = 1;
3556 /* Create X fontset. */
3557 fontset = FRAME_FONTSET (f);
3558 if (fontset < 0)
3559 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3560 else
3562 /* Determine the base fontname from the ASCII font name of
3563 FONTSET. */
3564 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3565 char *p = ascii_font;
3566 int i;
3568 for (i = 0; *p; p++)
3569 if (*p == '-') i++;
3570 if (i != 14)
3571 /* As the font name doesn't conform to XLFD, we can't
3572 modify it to get a suitable base fontname for the
3573 frame. */
3574 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3575 else
3577 int len = strlen (ascii_font) + 1;
3578 char *p1 = NULL;
3580 for (i = 0, p = ascii_font; i < 8; p++)
3582 if (*p == '-')
3584 i++;
3585 if (i == 3)
3586 p1 = p + 1;
3589 base_fontname = (char *) alloca (len);
3590 bzero (base_fontname, len);
3591 strcpy (base_fontname, "-*-*-");
3592 bcopy (p1, base_fontname + 5, p - p1);
3593 strcat (base_fontname, "*-*-*-*-*-*-*");
3596 xfs = xic_create_xfontset (f, base_fontname);
3598 /* Determine XIC style. */
3599 if (xic_style == 0)
3601 XIMStyles supported_list;
3602 supported_list.count_styles = (sizeof supported_xim_styles
3603 / sizeof supported_xim_styles[0]);
3604 supported_list.supported_styles = supported_xim_styles;
3605 xic_style = best_xim_style (&supported_list,
3606 FRAME_X_XIM_STYLES (f));
3609 preedit_attr = XVaCreateNestedList (0,
3610 XNFontSet, xfs,
3611 XNForeground,
3612 FRAME_FOREGROUND_PIXEL (f),
3613 XNBackground,
3614 FRAME_BACKGROUND_PIXEL (f),
3615 (xic_style & XIMPreeditPosition
3616 ? XNSpotLocation
3617 : NULL),
3618 &spot,
3619 NULL);
3620 status_attr = XVaCreateNestedList (0,
3621 XNArea,
3622 &s_area,
3623 XNFontSet,
3624 xfs,
3625 XNForeground,
3626 FRAME_FOREGROUND_PIXEL (f),
3627 XNBackground,
3628 FRAME_BACKGROUND_PIXEL (f),
3629 NULL);
3631 xic = XCreateIC (xim,
3632 XNInputStyle, xic_style,
3633 XNClientWindow, FRAME_X_WINDOW(f),
3634 XNFocusWindow, FRAME_X_WINDOW(f),
3635 XNStatusAttributes, status_attr,
3636 XNPreeditAttributes, preedit_attr,
3637 NULL);
3638 XFree (preedit_attr);
3639 XFree (status_attr);
3642 FRAME_XIC (f) = xic;
3643 FRAME_XIC_STYLE (f) = xic_style;
3644 FRAME_XIC_FONTSET (f) = xfs;
3648 /* Destroy XIC and free XIC fontset of frame F, if any. */
3650 void
3651 free_frame_xic (f)
3652 struct frame *f;
3654 if (FRAME_XIC (f) == NULL)
3655 return;
3657 XDestroyIC (FRAME_XIC (f));
3658 if (FRAME_XIC_FONTSET (f))
3659 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3661 FRAME_XIC (f) = NULL;
3662 FRAME_XIC_FONTSET (f) = NULL;
3666 /* Place preedit area for XIC of window W's frame to specified
3667 pixel position X/Y. X and Y are relative to window W. */
3669 void
3670 xic_set_preeditarea (w, x, y)
3671 struct window *w;
3672 int x, y;
3674 struct frame *f = XFRAME (w->frame);
3675 XVaNestedList attr;
3676 XPoint spot;
3678 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3679 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3680 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3681 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3682 XFree (attr);
3686 /* Place status area for XIC in bottom right corner of frame F.. */
3688 void
3689 xic_set_statusarea (f)
3690 struct frame *f;
3692 XIC xic = FRAME_XIC (f);
3693 XVaNestedList attr;
3694 XRectangle area;
3695 XRectangle *needed;
3697 /* Negotiate geometry of status area. If input method has existing
3698 status area, use its current size. */
3699 area.x = area.y = area.width = area.height = 0;
3700 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3701 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3702 XFree (attr);
3704 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3705 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3706 XFree (attr);
3708 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3710 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3711 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3712 XFree (attr);
3715 area.width = needed->width;
3716 area.height = needed->height;
3717 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3718 area.y = (PIXEL_HEIGHT (f) - area.height
3719 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3720 XFree (needed);
3722 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3723 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3724 XFree (attr);
3728 /* Set X fontset for XIC of frame F, using base font name
3729 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3731 void
3732 xic_set_xfontset (f, base_fontname)
3733 struct frame *f;
3734 char *base_fontname;
3736 XVaNestedList attr;
3737 XFontSet xfs;
3739 xfs = xic_create_xfontset (f, base_fontname);
3741 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3742 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3743 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3744 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3745 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3746 XFree (attr);
3748 if (FRAME_XIC_FONTSET (f))
3749 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3750 FRAME_XIC_FONTSET (f) = xfs;
3753 #endif /* HAVE_X_I18N */
3757 #ifdef USE_X_TOOLKIT
3759 /* Create and set up the X widget for frame F. */
3761 static void
3762 x_window (f, window_prompting, minibuffer_only)
3763 struct frame *f;
3764 long window_prompting;
3765 int minibuffer_only;
3767 XClassHint class_hints;
3768 XSetWindowAttributes attributes;
3769 unsigned long attribute_mask;
3770 Widget shell_widget;
3771 Widget pane_widget;
3772 Widget frame_widget;
3773 Arg al [25];
3774 int ac;
3776 BLOCK_INPUT;
3778 /* Use the resource name as the top-level widget name
3779 for looking up resources. Make a non-Lisp copy
3780 for the window manager, so GC relocation won't bother it.
3782 Elsewhere we specify the window name for the window manager. */
3785 char *str = (char *) XSTRING (Vx_resource_name)->data;
3786 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3787 strcpy (f->namebuf, str);
3790 ac = 0;
3791 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3792 XtSetArg (al[ac], XtNinput, 1); ac++;
3793 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3794 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3795 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3796 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3797 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3798 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3799 applicationShellWidgetClass,
3800 FRAME_X_DISPLAY (f), al, ac);
3802 f->output_data.x->widget = shell_widget;
3803 /* maybe_set_screen_title_format (shell_widget); */
3805 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3806 (widget_value *) NULL,
3807 shell_widget, False,
3808 (lw_callback) NULL,
3809 (lw_callback) NULL,
3810 (lw_callback) NULL,
3811 (lw_callback) NULL);
3813 ac = 0;
3814 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3815 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3816 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3817 XtSetValues (pane_widget, al, ac);
3818 f->output_data.x->column_widget = pane_widget;
3820 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3821 the emacs screen when changing menubar. This reduces flickering. */
3823 ac = 0;
3824 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3825 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3826 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3827 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3828 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3829 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3830 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3831 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3832 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3833 al, ac);
3835 f->output_data.x->edit_widget = frame_widget;
3837 XtManageChild (frame_widget);
3839 /* Do some needed geometry management. */
3841 int len;
3842 char *tem, shell_position[32];
3843 Arg al[2];
3844 int ac = 0;
3845 int extra_borders = 0;
3846 int menubar_size
3847 = (f->output_data.x->menubar_widget
3848 ? (f->output_data.x->menubar_widget->core.height
3849 + f->output_data.x->menubar_widget->core.border_width)
3850 : 0);
3852 #if 0 /* Experimentally, we now get the right results
3853 for -geometry -0-0 without this. 24 Aug 96, rms. */
3854 if (FRAME_EXTERNAL_MENU_BAR (f))
3856 Dimension ibw = 0;
3857 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3858 menubar_size += ibw;
3860 #endif
3862 f->output_data.x->menubar_height = menubar_size;
3864 #ifndef USE_LUCID
3865 /* Motif seems to need this amount added to the sizes
3866 specified for the shell widget. The Athena/Lucid widgets don't.
3867 Both conclusions reached experimentally. -- rms. */
3868 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3869 &extra_borders, NULL);
3870 extra_borders *= 2;
3871 #endif
3873 /* Convert our geometry parameters into a geometry string
3874 and specify it.
3875 Note that we do not specify here whether the position
3876 is a user-specified or program-specified one.
3877 We pass that information later, in x_wm_set_size_hints. */
3879 int left = f->output_data.x->left_pos;
3880 int xneg = window_prompting & XNegative;
3881 int top = f->output_data.x->top_pos;
3882 int yneg = window_prompting & YNegative;
3883 if (xneg)
3884 left = -left;
3885 if (yneg)
3886 top = -top;
3888 if (window_prompting & USPosition)
3889 sprintf (shell_position, "=%dx%d%c%d%c%d",
3890 PIXEL_WIDTH (f) + extra_borders,
3891 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3892 (xneg ? '-' : '+'), left,
3893 (yneg ? '-' : '+'), top);
3894 else
3895 sprintf (shell_position, "=%dx%d",
3896 PIXEL_WIDTH (f) + extra_borders,
3897 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3900 len = strlen (shell_position) + 1;
3901 /* We don't free this because we don't know whether
3902 it is safe to free it while the frame exists.
3903 It isn't worth the trouble of arranging to free it
3904 when the frame is deleted. */
3905 tem = (char *) xmalloc (len);
3906 strncpy (tem, shell_position, len);
3907 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3908 XtSetValues (shell_widget, al, ac);
3911 XtManageChild (pane_widget);
3912 XtRealizeWidget (shell_widget);
3914 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3916 validate_x_resource_name ();
3918 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3919 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3920 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3922 #ifdef HAVE_X_I18N
3923 FRAME_XIC (f) = NULL;
3924 #ifdef USE_XIM
3925 create_frame_xic (f);
3926 #endif
3927 #endif
3929 f->output_data.x->wm_hints.input = True;
3930 f->output_data.x->wm_hints.flags |= InputHint;
3931 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3932 &f->output_data.x->wm_hints);
3934 hack_wm_protocols (f, shell_widget);
3936 #ifdef HACK_EDITRES
3937 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3938 #endif
3940 /* Do a stupid property change to force the server to generate a
3941 PropertyNotify event so that the event_stream server timestamp will
3942 be initialized to something relevant to the time we created the window.
3944 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3945 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3946 XA_ATOM, 32, PropModeAppend,
3947 (unsigned char*) NULL, 0);
3949 /* Make all the standard events reach the Emacs frame. */
3950 attributes.event_mask = STANDARD_EVENT_SET;
3952 #ifdef HAVE_X_I18N
3953 if (FRAME_XIC (f))
3955 /* XIM server might require some X events. */
3956 unsigned long fevent = NoEventMask;
3957 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3958 attributes.event_mask |= fevent;
3960 #endif /* HAVE_X_I18N */
3962 attribute_mask = CWEventMask;
3963 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3964 attribute_mask, &attributes);
3966 XtMapWidget (frame_widget);
3968 /* x_set_name normally ignores requests to set the name if the
3969 requested name is the same as the current name. This is the one
3970 place where that assumption isn't correct; f->name is set, but
3971 the X server hasn't been told. */
3973 Lisp_Object name;
3974 int explicit = f->explicit_name;
3976 f->explicit_name = 0;
3977 name = f->name;
3978 f->name = Qnil;
3979 x_set_name (f, name, explicit);
3982 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3983 f->output_data.x->text_cursor);
3985 UNBLOCK_INPUT;
3987 /* This is a no-op, except under Motif. Make sure main areas are
3988 set to something reasonable, in case we get an error later. */
3989 lw_set_main_areas (pane_widget, 0, frame_widget);
3992 #else /* not USE_X_TOOLKIT */
3994 /* Create and set up the X window for frame F. */
3996 void
3997 x_window (f)
3998 struct frame *f;
4001 XClassHint class_hints;
4002 XSetWindowAttributes attributes;
4003 unsigned long attribute_mask;
4005 attributes.background_pixel = f->output_data.x->background_pixel;
4006 attributes.border_pixel = f->output_data.x->border_pixel;
4007 attributes.bit_gravity = StaticGravity;
4008 attributes.backing_store = NotUseful;
4009 attributes.save_under = True;
4010 attributes.event_mask = STANDARD_EVENT_SET;
4011 attributes.colormap = FRAME_X_COLORMAP (f);
4012 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
4013 | CWColormap);
4015 BLOCK_INPUT;
4016 FRAME_X_WINDOW (f)
4017 = XCreateWindow (FRAME_X_DISPLAY (f),
4018 f->output_data.x->parent_desc,
4019 f->output_data.x->left_pos,
4020 f->output_data.x->top_pos,
4021 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
4022 f->output_data.x->border_width,
4023 CopyFromParent, /* depth */
4024 InputOutput, /* class */
4025 FRAME_X_VISUAL (f),
4026 attribute_mask, &attributes);
4028 #ifdef HAVE_X_I18N
4029 #ifdef USE_XIM
4030 create_frame_xic (f);
4031 if (FRAME_XIC (f))
4033 /* XIM server might require some X events. */
4034 unsigned long fevent = NoEventMask;
4035 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4036 attributes.event_mask |= fevent;
4037 attribute_mask = CWEventMask;
4038 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4039 attribute_mask, &attributes);
4041 #endif
4042 #endif /* HAVE_X_I18N */
4044 validate_x_resource_name ();
4046 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
4047 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
4048 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
4050 /* The menubar is part of the ordinary display;
4051 it does not count in addition to the height of the window. */
4052 f->output_data.x->menubar_height = 0;
4054 /* This indicates that we use the "Passive Input" input model.
4055 Unless we do this, we don't get the Focus{In,Out} events that we
4056 need to draw the cursor correctly. Accursed bureaucrats.
4057 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4059 f->output_data.x->wm_hints.input = True;
4060 f->output_data.x->wm_hints.flags |= InputHint;
4061 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4062 &f->output_data.x->wm_hints);
4063 f->output_data.x->wm_hints.icon_pixmap = None;
4065 /* Request "save yourself" and "delete window" commands from wm. */
4067 Atom protocols[2];
4068 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
4069 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
4070 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
4073 /* x_set_name normally ignores requests to set the name if the
4074 requested name is the same as the current name. This is the one
4075 place where that assumption isn't correct; f->name is set, but
4076 the X server hasn't been told. */
4078 Lisp_Object name;
4079 int explicit = f->explicit_name;
4081 f->explicit_name = 0;
4082 name = f->name;
4083 f->name = Qnil;
4084 x_set_name (f, name, explicit);
4087 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4088 f->output_data.x->text_cursor);
4090 UNBLOCK_INPUT;
4092 if (FRAME_X_WINDOW (f) == 0)
4093 error ("Unable to create window");
4096 #endif /* not USE_X_TOOLKIT */
4098 /* Handle the icon stuff for this window. Perhaps later we might
4099 want an x_set_icon_position which can be called interactively as
4100 well. */
4102 static void
4103 x_icon (f, parms)
4104 struct frame *f;
4105 Lisp_Object parms;
4107 Lisp_Object icon_x, icon_y;
4108 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4110 /* Set the position of the icon. Note that twm groups all
4111 icons in an icon window. */
4112 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4113 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4114 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
4116 CHECK_NUMBER (icon_x);
4117 CHECK_NUMBER (icon_y);
4119 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
4120 error ("Both left and top icon corners of icon must be specified");
4122 BLOCK_INPUT;
4124 if (! EQ (icon_x, Qunbound))
4125 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
4127 /* Start up iconic or window? */
4128 x_wm_set_window_state
4129 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
4130 Qicon)
4131 ? IconicState
4132 : NormalState));
4134 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
4135 ? f->icon_name
4136 : f->name))->data);
4138 UNBLOCK_INPUT;
4141 /* Make the GCs needed for this window, setting the
4142 background, border and mouse colors; also create the
4143 mouse cursor and the gray border tile. */
4145 static char cursor_bits[] =
4147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4153 static void
4154 x_make_gc (f)
4155 struct frame *f;
4157 XGCValues gc_values;
4159 BLOCK_INPUT;
4161 /* Create the GCs of this frame.
4162 Note that many default values are used. */
4164 /* Normal video */
4165 gc_values.font = f->output_data.x->font->fid;
4166 gc_values.foreground = f->output_data.x->foreground_pixel;
4167 gc_values.background = f->output_data.x->background_pixel;
4168 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
4169 f->output_data.x->normal_gc
4170 = XCreateGC (FRAME_X_DISPLAY (f),
4171 FRAME_X_WINDOW (f),
4172 GCLineWidth | GCFont | GCForeground | GCBackground,
4173 &gc_values);
4175 /* Reverse video style. */
4176 gc_values.foreground = f->output_data.x->background_pixel;
4177 gc_values.background = f->output_data.x->foreground_pixel;
4178 f->output_data.x->reverse_gc
4179 = XCreateGC (FRAME_X_DISPLAY (f),
4180 FRAME_X_WINDOW (f),
4181 GCFont | GCForeground | GCBackground | GCLineWidth,
4182 &gc_values);
4184 /* Cursor has cursor-color background, background-color foreground. */
4185 gc_values.foreground = f->output_data.x->background_pixel;
4186 gc_values.background = f->output_data.x->cursor_pixel;
4187 gc_values.fill_style = FillOpaqueStippled;
4188 gc_values.stipple
4189 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4190 FRAME_X_DISPLAY_INFO (f)->root_window,
4191 cursor_bits, 16, 16);
4192 f->output_data.x->cursor_gc
4193 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4194 (GCFont | GCForeground | GCBackground
4195 | GCFillStyle /* | GCStipple */ | GCLineWidth),
4196 &gc_values);
4198 /* Reliefs. */
4199 f->output_data.x->white_relief.gc = 0;
4200 f->output_data.x->black_relief.gc = 0;
4202 /* Create the gray border tile used when the pointer is not in
4203 the frame. Since this depends on the frame's pixel values,
4204 this must be done on a per-frame basis. */
4205 f->output_data.x->border_tile
4206 = (XCreatePixmapFromBitmapData
4207 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4208 gray_bits, gray_width, gray_height,
4209 f->output_data.x->foreground_pixel,
4210 f->output_data.x->background_pixel,
4211 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4213 UNBLOCK_INPUT;
4217 /* Free what was was allocated in x_make_gc. */
4219 void
4220 x_free_gcs (f)
4221 struct frame *f;
4223 Display *dpy = FRAME_X_DISPLAY (f);
4225 BLOCK_INPUT;
4227 if (f->output_data.x->normal_gc)
4229 XFreeGC (dpy, f->output_data.x->normal_gc);
4230 f->output_data.x->normal_gc = 0;
4233 if (f->output_data.x->reverse_gc)
4235 XFreeGC (dpy, f->output_data.x->reverse_gc);
4236 f->output_data.x->reverse_gc = 0;
4239 if (f->output_data.x->cursor_gc)
4241 XFreeGC (dpy, f->output_data.x->cursor_gc);
4242 f->output_data.x->cursor_gc = 0;
4245 if (f->output_data.x->border_tile)
4247 XFreePixmap (dpy, f->output_data.x->border_tile);
4248 f->output_data.x->border_tile = 0;
4251 UNBLOCK_INPUT;
4255 /* Handler for signals raised during x_create_frame and
4256 x_create_top_frame. FRAME is the frame which is partially
4257 constructed. */
4259 static Lisp_Object
4260 unwind_create_frame (frame)
4261 Lisp_Object frame;
4263 struct frame *f = XFRAME (frame);
4265 /* If frame is ``official'', nothing to do. */
4266 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4268 #if GLYPH_DEBUG
4269 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4270 #endif
4272 x_free_frame_resources (f);
4274 /* Check that reference counts are indeed correct. */
4275 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4276 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4277 return Qt;
4280 return Qnil;
4284 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4285 1, 1, 0,
4286 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
4287 Returns an Emacs frame object.
4288 ALIST is an alist of frame parameters.
4289 If the parameters specify that the frame should not have a minibuffer,
4290 and do not specify a specific minibuffer window to use,
4291 then `default-minibuffer-frame' must be a frame whose minibuffer can
4292 be shared by the new frame.
4294 This function is an internal primitive--use `make-frame' instead. */)
4295 (parms)
4296 Lisp_Object parms;
4298 struct frame *f;
4299 Lisp_Object frame, tem;
4300 Lisp_Object name;
4301 int minibuffer_only = 0;
4302 long window_prompting = 0;
4303 int width, height;
4304 int count = BINDING_STACK_SIZE ();
4305 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4306 Lisp_Object display;
4307 struct x_display_info *dpyinfo = NULL;
4308 Lisp_Object parent;
4309 struct kboard *kb;
4311 check_x ();
4313 /* Use this general default value to start with
4314 until we know if this frame has a specified name. */
4315 Vx_resource_name = Vinvocation_name;
4317 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4318 if (EQ (display, Qunbound))
4319 display = Qnil;
4320 dpyinfo = check_x_display_info (display);
4321 #ifdef MULTI_KBOARD
4322 kb = dpyinfo->kboard;
4323 #else
4324 kb = &the_only_kboard;
4325 #endif
4327 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4328 if (!STRINGP (name)
4329 && ! EQ (name, Qunbound)
4330 && ! NILP (name))
4331 error ("Invalid frame name--not a string or nil");
4333 if (STRINGP (name))
4334 Vx_resource_name = name;
4336 /* See if parent window is specified. */
4337 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4338 if (EQ (parent, Qunbound))
4339 parent = Qnil;
4340 if (! NILP (parent))
4341 CHECK_NUMBER (parent);
4343 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4344 /* No need to protect DISPLAY because that's not used after passing
4345 it to make_frame_without_minibuffer. */
4346 frame = Qnil;
4347 GCPRO4 (parms, parent, name, frame);
4348 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4349 RES_TYPE_SYMBOL);
4350 if (EQ (tem, Qnone) || NILP (tem))
4351 f = make_frame_without_minibuffer (Qnil, kb, display);
4352 else if (EQ (tem, Qonly))
4354 f = make_minibuffer_frame ();
4355 minibuffer_only = 1;
4357 else if (WINDOWP (tem))
4358 f = make_frame_without_minibuffer (tem, kb, display);
4359 else
4360 f = make_frame (1);
4362 XSETFRAME (frame, f);
4364 /* Note that X Windows does support scroll bars. */
4365 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4367 f->output_method = output_x_window;
4368 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4369 bzero (f->output_data.x, sizeof (struct x_output));
4370 f->output_data.x->icon_bitmap = -1;
4371 f->output_data.x->fontset = -1;
4372 f->output_data.x->scroll_bar_foreground_pixel = -1;
4373 f->output_data.x->scroll_bar_background_pixel = -1;
4374 #ifdef USE_TOOLKIT_SCROLL_BARS
4375 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4376 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4377 #endif /* USE_TOOLKIT_SCROLL_BARS */
4378 record_unwind_protect (unwind_create_frame, frame);
4380 f->icon_name
4381 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4382 RES_TYPE_STRING);
4383 if (! STRINGP (f->icon_name))
4384 f->icon_name = Qnil;
4386 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4387 #if GLYPH_DEBUG
4388 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4389 dpyinfo_refcount = dpyinfo->reference_count;
4390 #endif /* GLYPH_DEBUG */
4391 #ifdef MULTI_KBOARD
4392 FRAME_KBOARD (f) = kb;
4393 #endif
4395 /* These colors will be set anyway later, but it's important
4396 to get the color reference counts right, so initialize them! */
4398 Lisp_Object black;
4399 struct gcpro gcpro1;
4401 /* Function x_decode_color can signal an error. Make
4402 sure to initialize color slots so that we won't try
4403 to free colors we haven't allocated. */
4404 f->output_data.x->foreground_pixel = -1;
4405 f->output_data.x->background_pixel = -1;
4406 f->output_data.x->cursor_pixel = -1;
4407 f->output_data.x->cursor_foreground_pixel = -1;
4408 f->output_data.x->border_pixel = -1;
4409 f->output_data.x->mouse_pixel = -1;
4411 black = build_string ("black");
4412 GCPRO1 (black);
4413 f->output_data.x->foreground_pixel
4414 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4415 f->output_data.x->background_pixel
4416 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4417 f->output_data.x->cursor_pixel
4418 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4419 f->output_data.x->cursor_foreground_pixel
4420 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4421 f->output_data.x->border_pixel
4422 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4423 f->output_data.x->mouse_pixel
4424 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4425 UNGCPRO;
4428 /* Specify the parent under which to make this X window. */
4430 if (!NILP (parent))
4432 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4433 f->output_data.x->explicit_parent = 1;
4435 else
4437 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4438 f->output_data.x->explicit_parent = 0;
4441 /* Set the name; the functions to which we pass f expect the name to
4442 be set. */
4443 if (EQ (name, Qunbound) || NILP (name))
4445 f->name = build_string (dpyinfo->x_id_name);
4446 f->explicit_name = 0;
4448 else
4450 f->name = name;
4451 f->explicit_name = 1;
4452 /* use the frame's title when getting resources for this frame. */
4453 specbind (Qx_resource_name, name);
4456 /* Extract the window parameters from the supplied values
4457 that are needed to determine window geometry. */
4459 Lisp_Object font;
4461 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4463 BLOCK_INPUT;
4464 /* First, try whatever font the caller has specified. */
4465 if (STRINGP (font))
4467 tem = Fquery_fontset (font, Qnil);
4468 if (STRINGP (tem))
4469 font = x_new_fontset (f, XSTRING (tem)->data);
4470 else
4471 font = x_new_font (f, XSTRING (font)->data);
4474 /* Try out a font which we hope has bold and italic variations. */
4475 if (!STRINGP (font))
4476 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4477 if (!STRINGP (font))
4478 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4479 if (! STRINGP (font))
4480 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4481 if (! STRINGP (font))
4482 /* This was formerly the first thing tried, but it finds too many fonts
4483 and takes too long. */
4484 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4485 /* If those didn't work, look for something which will at least work. */
4486 if (! STRINGP (font))
4487 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4488 UNBLOCK_INPUT;
4489 if (! STRINGP (font))
4490 font = build_string ("fixed");
4492 x_default_parameter (f, parms, Qfont, font,
4493 "font", "Font", RES_TYPE_STRING);
4496 #ifdef USE_LUCID
4497 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4498 whereby it fails to get any font. */
4499 xlwmenu_default_font = f->output_data.x->font;
4500 #endif
4502 x_default_parameter (f, parms, Qborder_width, make_number (2),
4503 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4505 /* This defaults to 1 in order to match xterm. We recognize either
4506 internalBorderWidth or internalBorder (which is what xterm calls
4507 it). */
4508 if (NILP (Fassq (Qinternal_border_width, parms)))
4510 Lisp_Object value;
4512 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4513 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4514 if (! EQ (value, Qunbound))
4515 parms = Fcons (Fcons (Qinternal_border_width, value),
4516 parms);
4518 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4519 "internalBorderWidth", "internalBorderWidth",
4520 RES_TYPE_NUMBER);
4521 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4522 "verticalScrollBars", "ScrollBars",
4523 RES_TYPE_SYMBOL);
4525 /* Also do the stuff which must be set before the window exists. */
4526 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4527 "foreground", "Foreground", RES_TYPE_STRING);
4528 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4529 "background", "Background", RES_TYPE_STRING);
4530 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4531 "pointerColor", "Foreground", RES_TYPE_STRING);
4532 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4533 "cursorColor", "Foreground", RES_TYPE_STRING);
4534 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4535 "borderColor", "BorderColor", RES_TYPE_STRING);
4536 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4537 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4538 x_default_parameter (f, parms, Qline_spacing, Qnil,
4539 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4540 x_default_parameter (f, parms, Qleft_fringe, Qnil,
4541 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4542 x_default_parameter (f, parms, Qright_fringe, Qnil,
4543 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4545 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4546 "scrollBarForeground",
4547 "ScrollBarForeground", 1);
4548 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4549 "scrollBarBackground",
4550 "ScrollBarBackground", 0);
4552 /* Init faces before x_default_parameter is called for scroll-bar
4553 parameters because that function calls x_set_scroll_bar_width,
4554 which calls change_frame_size, which calls Fset_window_buffer,
4555 which runs hooks, which call Fvertical_motion. At the end, we
4556 end up in init_iterator with a null face cache, which should not
4557 happen. */
4558 init_frame_faces (f);
4560 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4561 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4562 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4563 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4564 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4565 "bufferPredicate", "BufferPredicate",
4566 RES_TYPE_SYMBOL);
4567 x_default_parameter (f, parms, Qtitle, Qnil,
4568 "title", "Title", RES_TYPE_STRING);
4569 x_default_parameter (f, parms, Qwait_for_wm, Qt,
4570 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4571 x_default_parameter (f, parms, Qfullscreen, Qnil,
4572 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4574 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4576 /* Add the tool-bar height to the initial frame height so that the
4577 user gets a text display area of the size he specified with -g or
4578 via .Xdefaults. Later changes of the tool-bar height don't
4579 change the frame size. This is done so that users can create
4580 tall Emacs frames without having to guess how tall the tool-bar
4581 will get. */
4582 if (FRAME_TOOL_BAR_LINES (f))
4584 int margin, relief, bar_height;
4586 relief = (tool_bar_button_relief >= 0
4587 ? tool_bar_button_relief
4588 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4590 if (INTEGERP (Vtool_bar_button_margin)
4591 && XINT (Vtool_bar_button_margin) > 0)
4592 margin = XFASTINT (Vtool_bar_button_margin);
4593 else if (CONSP (Vtool_bar_button_margin)
4594 && INTEGERP (XCDR (Vtool_bar_button_margin))
4595 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4596 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4597 else
4598 margin = 0;
4600 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4601 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4604 /* Compute the size of the X window. */
4605 window_prompting = x_figure_window_size (f, parms);
4607 if (window_prompting & XNegative)
4609 if (window_prompting & YNegative)
4610 f->output_data.x->win_gravity = SouthEastGravity;
4611 else
4612 f->output_data.x->win_gravity = NorthEastGravity;
4614 else
4616 if (window_prompting & YNegative)
4617 f->output_data.x->win_gravity = SouthWestGravity;
4618 else
4619 f->output_data.x->win_gravity = NorthWestGravity;
4622 f->output_data.x->size_hint_flags = window_prompting;
4624 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4625 f->no_split = minibuffer_only || EQ (tem, Qt);
4627 /* Create the X widget or window. */
4628 #ifdef USE_X_TOOLKIT
4629 x_window (f, window_prompting, minibuffer_only);
4630 #else
4631 x_window (f);
4632 #endif
4634 x_icon (f, parms);
4635 x_make_gc (f);
4637 /* Now consider the frame official. */
4638 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4639 Vframe_list = Fcons (frame, Vframe_list);
4641 /* We need to do this after creating the X window, so that the
4642 icon-creation functions can say whose icon they're describing. */
4643 x_default_parameter (f, parms, Qicon_type, Qnil,
4644 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4646 x_default_parameter (f, parms, Qauto_raise, Qnil,
4647 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4648 x_default_parameter (f, parms, Qauto_lower, Qnil,
4649 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4650 x_default_parameter (f, parms, Qcursor_type, Qbox,
4651 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4652 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4653 "scrollBarWidth", "ScrollBarWidth",
4654 RES_TYPE_NUMBER);
4656 /* Dimensions, especially f->height, must be done via change_frame_size.
4657 Change will not be effected unless different from the current
4658 f->height. */
4659 width = f->width;
4660 height = f->height;
4662 f->height = 0;
4663 SET_FRAME_WIDTH (f, 0);
4664 change_frame_size (f, height, width, 1, 0, 0);
4666 /* Set up faces after all frame parameters are known. This call
4667 also merges in face attributes specified for new frames. If we
4668 don't do this, the `menu' face for instance won't have the right
4669 colors, and the menu bar won't appear in the specified colors for
4670 new frames. */
4671 call1 (Qface_set_after_frame_default, frame);
4673 #ifdef USE_X_TOOLKIT
4674 /* Create the menu bar. */
4675 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4677 /* If this signals an error, we haven't set size hints for the
4678 frame and we didn't make it visible. */
4679 initialize_frame_menubar (f);
4681 /* This is a no-op, except under Motif where it arranges the
4682 main window for the widgets on it. */
4683 lw_set_main_areas (f->output_data.x->column_widget,
4684 f->output_data.x->menubar_widget,
4685 f->output_data.x->edit_widget);
4687 #endif /* USE_X_TOOLKIT */
4689 /* Tell the server what size and position, etc, we want, and how
4690 badly we want them. This should be done after we have the menu
4691 bar so that its size can be taken into account. */
4692 BLOCK_INPUT;
4693 x_wm_set_size_hint (f, window_prompting, 0);
4694 UNBLOCK_INPUT;
4696 /* Make the window appear on the frame and enable display, unless
4697 the caller says not to. However, with explicit parent, Emacs
4698 cannot control visibility, so don't try. */
4699 if (! f->output_data.x->explicit_parent)
4701 Lisp_Object visibility;
4703 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4704 RES_TYPE_SYMBOL);
4705 if (EQ (visibility, Qunbound))
4706 visibility = Qt;
4708 if (EQ (visibility, Qicon))
4709 x_iconify_frame (f);
4710 else if (! NILP (visibility))
4711 x_make_frame_visible (f);
4712 else
4713 /* Must have been Qnil. */
4717 UNGCPRO;
4719 /* Make sure windows on this frame appear in calls to next-window
4720 and similar functions. */
4721 Vwindow_list = Qnil;
4723 return unbind_to (count, frame);
4727 /* FRAME is used only to get a handle on the X display. We don't pass the
4728 display info directly because we're called from frame.c, which doesn't
4729 know about that structure. */
4731 Lisp_Object
4732 x_get_focus_frame (frame)
4733 struct frame *frame;
4735 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4736 Lisp_Object xfocus;
4737 if (! dpyinfo->x_focus_frame)
4738 return Qnil;
4740 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4741 return xfocus;
4745 /* In certain situations, when the window manager follows a
4746 click-to-focus policy, there seems to be no way around calling
4747 XSetInputFocus to give another frame the input focus .
4749 In an ideal world, XSetInputFocus should generally be avoided so
4750 that applications don't interfere with the window manager's focus
4751 policy. But I think it's okay to use when it's clearly done
4752 following a user-command. */
4754 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4755 doc: /* Set the input focus to FRAME.
4756 FRAME nil means use the selected frame. */)
4757 (frame)
4758 Lisp_Object frame;
4760 struct frame *f = check_x_frame (frame);
4761 Display *dpy = FRAME_X_DISPLAY (f);
4762 int count;
4764 BLOCK_INPUT;
4765 count = x_catch_errors (dpy);
4766 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4767 RevertToParent, CurrentTime);
4768 x_uncatch_errors (dpy, count);
4769 UNBLOCK_INPUT;
4771 return Qnil;
4775 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4776 doc: /* Internal function called by `color-defined-p', which see. */)
4777 (color, frame)
4778 Lisp_Object color, frame;
4780 XColor foo;
4781 FRAME_PTR f = check_x_frame (frame);
4783 CHECK_STRING (color);
4785 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4786 return Qt;
4787 else
4788 return Qnil;
4791 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4792 doc: /* Internal function called by `color-values', which see. */)
4793 (color, frame)
4794 Lisp_Object color, frame;
4796 XColor foo;
4797 FRAME_PTR f = check_x_frame (frame);
4799 CHECK_STRING (color);
4801 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4803 Lisp_Object rgb[3];
4805 rgb[0] = make_number (foo.red);
4806 rgb[1] = make_number (foo.green);
4807 rgb[2] = make_number (foo.blue);
4808 return Flist (3, rgb);
4810 else
4811 return Qnil;
4814 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4815 doc: /* Internal function called by `display-color-p', which see. */)
4816 (display)
4817 Lisp_Object display;
4819 struct x_display_info *dpyinfo = check_x_display_info (display);
4821 if (dpyinfo->n_planes <= 2)
4822 return Qnil;
4824 switch (dpyinfo->visual->class)
4826 case StaticColor:
4827 case PseudoColor:
4828 case TrueColor:
4829 case DirectColor:
4830 return Qt;
4832 default:
4833 return Qnil;
4837 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4838 0, 1, 0,
4839 doc: /* Return t if the X display supports shades of gray.
4840 Note that color displays do support shades of gray.
4841 The optional argument DISPLAY specifies which display to ask about.
4842 DISPLAY should be either a frame or a display name (a string).
4843 If omitted or nil, that stands for the selected frame's display. */)
4844 (display)
4845 Lisp_Object display;
4847 struct x_display_info *dpyinfo = check_x_display_info (display);
4849 if (dpyinfo->n_planes <= 1)
4850 return Qnil;
4852 switch (dpyinfo->visual->class)
4854 case StaticColor:
4855 case PseudoColor:
4856 case TrueColor:
4857 case DirectColor:
4858 case StaticGray:
4859 case GrayScale:
4860 return Qt;
4862 default:
4863 return Qnil;
4867 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4868 0, 1, 0,
4869 doc: /* Returns the width in pixels of the X display DISPLAY.
4870 The optional argument DISPLAY specifies which display to ask about.
4871 DISPLAY should be either a frame or a display name (a string).
4872 If omitted or nil, that stands for the selected frame's display. */)
4873 (display)
4874 Lisp_Object display;
4876 struct x_display_info *dpyinfo = check_x_display_info (display);
4878 return make_number (dpyinfo->width);
4881 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4882 Sx_display_pixel_height, 0, 1, 0,
4883 doc: /* Returns the height in pixels of the X display DISPLAY.
4884 The optional argument DISPLAY specifies which display to ask about.
4885 DISPLAY should be either a frame or a display name (a string).
4886 If omitted or nil, that stands for the selected frame's display. */)
4887 (display)
4888 Lisp_Object display;
4890 struct x_display_info *dpyinfo = check_x_display_info (display);
4892 return make_number (dpyinfo->height);
4895 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4896 0, 1, 0,
4897 doc: /* Returns the number of bitplanes of the X display DISPLAY.
4898 The optional argument DISPLAY specifies which display to ask about.
4899 DISPLAY should be either a frame or a display name (a string).
4900 If omitted or nil, that stands for the selected frame's display. */)
4901 (display)
4902 Lisp_Object display;
4904 struct x_display_info *dpyinfo = check_x_display_info (display);
4906 return make_number (dpyinfo->n_planes);
4909 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4910 0, 1, 0,
4911 doc: /* Returns the number of color cells of the X display DISPLAY.
4912 The optional argument DISPLAY specifies which display to ask about.
4913 DISPLAY should be either a frame or a display name (a string).
4914 If omitted or nil, that stands for the selected frame's display. */)
4915 (display)
4916 Lisp_Object display;
4918 struct x_display_info *dpyinfo = check_x_display_info (display);
4920 return make_number (DisplayCells (dpyinfo->display,
4921 XScreenNumberOfScreen (dpyinfo->screen)));
4924 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4925 Sx_server_max_request_size,
4926 0, 1, 0,
4927 doc: /* Returns the maximum request size of the X server of display DISPLAY.
4928 The optional argument DISPLAY specifies which display to ask about.
4929 DISPLAY should be either a frame or a display name (a string).
4930 If omitted or nil, that stands for the selected frame's display. */)
4931 (display)
4932 Lisp_Object display;
4934 struct x_display_info *dpyinfo = check_x_display_info (display);
4936 return make_number (MAXREQUEST (dpyinfo->display));
4939 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4940 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
4941 The optional argument DISPLAY specifies which display to ask about.
4942 DISPLAY should be either a frame or a display name (a string).
4943 If omitted or nil, that stands for the selected frame's display. */)
4944 (display)
4945 Lisp_Object display;
4947 struct x_display_info *dpyinfo = check_x_display_info (display);
4948 char *vendor = ServerVendor (dpyinfo->display);
4950 if (! vendor) vendor = "";
4951 return build_string (vendor);
4954 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4955 doc: /* Returns the version numbers of the X server of display DISPLAY.
4956 The value is a list of three integers: the major and minor
4957 version numbers of the X Protocol in use, and the vendor-specific release
4958 number. See also the function `x-server-vendor'.
4960 The optional argument DISPLAY specifies which display to ask about.
4961 DISPLAY should be either a frame or a display name (a string).
4962 If omitted or nil, that stands for the selected frame's display. */)
4963 (display)
4964 Lisp_Object display;
4966 struct x_display_info *dpyinfo = check_x_display_info (display);
4967 Display *dpy = dpyinfo->display;
4969 return Fcons (make_number (ProtocolVersion (dpy)),
4970 Fcons (make_number (ProtocolRevision (dpy)),
4971 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4974 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4975 doc: /* Return the number of screens on the X server of display DISPLAY.
4976 The optional argument DISPLAY specifies which display to ask about.
4977 DISPLAY should be either a frame or a display name (a string).
4978 If omitted or nil, that stands for the selected frame's display. */)
4979 (display)
4980 Lisp_Object display;
4982 struct x_display_info *dpyinfo = check_x_display_info (display);
4984 return make_number (ScreenCount (dpyinfo->display));
4987 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4988 doc: /* Return the height in millimeters of the X display DISPLAY.
4989 The optional argument DISPLAY specifies which display to ask about.
4990 DISPLAY should be either a frame or a display name (a string).
4991 If omitted or nil, that stands for the selected frame's display. */)
4992 (display)
4993 Lisp_Object display;
4995 struct x_display_info *dpyinfo = check_x_display_info (display);
4997 return make_number (HeightMMOfScreen (dpyinfo->screen));
5000 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
5001 doc: /* Return the width in millimeters of the X display DISPLAY.
5002 The optional argument DISPLAY specifies which display to ask about.
5003 DISPLAY should be either a frame or a display name (a string).
5004 If omitted or nil, that stands for the selected frame's display. */)
5005 (display)
5006 Lisp_Object display;
5008 struct x_display_info *dpyinfo = check_x_display_info (display);
5010 return make_number (WidthMMOfScreen (dpyinfo->screen));
5013 DEFUN ("x-display-backing-store", Fx_display_backing_store,
5014 Sx_display_backing_store, 0, 1, 0,
5015 doc: /* Returns an indication of whether X display DISPLAY does backing store.
5016 The value may be `always', `when-mapped', or `not-useful'.
5017 The optional argument DISPLAY specifies which display to ask about.
5018 DISPLAY should be either a frame or a display name (a string).
5019 If omitted or nil, that stands for the selected frame's display. */)
5020 (display)
5021 Lisp_Object display;
5023 struct x_display_info *dpyinfo = check_x_display_info (display);
5024 Lisp_Object result;
5026 switch (DoesBackingStore (dpyinfo->screen))
5028 case Always:
5029 result = intern ("always");
5030 break;
5032 case WhenMapped:
5033 result = intern ("when-mapped");
5034 break;
5036 case NotUseful:
5037 result = intern ("not-useful");
5038 break;
5040 default:
5041 error ("Strange value for BackingStore parameter of screen");
5042 result = Qnil;
5045 return result;
5048 DEFUN ("x-display-visual-class", Fx_display_visual_class,
5049 Sx_display_visual_class, 0, 1, 0,
5050 doc: /* Return the visual class of the X display DISPLAY.
5051 The value is one of the symbols `static-gray', `gray-scale',
5052 `static-color', `pseudo-color', `true-color', or `direct-color'.
5054 The optional argument DISPLAY specifies which display to ask about.
5055 DISPLAY should be either a frame or a display name (a string).
5056 If omitted or nil, that stands for the selected frame's display. */)
5057 (display)
5058 Lisp_Object display;
5060 struct x_display_info *dpyinfo = check_x_display_info (display);
5061 Lisp_Object result;
5063 switch (dpyinfo->visual->class)
5065 case StaticGray:
5066 result = intern ("static-gray");
5067 break;
5068 case GrayScale:
5069 result = intern ("gray-scale");
5070 break;
5071 case StaticColor:
5072 result = intern ("static-color");
5073 break;
5074 case PseudoColor:
5075 result = intern ("pseudo-color");
5076 break;
5077 case TrueColor:
5078 result = intern ("true-color");
5079 break;
5080 case DirectColor:
5081 result = intern ("direct-color");
5082 break;
5083 default:
5084 error ("Display has an unknown visual class");
5085 result = Qnil;
5088 return result;
5091 DEFUN ("x-display-save-under", Fx_display_save_under,
5092 Sx_display_save_under, 0, 1, 0,
5093 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
5094 The optional argument DISPLAY specifies which display to ask about.
5095 DISPLAY should be either a frame or a display name (a string).
5096 If omitted or nil, that stands for the selected frame's display. */)
5097 (display)
5098 Lisp_Object display;
5100 struct x_display_info *dpyinfo = check_x_display_info (display);
5102 if (DoesSaveUnders (dpyinfo->screen) == True)
5103 return Qt;
5104 else
5105 return Qnil;
5109 x_pixel_width (f)
5110 register struct frame *f;
5112 return PIXEL_WIDTH (f);
5116 x_pixel_height (f)
5117 register struct frame *f;
5119 return PIXEL_HEIGHT (f);
5123 x_char_width (f)
5124 register struct frame *f;
5126 return FONT_WIDTH (f->output_data.x->font);
5130 x_char_height (f)
5131 register struct frame *f;
5133 return f->output_data.x->line_height;
5137 x_screen_planes (f)
5138 register struct frame *f;
5140 return FRAME_X_DISPLAY_INFO (f)->n_planes;
5145 /************************************************************************
5146 X Displays
5147 ************************************************************************/
5150 /* Mapping visual names to visuals. */
5152 static struct visual_class
5154 char *name;
5155 int class;
5157 visual_classes[] =
5159 {"StaticGray", StaticGray},
5160 {"GrayScale", GrayScale},
5161 {"StaticColor", StaticColor},
5162 {"PseudoColor", PseudoColor},
5163 {"TrueColor", TrueColor},
5164 {"DirectColor", DirectColor},
5165 {NULL, 0}
5169 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5171 /* Value is the screen number of screen SCR. This is a substitute for
5172 the X function with the same name when that doesn't exist. */
5175 XScreenNumberOfScreen (scr)
5176 register Screen *scr;
5178 Display *dpy = scr->display;
5179 int i;
5181 for (i = 0; i < dpy->nscreens; ++i)
5182 if (scr == dpy->screens + i)
5183 break;
5185 return i;
5188 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5191 /* Select the visual that should be used on display DPYINFO. Set
5192 members of DPYINFO appropriately. Called from x_term_init. */
5194 void
5195 select_visual (dpyinfo)
5196 struct x_display_info *dpyinfo;
5198 Display *dpy = dpyinfo->display;
5199 Screen *screen = dpyinfo->screen;
5200 Lisp_Object value;
5202 /* See if a visual is specified. */
5203 value = display_x_get_resource (dpyinfo,
5204 build_string ("visualClass"),
5205 build_string ("VisualClass"),
5206 Qnil, Qnil);
5207 if (STRINGP (value))
5209 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5210 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5211 depth, a decimal number. NAME is compared with case ignored. */
5212 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
5213 char *dash;
5214 int i, class = -1;
5215 XVisualInfo vinfo;
5217 strcpy (s, XSTRING (value)->data);
5218 dash = index (s, '-');
5219 if (dash)
5221 dpyinfo->n_planes = atoi (dash + 1);
5222 *dash = '\0';
5224 else
5225 /* We won't find a matching visual with depth 0, so that
5226 an error will be printed below. */
5227 dpyinfo->n_planes = 0;
5229 /* Determine the visual class. */
5230 for (i = 0; visual_classes[i].name; ++i)
5231 if (xstricmp (s, visual_classes[i].name) == 0)
5233 class = visual_classes[i].class;
5234 break;
5237 /* Look up a matching visual for the specified class. */
5238 if (class == -1
5239 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5240 dpyinfo->n_planes, class, &vinfo))
5241 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
5243 dpyinfo->visual = vinfo.visual;
5245 else
5247 int n_visuals;
5248 XVisualInfo *vinfo, vinfo_template;
5250 dpyinfo->visual = DefaultVisualOfScreen (screen);
5252 #ifdef HAVE_X11R4
5253 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5254 #else
5255 vinfo_template.visualid = dpyinfo->visual->visualid;
5256 #endif
5257 vinfo_template.screen = XScreenNumberOfScreen (screen);
5258 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5259 &vinfo_template, &n_visuals);
5260 if (n_visuals != 1)
5261 fatal ("Can't get proper X visual info");
5263 dpyinfo->n_planes = vinfo->depth;
5264 XFree ((char *) vinfo);
5269 /* Return the X display structure for the display named NAME.
5270 Open a new connection if necessary. */
5272 struct x_display_info *
5273 x_display_info_for_name (name)
5274 Lisp_Object name;
5276 Lisp_Object names;
5277 struct x_display_info *dpyinfo;
5279 CHECK_STRING (name);
5281 if (! EQ (Vwindow_system, intern ("x")))
5282 error ("Not using X Windows");
5284 for (dpyinfo = x_display_list, names = x_display_name_list;
5285 dpyinfo;
5286 dpyinfo = dpyinfo->next, names = XCDR (names))
5288 Lisp_Object tem;
5289 tem = Fstring_equal (XCAR (XCAR (names)), name);
5290 if (!NILP (tem))
5291 return dpyinfo;
5294 /* Use this general default value to start with. */
5295 Vx_resource_name = Vinvocation_name;
5297 validate_x_resource_name ();
5299 dpyinfo = x_term_init (name, (char *)0,
5300 (char *) XSTRING (Vx_resource_name)->data);
5302 if (dpyinfo == 0)
5303 error ("Cannot connect to X server %s", XSTRING (name)->data);
5305 x_in_use = 1;
5306 XSETFASTINT (Vwindow_system_version, 11);
5308 return dpyinfo;
5312 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5313 1, 3, 0,
5314 doc: /* Open a connection to an X server.
5315 DISPLAY is the name of the display to connect to.
5316 Optional second arg XRM-STRING is a string of resources in xrdb format.
5317 If the optional third arg MUST-SUCCEED is non-nil,
5318 terminate Emacs if we can't open the connection. */)
5319 (display, xrm_string, must_succeed)
5320 Lisp_Object display, xrm_string, must_succeed;
5322 unsigned char *xrm_option;
5323 struct x_display_info *dpyinfo;
5325 CHECK_STRING (display);
5326 if (! NILP (xrm_string))
5327 CHECK_STRING (xrm_string);
5329 if (! EQ (Vwindow_system, intern ("x")))
5330 error ("Not using X Windows");
5332 if (! NILP (xrm_string))
5333 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5334 else
5335 xrm_option = (unsigned char *) 0;
5337 validate_x_resource_name ();
5339 /* This is what opens the connection and sets x_current_display.
5340 This also initializes many symbols, such as those used for input. */
5341 dpyinfo = x_term_init (display, xrm_option,
5342 (char *) XSTRING (Vx_resource_name)->data);
5344 if (dpyinfo == 0)
5346 if (!NILP (must_succeed))
5347 fatal ("Cannot connect to X server %s.\n\
5348 Check the DISPLAY environment variable or use `-d'.\n\
5349 Also use the `xhost' program to verify that it is set to permit\n\
5350 connections from your machine.\n",
5351 XSTRING (display)->data);
5352 else
5353 error ("Cannot connect to X server %s", XSTRING (display)->data);
5356 x_in_use = 1;
5358 XSETFASTINT (Vwindow_system_version, 11);
5359 return Qnil;
5362 DEFUN ("x-close-connection", Fx_close_connection,
5363 Sx_close_connection, 1, 1, 0,
5364 doc: /* Close the connection to DISPLAY's X server.
5365 For DISPLAY, specify either a frame or a display name (a string).
5366 If DISPLAY is nil, that stands for the selected frame's display. */)
5367 (display)
5368 Lisp_Object display;
5370 struct x_display_info *dpyinfo = check_x_display_info (display);
5371 int i;
5373 if (dpyinfo->reference_count > 0)
5374 error ("Display still has frames on it");
5376 BLOCK_INPUT;
5377 /* Free the fonts in the font table. */
5378 for (i = 0; i < dpyinfo->n_fonts; i++)
5379 if (dpyinfo->font_table[i].name)
5381 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5382 xfree (dpyinfo->font_table[i].full_name);
5383 xfree (dpyinfo->font_table[i].name);
5384 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5387 x_destroy_all_bitmaps (dpyinfo);
5388 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5390 #ifdef USE_X_TOOLKIT
5391 XtCloseDisplay (dpyinfo->display);
5392 #else
5393 XCloseDisplay (dpyinfo->display);
5394 #endif
5396 x_delete_display (dpyinfo);
5397 UNBLOCK_INPUT;
5399 return Qnil;
5402 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5403 doc: /* Return the list of display names that Emacs has connections to. */)
5406 Lisp_Object tail, result;
5408 result = Qnil;
5409 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5410 result = Fcons (XCAR (XCAR (tail)), result);
5412 return result;
5415 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5416 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5417 If ON is nil, allow buffering of requests.
5418 Turning on synchronization prohibits the Xlib routines from buffering
5419 requests and seriously degrades performance, but makes debugging much
5420 easier.
5421 The optional second argument DISPLAY specifies which display to act on.
5422 DISPLAY should be either a frame or a display name (a string).
5423 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5424 (on, display)
5425 Lisp_Object display, on;
5427 struct x_display_info *dpyinfo = check_x_display_info (display);
5429 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5431 return Qnil;
5434 /* Wait for responses to all X commands issued so far for frame F. */
5436 void
5437 x_sync (f)
5438 FRAME_PTR f;
5440 BLOCK_INPUT;
5441 XSync (FRAME_X_DISPLAY (f), False);
5442 UNBLOCK_INPUT;
5446 /***********************************************************************
5447 Image types
5448 ***********************************************************************/
5450 /* Value is the number of elements of vector VECTOR. */
5452 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5454 /* List of supported image types. Use define_image_type to add new
5455 types. Use lookup_image_type to find a type for a given symbol. */
5457 static struct image_type *image_types;
5459 /* The symbol `image' which is the car of the lists used to represent
5460 images in Lisp. */
5462 extern Lisp_Object Qimage;
5464 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5466 Lisp_Object Qxbm;
5468 /* Keywords. */
5470 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5471 extern Lisp_Object QCdata, QCtype;
5472 Lisp_Object QCascent, QCmargin, QCrelief;
5473 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5474 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5476 /* Other symbols. */
5478 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5480 /* Time in seconds after which images should be removed from the cache
5481 if not displayed. */
5483 Lisp_Object Vimage_cache_eviction_delay;
5485 /* Function prototypes. */
5487 static void define_image_type P_ ((struct image_type *type));
5488 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5489 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5490 static void x_laplace P_ ((struct frame *, struct image *));
5491 static void x_emboss P_ ((struct frame *, struct image *));
5492 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5493 Lisp_Object));
5496 /* Define a new image type from TYPE. This adds a copy of TYPE to
5497 image_types and adds the symbol *TYPE->type to Vimage_types. */
5499 static void
5500 define_image_type (type)
5501 struct image_type *type;
5503 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5504 The initialized data segment is read-only. */
5505 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5506 bcopy (type, p, sizeof *p);
5507 p->next = image_types;
5508 image_types = p;
5509 Vimage_types = Fcons (*p->type, Vimage_types);
5513 /* Look up image type SYMBOL, and return a pointer to its image_type
5514 structure. Value is null if SYMBOL is not a known image type. */
5516 static INLINE struct image_type *
5517 lookup_image_type (symbol)
5518 Lisp_Object symbol;
5520 struct image_type *type;
5522 for (type = image_types; type; type = type->next)
5523 if (EQ (symbol, *type->type))
5524 break;
5526 return type;
5530 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5531 valid image specification is a list whose car is the symbol
5532 `image', and whose rest is a property list. The property list must
5533 contain a value for key `:type'. That value must be the name of a
5534 supported image type. The rest of the property list depends on the
5535 image type. */
5538 valid_image_p (object)
5539 Lisp_Object object;
5541 int valid_p = 0;
5543 if (CONSP (object) && EQ (XCAR (object), Qimage))
5545 Lisp_Object tem;
5547 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5548 if (EQ (XCAR (tem), QCtype))
5550 tem = XCDR (tem);
5551 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5553 struct image_type *type;
5554 type = lookup_image_type (XCAR (tem));
5555 if (type)
5556 valid_p = type->valid_p (object);
5559 break;
5563 return valid_p;
5567 /* Log error message with format string FORMAT and argument ARG.
5568 Signaling an error, e.g. when an image cannot be loaded, is not a
5569 good idea because this would interrupt redisplay, and the error
5570 message display would lead to another redisplay. This function
5571 therefore simply displays a message. */
5573 static void
5574 image_error (format, arg1, arg2)
5575 char *format;
5576 Lisp_Object arg1, arg2;
5578 add_to_log (format, arg1, arg2);
5583 /***********************************************************************
5584 Image specifications
5585 ***********************************************************************/
5587 enum image_value_type
5589 IMAGE_DONT_CHECK_VALUE_TYPE,
5590 IMAGE_STRING_VALUE,
5591 IMAGE_STRING_OR_NIL_VALUE,
5592 IMAGE_SYMBOL_VALUE,
5593 IMAGE_POSITIVE_INTEGER_VALUE,
5594 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5595 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5596 IMAGE_ASCENT_VALUE,
5597 IMAGE_INTEGER_VALUE,
5598 IMAGE_FUNCTION_VALUE,
5599 IMAGE_NUMBER_VALUE,
5600 IMAGE_BOOL_VALUE
5603 /* Structure used when parsing image specifications. */
5605 struct image_keyword
5607 /* Name of keyword. */
5608 char *name;
5610 /* The type of value allowed. */
5611 enum image_value_type type;
5613 /* Non-zero means key must be present. */
5614 int mandatory_p;
5616 /* Used to recognize duplicate keywords in a property list. */
5617 int count;
5619 /* The value that was found. */
5620 Lisp_Object value;
5624 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5625 int, Lisp_Object));
5626 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5629 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5630 has the format (image KEYWORD VALUE ...). One of the keyword/
5631 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5632 image_keywords structures of size NKEYWORDS describing other
5633 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5635 static int
5636 parse_image_spec (spec, keywords, nkeywords, type)
5637 Lisp_Object spec;
5638 struct image_keyword *keywords;
5639 int nkeywords;
5640 Lisp_Object type;
5642 int i;
5643 Lisp_Object plist;
5645 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5646 return 0;
5648 plist = XCDR (spec);
5649 while (CONSP (plist))
5651 Lisp_Object key, value;
5653 /* First element of a pair must be a symbol. */
5654 key = XCAR (plist);
5655 plist = XCDR (plist);
5656 if (!SYMBOLP (key))
5657 return 0;
5659 /* There must follow a value. */
5660 if (!CONSP (plist))
5661 return 0;
5662 value = XCAR (plist);
5663 plist = XCDR (plist);
5665 /* Find key in KEYWORDS. Error if not found. */
5666 for (i = 0; i < nkeywords; ++i)
5667 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5668 break;
5670 if (i == nkeywords)
5671 continue;
5673 /* Record that we recognized the keyword. If a keywords
5674 was found more than once, it's an error. */
5675 keywords[i].value = value;
5676 ++keywords[i].count;
5678 if (keywords[i].count > 1)
5679 return 0;
5681 /* Check type of value against allowed type. */
5682 switch (keywords[i].type)
5684 case IMAGE_STRING_VALUE:
5685 if (!STRINGP (value))
5686 return 0;
5687 break;
5689 case IMAGE_STRING_OR_NIL_VALUE:
5690 if (!STRINGP (value) && !NILP (value))
5691 return 0;
5692 break;
5694 case IMAGE_SYMBOL_VALUE:
5695 if (!SYMBOLP (value))
5696 return 0;
5697 break;
5699 case IMAGE_POSITIVE_INTEGER_VALUE:
5700 if (!INTEGERP (value) || XINT (value) <= 0)
5701 return 0;
5702 break;
5704 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5705 if (INTEGERP (value) && XINT (value) >= 0)
5706 break;
5707 if (CONSP (value)
5708 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5709 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5710 break;
5711 return 0;
5713 case IMAGE_ASCENT_VALUE:
5714 if (SYMBOLP (value) && EQ (value, Qcenter))
5715 break;
5716 else if (INTEGERP (value)
5717 && XINT (value) >= 0
5718 && XINT (value) <= 100)
5719 break;
5720 return 0;
5722 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5723 if (!INTEGERP (value) || XINT (value) < 0)
5724 return 0;
5725 break;
5727 case IMAGE_DONT_CHECK_VALUE_TYPE:
5728 break;
5730 case IMAGE_FUNCTION_VALUE:
5731 value = indirect_function (value);
5732 if (SUBRP (value)
5733 || COMPILEDP (value)
5734 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5735 break;
5736 return 0;
5738 case IMAGE_NUMBER_VALUE:
5739 if (!INTEGERP (value) && !FLOATP (value))
5740 return 0;
5741 break;
5743 case IMAGE_INTEGER_VALUE:
5744 if (!INTEGERP (value))
5745 return 0;
5746 break;
5748 case IMAGE_BOOL_VALUE:
5749 if (!NILP (value) && !EQ (value, Qt))
5750 return 0;
5751 break;
5753 default:
5754 abort ();
5755 break;
5758 if (EQ (key, QCtype) && !EQ (type, value))
5759 return 0;
5762 /* Check that all mandatory fields are present. */
5763 for (i = 0; i < nkeywords; ++i)
5764 if (keywords[i].mandatory_p && keywords[i].count == 0)
5765 return 0;
5767 return NILP (plist);
5771 /* Return the value of KEY in image specification SPEC. Value is nil
5772 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5773 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5775 static Lisp_Object
5776 image_spec_value (spec, key, found)
5777 Lisp_Object spec, key;
5778 int *found;
5780 Lisp_Object tail;
5782 xassert (valid_image_p (spec));
5784 for (tail = XCDR (spec);
5785 CONSP (tail) && CONSP (XCDR (tail));
5786 tail = XCDR (XCDR (tail)))
5788 if (EQ (XCAR (tail), key))
5790 if (found)
5791 *found = 1;
5792 return XCAR (XCDR (tail));
5796 if (found)
5797 *found = 0;
5798 return Qnil;
5802 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5803 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5804 PIXELS non-nil means return the size in pixels, otherwise return the
5805 size in canonical character units.
5806 FRAME is the frame on which the image will be displayed. FRAME nil
5807 or omitted means use the selected frame. */)
5808 (spec, pixels, frame)
5809 Lisp_Object spec, pixels, frame;
5811 Lisp_Object size;
5813 size = Qnil;
5814 if (valid_image_p (spec))
5816 struct frame *f = check_x_frame (frame);
5817 int id = lookup_image (f, spec);
5818 struct image *img = IMAGE_FROM_ID (f, id);
5819 int width = img->width + 2 * img->hmargin;
5820 int height = img->height + 2 * img->vmargin;
5822 if (NILP (pixels))
5823 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5824 make_float ((double) height / CANON_Y_UNIT (f)));
5825 else
5826 size = Fcons (make_number (width), make_number (height));
5828 else
5829 error ("Invalid image specification");
5831 return size;
5835 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5836 doc: /* Return t if image SPEC has a mask bitmap.
5837 FRAME is the frame on which the image will be displayed. FRAME nil
5838 or omitted means use the selected frame. */)
5839 (spec, frame)
5840 Lisp_Object spec, frame;
5842 Lisp_Object mask;
5844 mask = Qnil;
5845 if (valid_image_p (spec))
5847 struct frame *f = check_x_frame (frame);
5848 int id = lookup_image (f, spec);
5849 struct image *img = IMAGE_FROM_ID (f, id);
5850 if (img->mask)
5851 mask = Qt;
5853 else
5854 error ("Invalid image specification");
5856 return mask;
5861 /***********************************************************************
5862 Image type independent image structures
5863 ***********************************************************************/
5865 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5866 static void free_image P_ ((struct frame *f, struct image *img));
5869 /* Allocate and return a new image structure for image specification
5870 SPEC. SPEC has a hash value of HASH. */
5872 static struct image *
5873 make_image (spec, hash)
5874 Lisp_Object spec;
5875 unsigned hash;
5877 struct image *img = (struct image *) xmalloc (sizeof *img);
5879 xassert (valid_image_p (spec));
5880 bzero (img, sizeof *img);
5881 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5882 xassert (img->type != NULL);
5883 img->spec = spec;
5884 img->data.lisp_val = Qnil;
5885 img->ascent = DEFAULT_IMAGE_ASCENT;
5886 img->hash = hash;
5887 return img;
5891 /* Free image IMG which was used on frame F, including its resources. */
5893 static void
5894 free_image (f, img)
5895 struct frame *f;
5896 struct image *img;
5898 if (img)
5900 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5902 /* Remove IMG from the hash table of its cache. */
5903 if (img->prev)
5904 img->prev->next = img->next;
5905 else
5906 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5908 if (img->next)
5909 img->next->prev = img->prev;
5911 c->images[img->id] = NULL;
5913 /* Free resources, then free IMG. */
5914 img->type->free (f, img);
5915 xfree (img);
5920 /* Prepare image IMG for display on frame F. Must be called before
5921 drawing an image. */
5923 void
5924 prepare_image_for_display (f, img)
5925 struct frame *f;
5926 struct image *img;
5928 EMACS_TIME t;
5930 /* We're about to display IMG, so set its timestamp to `now'. */
5931 EMACS_GET_TIME (t);
5932 img->timestamp = EMACS_SECS (t);
5934 /* If IMG doesn't have a pixmap yet, load it now, using the image
5935 type dependent loader function. */
5936 if (img->pixmap == None && !img->load_failed_p)
5937 img->load_failed_p = img->type->load (f, img) == 0;
5941 /* Value is the number of pixels for the ascent of image IMG when
5942 drawn in face FACE. */
5945 image_ascent (img, face)
5946 struct image *img;
5947 struct face *face;
5949 int height = img->height + img->vmargin;
5950 int ascent;
5952 if (img->ascent == CENTERED_IMAGE_ASCENT)
5954 if (face->font)
5955 /* This expression is arranged so that if the image can't be
5956 exactly centered, it will be moved slightly up. This is
5957 because a typical font is `top-heavy' (due to the presence
5958 uppercase letters), so the image placement should err towards
5959 being top-heavy too. It also just generally looks better. */
5960 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5961 else
5962 ascent = height / 2;
5964 else
5965 ascent = height * img->ascent / 100.0;
5967 return ascent;
5971 /* Image background colors. */
5973 static unsigned long
5974 four_corners_best (ximg, width, height)
5975 XImage *ximg;
5976 unsigned long width, height;
5978 unsigned long corners[4], best;
5979 int i, best_count;
5981 /* Get the colors at the corners of ximg. */
5982 corners[0] = XGetPixel (ximg, 0, 0);
5983 corners[1] = XGetPixel (ximg, width - 1, 0);
5984 corners[2] = XGetPixel (ximg, width - 1, height - 1);
5985 corners[3] = XGetPixel (ximg, 0, height - 1);
5987 /* Choose the most frequently found color as background. */
5988 for (i = best_count = 0; i < 4; ++i)
5990 int j, n;
5992 for (j = n = 0; j < 4; ++j)
5993 if (corners[i] == corners[j])
5994 ++n;
5996 if (n > best_count)
5997 best = corners[i], best_count = n;
6000 return best;
6003 /* Return the `background' field of IMG. If IMG doesn't have one yet,
6004 it is guessed heuristically. If non-zero, XIMG is an existing XImage
6005 object to use for the heuristic. */
6007 unsigned long
6008 image_background (img, f, ximg)
6009 struct image *img;
6010 struct frame *f;
6011 XImage *ximg;
6013 if (! img->background_valid)
6014 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6016 int free_ximg = !ximg;
6018 if (! ximg)
6019 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6020 0, 0, img->width, img->height, ~0, ZPixmap);
6022 img->background = four_corners_best (ximg, img->width, img->height);
6024 if (free_ximg)
6025 XDestroyImage (ximg);
6027 img->background_valid = 1;
6030 return img->background;
6033 /* Return the `background_transparent' field of IMG. If IMG doesn't
6034 have one yet, it is guessed heuristically. If non-zero, MASK is an
6035 existing XImage object to use for the heuristic. */
6038 image_background_transparent (img, f, mask)
6039 struct image *img;
6040 struct frame *f;
6041 XImage *mask;
6043 if (! img->background_transparent_valid)
6044 /* IMG doesn't have a background yet, try to guess a reasonable value. */
6046 if (img->mask)
6048 int free_mask = !mask;
6050 if (! mask)
6051 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
6052 0, 0, img->width, img->height, ~0, ZPixmap);
6054 img->background_transparent
6055 = !four_corners_best (mask, img->width, img->height);
6057 if (free_mask)
6058 XDestroyImage (mask);
6060 else
6061 img->background_transparent = 0;
6063 img->background_transparent_valid = 1;
6066 return img->background_transparent;
6070 /***********************************************************************
6071 Helper functions for X image types
6072 ***********************************************************************/
6074 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
6075 int, int));
6076 static void x_clear_image P_ ((struct frame *f, struct image *img));
6077 static unsigned long x_alloc_image_color P_ ((struct frame *f,
6078 struct image *img,
6079 Lisp_Object color_name,
6080 unsigned long dflt));
6083 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6084 free the pixmap if any. MASK_P non-zero means clear the mask
6085 pixmap if any. COLORS_P non-zero means free colors allocated for
6086 the image, if any. */
6088 static void
6089 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
6090 struct frame *f;
6091 struct image *img;
6092 int pixmap_p, mask_p, colors_p;
6094 if (pixmap_p && img->pixmap)
6096 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
6097 img->pixmap = None;
6098 img->background_valid = 0;
6101 if (mask_p && img->mask)
6103 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6104 img->mask = None;
6105 img->background_transparent_valid = 0;
6108 if (colors_p && img->ncolors)
6110 x_free_colors (f, img->colors, img->ncolors);
6111 xfree (img->colors);
6112 img->colors = NULL;
6113 img->ncolors = 0;
6117 /* Free X resources of image IMG which is used on frame F. */
6119 static void
6120 x_clear_image (f, img)
6121 struct frame *f;
6122 struct image *img;
6124 BLOCK_INPUT;
6125 x_clear_image_1 (f, img, 1, 1, 1);
6126 UNBLOCK_INPUT;
6130 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6131 cannot be allocated, use DFLT. Add a newly allocated color to
6132 IMG->colors, so that it can be freed again. Value is the pixel
6133 color. */
6135 static unsigned long
6136 x_alloc_image_color (f, img, color_name, dflt)
6137 struct frame *f;
6138 struct image *img;
6139 Lisp_Object color_name;
6140 unsigned long dflt;
6142 XColor color;
6143 unsigned long result;
6145 xassert (STRINGP (color_name));
6147 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
6149 /* This isn't called frequently so we get away with simply
6150 reallocating the color vector to the needed size, here. */
6151 ++img->ncolors;
6152 img->colors =
6153 (unsigned long *) xrealloc (img->colors,
6154 img->ncolors * sizeof *img->colors);
6155 img->colors[img->ncolors - 1] = color.pixel;
6156 result = color.pixel;
6158 else
6159 result = dflt;
6161 return result;
6166 /***********************************************************************
6167 Image Cache
6168 ***********************************************************************/
6170 static void cache_image P_ ((struct frame *f, struct image *img));
6171 static void postprocess_image P_ ((struct frame *, struct image *));
6174 /* Return a new, initialized image cache that is allocated from the
6175 heap. Call free_image_cache to free an image cache. */
6177 struct image_cache *
6178 make_image_cache ()
6180 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
6181 int size;
6183 bzero (c, sizeof *c);
6184 c->size = 50;
6185 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
6186 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
6187 c->buckets = (struct image **) xmalloc (size);
6188 bzero (c->buckets, size);
6189 return c;
6193 /* Free image cache of frame F. Be aware that X frames share images
6194 caches. */
6196 void
6197 free_image_cache (f)
6198 struct frame *f;
6200 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6201 if (c)
6203 int i;
6205 /* Cache should not be referenced by any frame when freed. */
6206 xassert (c->refcount == 0);
6208 for (i = 0; i < c->used; ++i)
6209 free_image (f, c->images[i]);
6210 xfree (c->images);
6211 xfree (c->buckets);
6212 xfree (c);
6213 FRAME_X_IMAGE_CACHE (f) = NULL;
6218 /* Clear image cache of frame F. FORCE_P non-zero means free all
6219 images. FORCE_P zero means clear only images that haven't been
6220 displayed for some time. Should be called from time to time to
6221 reduce the number of loaded images. If image-eviction-seconds is
6222 non-nil, this frees images in the cache which weren't displayed for
6223 at least that many seconds. */
6225 void
6226 clear_image_cache (f, force_p)
6227 struct frame *f;
6228 int force_p;
6230 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6232 if (c && INTEGERP (Vimage_cache_eviction_delay))
6234 EMACS_TIME t;
6235 unsigned long old;
6236 int i, nfreed;
6238 EMACS_GET_TIME (t);
6239 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
6241 /* Block input so that we won't be interrupted by a SIGIO
6242 while being in an inconsistent state. */
6243 BLOCK_INPUT;
6245 for (i = nfreed = 0; i < c->used; ++i)
6247 struct image *img = c->images[i];
6248 if (img != NULL
6249 && (force_p || img->timestamp < old))
6251 free_image (f, img);
6252 ++nfreed;
6256 /* We may be clearing the image cache because, for example,
6257 Emacs was iconified for a longer period of time. In that
6258 case, current matrices may still contain references to
6259 images freed above. So, clear these matrices. */
6260 if (nfreed)
6262 Lisp_Object tail, frame;
6264 FOR_EACH_FRAME (tail, frame)
6266 struct frame *f = XFRAME (frame);
6267 if (FRAME_X_P (f)
6268 && FRAME_X_IMAGE_CACHE (f) == c)
6269 clear_current_matrices (f);
6272 ++windows_or_buffers_changed;
6275 UNBLOCK_INPUT;
6280 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
6281 0, 1, 0,
6282 doc: /* Clear the image cache of FRAME.
6283 FRAME nil or omitted means use the selected frame.
6284 FRAME t means clear the image caches of all frames. */)
6285 (frame)
6286 Lisp_Object frame;
6288 if (EQ (frame, Qt))
6290 Lisp_Object tail;
6292 FOR_EACH_FRAME (tail, frame)
6293 if (FRAME_X_P (XFRAME (frame)))
6294 clear_image_cache (XFRAME (frame), 1);
6296 else
6297 clear_image_cache (check_x_frame (frame), 1);
6299 return Qnil;
6303 /* Compute masks and transform image IMG on frame F, as specified
6304 by the image's specification, */
6306 static void
6307 postprocess_image (f, img)
6308 struct frame *f;
6309 struct image *img;
6311 /* Manipulation of the image's mask. */
6312 if (img->pixmap)
6314 Lisp_Object conversion, spec;
6315 Lisp_Object mask;
6317 spec = img->spec;
6319 /* `:heuristic-mask t'
6320 `:mask heuristic'
6321 means build a mask heuristically.
6322 `:heuristic-mask (R G B)'
6323 `:mask (heuristic (R G B))'
6324 means build a mask from color (R G B) in the
6325 image.
6326 `:mask nil'
6327 means remove a mask, if any. */
6329 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6330 if (!NILP (mask))
6331 x_build_heuristic_mask (f, img, mask);
6332 else
6334 int found_p;
6336 mask = image_spec_value (spec, QCmask, &found_p);
6338 if (EQ (mask, Qheuristic))
6339 x_build_heuristic_mask (f, img, Qt);
6340 else if (CONSP (mask)
6341 && EQ (XCAR (mask), Qheuristic))
6343 if (CONSP (XCDR (mask)))
6344 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6345 else
6346 x_build_heuristic_mask (f, img, XCDR (mask));
6348 else if (NILP (mask) && found_p && img->mask)
6350 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6351 img->mask = None;
6356 /* Should we apply an image transformation algorithm? */
6357 conversion = image_spec_value (spec, QCconversion, NULL);
6358 if (EQ (conversion, Qdisabled))
6359 x_disable_image (f, img);
6360 else if (EQ (conversion, Qlaplace))
6361 x_laplace (f, img);
6362 else if (EQ (conversion, Qemboss))
6363 x_emboss (f, img);
6364 else if (CONSP (conversion)
6365 && EQ (XCAR (conversion), Qedge_detection))
6367 Lisp_Object tem;
6368 tem = XCDR (conversion);
6369 if (CONSP (tem))
6370 x_edge_detection (f, img,
6371 Fplist_get (tem, QCmatrix),
6372 Fplist_get (tem, QCcolor_adjustment));
6378 /* Return the id of image with Lisp specification SPEC on frame F.
6379 SPEC must be a valid Lisp image specification (see valid_image_p). */
6382 lookup_image (f, spec)
6383 struct frame *f;
6384 Lisp_Object spec;
6386 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6387 struct image *img;
6388 int i;
6389 unsigned hash;
6390 struct gcpro gcpro1;
6391 EMACS_TIME now;
6393 /* F must be a window-system frame, and SPEC must be a valid image
6394 specification. */
6395 xassert (FRAME_WINDOW_P (f));
6396 xassert (valid_image_p (spec));
6398 GCPRO1 (spec);
6400 /* Look up SPEC in the hash table of the image cache. */
6401 hash = sxhash (spec, 0);
6402 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6404 for (img = c->buckets[i]; img; img = img->next)
6405 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6406 break;
6408 /* If not found, create a new image and cache it. */
6409 if (img == NULL)
6411 extern Lisp_Object Qpostscript;
6413 BLOCK_INPUT;
6414 img = make_image (spec, hash);
6415 cache_image (f, img);
6416 img->load_failed_p = img->type->load (f, img) == 0;
6418 /* If we can't load the image, and we don't have a width and
6419 height, use some arbitrary width and height so that we can
6420 draw a rectangle for it. */
6421 if (img->load_failed_p)
6423 Lisp_Object value;
6425 value = image_spec_value (spec, QCwidth, NULL);
6426 img->width = (INTEGERP (value)
6427 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6428 value = image_spec_value (spec, QCheight, NULL);
6429 img->height = (INTEGERP (value)
6430 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6432 else
6434 /* Handle image type independent image attributes
6435 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6436 `:background COLOR'. */
6437 Lisp_Object ascent, margin, relief, bg;
6439 ascent = image_spec_value (spec, QCascent, NULL);
6440 if (INTEGERP (ascent))
6441 img->ascent = XFASTINT (ascent);
6442 else if (EQ (ascent, Qcenter))
6443 img->ascent = CENTERED_IMAGE_ASCENT;
6445 margin = image_spec_value (spec, QCmargin, NULL);
6446 if (INTEGERP (margin) && XINT (margin) >= 0)
6447 img->vmargin = img->hmargin = XFASTINT (margin);
6448 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6449 && INTEGERP (XCDR (margin)))
6451 if (XINT (XCAR (margin)) > 0)
6452 img->hmargin = XFASTINT (XCAR (margin));
6453 if (XINT (XCDR (margin)) > 0)
6454 img->vmargin = XFASTINT (XCDR (margin));
6457 relief = image_spec_value (spec, QCrelief, NULL);
6458 if (INTEGERP (relief))
6460 img->relief = XINT (relief);
6461 img->hmargin += abs (img->relief);
6462 img->vmargin += abs (img->relief);
6465 if (! img->background_valid)
6467 bg = image_spec_value (img->spec, QCbackground, NULL);
6468 if (!NILP (bg))
6470 img->background
6471 = x_alloc_image_color (f, img, bg,
6472 FRAME_BACKGROUND_PIXEL (f));
6473 img->background_valid = 1;
6477 /* Do image transformations and compute masks, unless we
6478 don't have the image yet. */
6479 if (!EQ (*img->type->type, Qpostscript))
6480 postprocess_image (f, img);
6483 UNBLOCK_INPUT;
6484 xassert (!interrupt_input_blocked);
6487 /* We're using IMG, so set its timestamp to `now'. */
6488 EMACS_GET_TIME (now);
6489 img->timestamp = EMACS_SECS (now);
6491 UNGCPRO;
6493 /* Value is the image id. */
6494 return img->id;
6498 /* Cache image IMG in the image cache of frame F. */
6500 static void
6501 cache_image (f, img)
6502 struct frame *f;
6503 struct image *img;
6505 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6506 int i;
6508 /* Find a free slot in c->images. */
6509 for (i = 0; i < c->used; ++i)
6510 if (c->images[i] == NULL)
6511 break;
6513 /* If no free slot found, maybe enlarge c->images. */
6514 if (i == c->used && c->used == c->size)
6516 c->size *= 2;
6517 c->images = (struct image **) xrealloc (c->images,
6518 c->size * sizeof *c->images);
6521 /* Add IMG to c->images, and assign IMG an id. */
6522 c->images[i] = img;
6523 img->id = i;
6524 if (i == c->used)
6525 ++c->used;
6527 /* Add IMG to the cache's hash table. */
6528 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6529 img->next = c->buckets[i];
6530 if (img->next)
6531 img->next->prev = img;
6532 img->prev = NULL;
6533 c->buckets[i] = img;
6537 /* Call FN on every image in the image cache of frame F. Used to mark
6538 Lisp Objects in the image cache. */
6540 void
6541 forall_images_in_image_cache (f, fn)
6542 struct frame *f;
6543 void (*fn) P_ ((struct image *img));
6545 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6547 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6548 if (c)
6550 int i;
6551 for (i = 0; i < c->used; ++i)
6552 if (c->images[i])
6553 fn (c->images[i]);
6560 /***********************************************************************
6561 X support code
6562 ***********************************************************************/
6564 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6565 XImage **, Pixmap *));
6566 static void x_destroy_x_image P_ ((XImage *));
6567 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6570 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6571 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6572 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6573 via xmalloc. Print error messages via image_error if an error
6574 occurs. Value is non-zero if successful. */
6576 static int
6577 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6578 struct frame *f;
6579 int width, height, depth;
6580 XImage **ximg;
6581 Pixmap *pixmap;
6583 Display *display = FRAME_X_DISPLAY (f);
6584 Screen *screen = FRAME_X_SCREEN (f);
6585 Window window = FRAME_X_WINDOW (f);
6587 xassert (interrupt_input_blocked);
6589 if (depth <= 0)
6590 depth = DefaultDepthOfScreen (screen);
6591 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6592 depth, ZPixmap, 0, NULL, width, height,
6593 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6594 if (*ximg == NULL)
6596 image_error ("Unable to allocate X image", Qnil, Qnil);
6597 return 0;
6600 /* Allocate image raster. */
6601 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6603 /* Allocate a pixmap of the same size. */
6604 *pixmap = XCreatePixmap (display, window, width, height, depth);
6605 if (*pixmap == None)
6607 x_destroy_x_image (*ximg);
6608 *ximg = NULL;
6609 image_error ("Unable to create X pixmap", Qnil, Qnil);
6610 return 0;
6613 return 1;
6617 /* Destroy XImage XIMG. Free XIMG->data. */
6619 static void
6620 x_destroy_x_image (ximg)
6621 XImage *ximg;
6623 xassert (interrupt_input_blocked);
6624 if (ximg)
6626 xfree (ximg->data);
6627 ximg->data = NULL;
6628 XDestroyImage (ximg);
6633 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6634 are width and height of both the image and pixmap. */
6636 static void
6637 x_put_x_image (f, ximg, pixmap, width, height)
6638 struct frame *f;
6639 XImage *ximg;
6640 Pixmap pixmap;
6642 GC gc;
6644 xassert (interrupt_input_blocked);
6645 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6646 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6647 XFreeGC (FRAME_X_DISPLAY (f), gc);
6652 /***********************************************************************
6653 File Handling
6654 ***********************************************************************/
6656 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6657 static char *slurp_file P_ ((char *, int *));
6660 /* Find image file FILE. Look in data-directory, then
6661 x-bitmap-file-path. Value is the full name of the file found, or
6662 nil if not found. */
6664 static Lisp_Object
6665 x_find_image_file (file)
6666 Lisp_Object file;
6668 Lisp_Object file_found, search_path;
6669 struct gcpro gcpro1, gcpro2;
6670 int fd;
6672 file_found = Qnil;
6673 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6674 GCPRO2 (file_found, search_path);
6676 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6677 fd = openp (search_path, file, Qnil, &file_found, Qnil);
6679 if (fd == -1)
6680 file_found = Qnil;
6681 else
6682 close (fd);
6684 UNGCPRO;
6685 return file_found;
6689 /* Read FILE into memory. Value is a pointer to a buffer allocated
6690 with xmalloc holding FILE's contents. Value is null if an error
6691 occurred. *SIZE is set to the size of the file. */
6693 static char *
6694 slurp_file (file, size)
6695 char *file;
6696 int *size;
6698 FILE *fp = NULL;
6699 char *buf = NULL;
6700 struct stat st;
6702 if (stat (file, &st) == 0
6703 && (fp = fopen (file, "r")) != NULL
6704 && (buf = (char *) xmalloc (st.st_size),
6705 fread (buf, 1, st.st_size, fp) == st.st_size))
6707 *size = st.st_size;
6708 fclose (fp);
6710 else
6712 if (fp)
6713 fclose (fp);
6714 if (buf)
6716 xfree (buf);
6717 buf = NULL;
6721 return buf;
6726 /***********************************************************************
6727 XBM images
6728 ***********************************************************************/
6730 static int xbm_scan P_ ((char **, char *, char *, int *));
6731 static int xbm_load P_ ((struct frame *f, struct image *img));
6732 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6733 char *, char *));
6734 static int xbm_image_p P_ ((Lisp_Object object));
6735 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6736 unsigned char **));
6737 static int xbm_file_p P_ ((Lisp_Object));
6740 /* Indices of image specification fields in xbm_format, below. */
6742 enum xbm_keyword_index
6744 XBM_TYPE,
6745 XBM_FILE,
6746 XBM_WIDTH,
6747 XBM_HEIGHT,
6748 XBM_DATA,
6749 XBM_FOREGROUND,
6750 XBM_BACKGROUND,
6751 XBM_ASCENT,
6752 XBM_MARGIN,
6753 XBM_RELIEF,
6754 XBM_ALGORITHM,
6755 XBM_HEURISTIC_MASK,
6756 XBM_MASK,
6757 XBM_LAST
6760 /* Vector of image_keyword structures describing the format
6761 of valid XBM image specifications. */
6763 static struct image_keyword xbm_format[XBM_LAST] =
6765 {":type", IMAGE_SYMBOL_VALUE, 1},
6766 {":file", IMAGE_STRING_VALUE, 0},
6767 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6768 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6769 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6770 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6771 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6772 {":ascent", IMAGE_ASCENT_VALUE, 0},
6773 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6774 {":relief", IMAGE_INTEGER_VALUE, 0},
6775 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6776 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6777 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6780 /* Structure describing the image type XBM. */
6782 static struct image_type xbm_type =
6784 &Qxbm,
6785 xbm_image_p,
6786 xbm_load,
6787 x_clear_image,
6788 NULL
6791 /* Tokens returned from xbm_scan. */
6793 enum xbm_token
6795 XBM_TK_IDENT = 256,
6796 XBM_TK_NUMBER
6800 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6801 A valid specification is a list starting with the symbol `image'
6802 The rest of the list is a property list which must contain an
6803 entry `:type xbm..
6805 If the specification specifies a file to load, it must contain
6806 an entry `:file FILENAME' where FILENAME is a string.
6808 If the specification is for a bitmap loaded from memory it must
6809 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6810 WIDTH and HEIGHT are integers > 0. DATA may be:
6812 1. a string large enough to hold the bitmap data, i.e. it must
6813 have a size >= (WIDTH + 7) / 8 * HEIGHT
6815 2. a bool-vector of size >= WIDTH * HEIGHT
6817 3. a vector of strings or bool-vectors, one for each line of the
6818 bitmap.
6820 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6821 may not be specified in this case because they are defined in the
6822 XBM file.
6824 Both the file and data forms may contain the additional entries
6825 `:background COLOR' and `:foreground COLOR'. If not present,
6826 foreground and background of the frame on which the image is
6827 displayed is used. */
6829 static int
6830 xbm_image_p (object)
6831 Lisp_Object object;
6833 struct image_keyword kw[XBM_LAST];
6835 bcopy (xbm_format, kw, sizeof kw);
6836 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6837 return 0;
6839 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6841 if (kw[XBM_FILE].count)
6843 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6844 return 0;
6846 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6848 /* In-memory XBM file. */
6849 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6850 return 0;
6852 else
6854 Lisp_Object data;
6855 int width, height;
6857 /* Entries for `:width', `:height' and `:data' must be present. */
6858 if (!kw[XBM_WIDTH].count
6859 || !kw[XBM_HEIGHT].count
6860 || !kw[XBM_DATA].count)
6861 return 0;
6863 data = kw[XBM_DATA].value;
6864 width = XFASTINT (kw[XBM_WIDTH].value);
6865 height = XFASTINT (kw[XBM_HEIGHT].value);
6867 /* Check type of data, and width and height against contents of
6868 data. */
6869 if (VECTORP (data))
6871 int i;
6873 /* Number of elements of the vector must be >= height. */
6874 if (XVECTOR (data)->size < height)
6875 return 0;
6877 /* Each string or bool-vector in data must be large enough
6878 for one line of the image. */
6879 for (i = 0; i < height; ++i)
6881 Lisp_Object elt = XVECTOR (data)->contents[i];
6883 if (STRINGP (elt))
6885 if (XSTRING (elt)->size
6886 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6887 return 0;
6889 else if (BOOL_VECTOR_P (elt))
6891 if (XBOOL_VECTOR (elt)->size < width)
6892 return 0;
6894 else
6895 return 0;
6898 else if (STRINGP (data))
6900 if (XSTRING (data)->size
6901 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6902 return 0;
6904 else if (BOOL_VECTOR_P (data))
6906 if (XBOOL_VECTOR (data)->size < width * height)
6907 return 0;
6909 else
6910 return 0;
6913 return 1;
6917 /* Scan a bitmap file. FP is the stream to read from. Value is
6918 either an enumerator from enum xbm_token, or a character for a
6919 single-character token, or 0 at end of file. If scanning an
6920 identifier, store the lexeme of the identifier in SVAL. If
6921 scanning a number, store its value in *IVAL. */
6923 static int
6924 xbm_scan (s, end, sval, ival)
6925 char **s, *end;
6926 char *sval;
6927 int *ival;
6929 int c;
6931 loop:
6933 /* Skip white space. */
6934 while (*s < end && (c = *(*s)++, isspace (c)))
6937 if (*s >= end)
6938 c = 0;
6939 else if (isdigit (c))
6941 int value = 0, digit;
6943 if (c == '0' && *s < end)
6945 c = *(*s)++;
6946 if (c == 'x' || c == 'X')
6948 while (*s < end)
6950 c = *(*s)++;
6951 if (isdigit (c))
6952 digit = c - '0';
6953 else if (c >= 'a' && c <= 'f')
6954 digit = c - 'a' + 10;
6955 else if (c >= 'A' && c <= 'F')
6956 digit = c - 'A' + 10;
6957 else
6958 break;
6959 value = 16 * value + digit;
6962 else if (isdigit (c))
6964 value = c - '0';
6965 while (*s < end
6966 && (c = *(*s)++, isdigit (c)))
6967 value = 8 * value + c - '0';
6970 else
6972 value = c - '0';
6973 while (*s < end
6974 && (c = *(*s)++, isdigit (c)))
6975 value = 10 * value + c - '0';
6978 if (*s < end)
6979 *s = *s - 1;
6980 *ival = value;
6981 c = XBM_TK_NUMBER;
6983 else if (isalpha (c) || c == '_')
6985 *sval++ = c;
6986 while (*s < end
6987 && (c = *(*s)++, (isalnum (c) || c == '_')))
6988 *sval++ = c;
6989 *sval = 0;
6990 if (*s < end)
6991 *s = *s - 1;
6992 c = XBM_TK_IDENT;
6994 else if (c == '/' && **s == '*')
6996 /* C-style comment. */
6997 ++*s;
6998 while (**s && (**s != '*' || *(*s + 1) != '/'))
6999 ++*s;
7000 if (**s)
7002 *s += 2;
7003 goto loop;
7007 return c;
7011 /* Replacement for XReadBitmapFileData which isn't available under old
7012 X versions. CONTENTS is a pointer to a buffer to parse; END is the
7013 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
7014 the image. Return in *DATA the bitmap data allocated with xmalloc.
7015 Value is non-zero if successful. DATA null means just test if
7016 CONTENTS looks like an in-memory XBM file. */
7018 static int
7019 xbm_read_bitmap_data (contents, end, width, height, data)
7020 char *contents, *end;
7021 int *width, *height;
7022 unsigned char **data;
7024 char *s = contents;
7025 char buffer[BUFSIZ];
7026 int padding_p = 0;
7027 int v10 = 0;
7028 int bytes_per_line, i, nbytes;
7029 unsigned char *p;
7030 int value;
7031 int LA1;
7033 #define match() \
7034 LA1 = xbm_scan (&s, end, buffer, &value)
7036 #define expect(TOKEN) \
7037 if (LA1 != (TOKEN)) \
7038 goto failure; \
7039 else \
7040 match ()
7042 #define expect_ident(IDENT) \
7043 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
7044 match (); \
7045 else \
7046 goto failure
7048 *width = *height = -1;
7049 if (data)
7050 *data = NULL;
7051 LA1 = xbm_scan (&s, end, buffer, &value);
7053 /* Parse defines for width, height and hot-spots. */
7054 while (LA1 == '#')
7056 match ();
7057 expect_ident ("define");
7058 expect (XBM_TK_IDENT);
7060 if (LA1 == XBM_TK_NUMBER);
7062 char *p = strrchr (buffer, '_');
7063 p = p ? p + 1 : buffer;
7064 if (strcmp (p, "width") == 0)
7065 *width = value;
7066 else if (strcmp (p, "height") == 0)
7067 *height = value;
7069 expect (XBM_TK_NUMBER);
7072 if (*width < 0 || *height < 0)
7073 goto failure;
7074 else if (data == NULL)
7075 goto success;
7077 /* Parse bits. Must start with `static'. */
7078 expect_ident ("static");
7079 if (LA1 == XBM_TK_IDENT)
7081 if (strcmp (buffer, "unsigned") == 0)
7083 match ();
7084 expect_ident ("char");
7086 else if (strcmp (buffer, "short") == 0)
7088 match ();
7089 v10 = 1;
7090 if (*width % 16 && *width % 16 < 9)
7091 padding_p = 1;
7093 else if (strcmp (buffer, "char") == 0)
7094 match ();
7095 else
7096 goto failure;
7098 else
7099 goto failure;
7101 expect (XBM_TK_IDENT);
7102 expect ('[');
7103 expect (']');
7104 expect ('=');
7105 expect ('{');
7107 bytes_per_line = (*width + 7) / 8 + padding_p;
7108 nbytes = bytes_per_line * *height;
7109 p = *data = (char *) xmalloc (nbytes);
7111 if (v10)
7113 for (i = 0; i < nbytes; i += 2)
7115 int val = value;
7116 expect (XBM_TK_NUMBER);
7118 *p++ = val;
7119 if (!padding_p || ((i + 2) % bytes_per_line))
7120 *p++ = value >> 8;
7122 if (LA1 == ',' || LA1 == '}')
7123 match ();
7124 else
7125 goto failure;
7128 else
7130 for (i = 0; i < nbytes; ++i)
7132 int val = value;
7133 expect (XBM_TK_NUMBER);
7135 *p++ = val;
7137 if (LA1 == ',' || LA1 == '}')
7138 match ();
7139 else
7140 goto failure;
7144 success:
7145 return 1;
7147 failure:
7149 if (data && *data)
7151 xfree (*data);
7152 *data = NULL;
7154 return 0;
7156 #undef match
7157 #undef expect
7158 #undef expect_ident
7162 /* Load XBM image IMG which will be displayed on frame F from buffer
7163 CONTENTS. END is the end of the buffer. Value is non-zero if
7164 successful. */
7166 static int
7167 xbm_load_image (f, img, contents, end)
7168 struct frame *f;
7169 struct image *img;
7170 char *contents, *end;
7172 int rc;
7173 unsigned char *data;
7174 int success_p = 0;
7176 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
7177 if (rc)
7179 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7180 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7181 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7182 Lisp_Object value;
7184 xassert (img->width > 0 && img->height > 0);
7186 /* Get foreground and background colors, maybe allocate colors. */
7187 value = image_spec_value (img->spec, QCforeground, NULL);
7188 if (!NILP (value))
7189 foreground = x_alloc_image_color (f, img, value, foreground);
7190 value = image_spec_value (img->spec, QCbackground, NULL);
7191 if (!NILP (value))
7193 background = x_alloc_image_color (f, img, value, background);
7194 img->background = background;
7195 img->background_valid = 1;
7198 img->pixmap
7199 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7200 FRAME_X_WINDOW (f),
7201 data,
7202 img->width, img->height,
7203 foreground, background,
7204 depth);
7205 xfree (data);
7207 if (img->pixmap == None)
7209 x_clear_image (f, img);
7210 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
7212 else
7213 success_p = 1;
7215 else
7216 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7218 return success_p;
7222 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7224 static int
7225 xbm_file_p (data)
7226 Lisp_Object data;
7228 int w, h;
7229 return (STRINGP (data)
7230 && xbm_read_bitmap_data (XSTRING (data)->data,
7231 (XSTRING (data)->data
7232 + STRING_BYTES (XSTRING (data))),
7233 &w, &h, NULL));
7237 /* Fill image IMG which is used on frame F with pixmap data. Value is
7238 non-zero if successful. */
7240 static int
7241 xbm_load (f, img)
7242 struct frame *f;
7243 struct image *img;
7245 int success_p = 0;
7246 Lisp_Object file_name;
7248 xassert (xbm_image_p (img->spec));
7250 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7251 file_name = image_spec_value (img->spec, QCfile, NULL);
7252 if (STRINGP (file_name))
7254 Lisp_Object file;
7255 char *contents;
7256 int size;
7257 struct gcpro gcpro1;
7259 file = x_find_image_file (file_name);
7260 GCPRO1 (file);
7261 if (!STRINGP (file))
7263 image_error ("Cannot find image file `%s'", file_name, Qnil);
7264 UNGCPRO;
7265 return 0;
7268 contents = slurp_file (XSTRING (file)->data, &size);
7269 if (contents == NULL)
7271 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7272 UNGCPRO;
7273 return 0;
7276 success_p = xbm_load_image (f, img, contents, contents + size);
7277 UNGCPRO;
7279 else
7281 struct image_keyword fmt[XBM_LAST];
7282 Lisp_Object data;
7283 int depth;
7284 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7285 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7286 char *bits;
7287 int parsed_p;
7288 int in_memory_file_p = 0;
7290 /* See if data looks like an in-memory XBM file. */
7291 data = image_spec_value (img->spec, QCdata, NULL);
7292 in_memory_file_p = xbm_file_p (data);
7294 /* Parse the image specification. */
7295 bcopy (xbm_format, fmt, sizeof fmt);
7296 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
7297 xassert (parsed_p);
7299 /* Get specified width, and height. */
7300 if (!in_memory_file_p)
7302 img->width = XFASTINT (fmt[XBM_WIDTH].value);
7303 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
7304 xassert (img->width > 0 && img->height > 0);
7307 /* Get foreground and background colors, maybe allocate colors. */
7308 if (fmt[XBM_FOREGROUND].count
7309 && STRINGP (fmt[XBM_FOREGROUND].value))
7310 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
7311 foreground);
7312 if (fmt[XBM_BACKGROUND].count
7313 && STRINGP (fmt[XBM_BACKGROUND].value))
7314 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
7315 background);
7317 if (in_memory_file_p)
7318 success_p = xbm_load_image (f, img, XSTRING (data)->data,
7319 (XSTRING (data)->data
7320 + STRING_BYTES (XSTRING (data))));
7321 else
7323 if (VECTORP (data))
7325 int i;
7326 char *p;
7327 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7329 p = bits = (char *) alloca (nbytes * img->height);
7330 for (i = 0; i < img->height; ++i, p += nbytes)
7332 Lisp_Object line = XVECTOR (data)->contents[i];
7333 if (STRINGP (line))
7334 bcopy (XSTRING (line)->data, p, nbytes);
7335 else
7336 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7339 else if (STRINGP (data))
7340 bits = XSTRING (data)->data;
7341 else
7342 bits = XBOOL_VECTOR (data)->data;
7344 /* Create the pixmap. */
7345 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7346 img->pixmap
7347 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7348 FRAME_X_WINDOW (f),
7349 bits,
7350 img->width, img->height,
7351 foreground, background,
7352 depth);
7353 if (img->pixmap)
7354 success_p = 1;
7355 else
7357 image_error ("Unable to create pixmap for XBM image `%s'",
7358 img->spec, Qnil);
7359 x_clear_image (f, img);
7364 return success_p;
7369 /***********************************************************************
7370 XPM images
7371 ***********************************************************************/
7373 #if HAVE_XPM
7375 static int xpm_image_p P_ ((Lisp_Object object));
7376 static int xpm_load P_ ((struct frame *f, struct image *img));
7377 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7379 #include "X11/xpm.h"
7381 /* The symbol `xpm' identifying XPM-format images. */
7383 Lisp_Object Qxpm;
7385 /* Indices of image specification fields in xpm_format, below. */
7387 enum xpm_keyword_index
7389 XPM_TYPE,
7390 XPM_FILE,
7391 XPM_DATA,
7392 XPM_ASCENT,
7393 XPM_MARGIN,
7394 XPM_RELIEF,
7395 XPM_ALGORITHM,
7396 XPM_HEURISTIC_MASK,
7397 XPM_MASK,
7398 XPM_COLOR_SYMBOLS,
7399 XPM_BACKGROUND,
7400 XPM_LAST
7403 /* Vector of image_keyword structures describing the format
7404 of valid XPM image specifications. */
7406 static struct image_keyword xpm_format[XPM_LAST] =
7408 {":type", IMAGE_SYMBOL_VALUE, 1},
7409 {":file", IMAGE_STRING_VALUE, 0},
7410 {":data", IMAGE_STRING_VALUE, 0},
7411 {":ascent", IMAGE_ASCENT_VALUE, 0},
7412 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7413 {":relief", IMAGE_INTEGER_VALUE, 0},
7414 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7415 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7416 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7417 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7418 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7421 /* Structure describing the image type XBM. */
7423 static struct image_type xpm_type =
7425 &Qxpm,
7426 xpm_image_p,
7427 xpm_load,
7428 x_clear_image,
7429 NULL
7433 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7434 functions for allocating image colors. Our own functions handle
7435 color allocation failures more gracefully than the ones on the XPM
7436 lib. */
7438 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7439 #define ALLOC_XPM_COLORS
7440 #endif
7442 #ifdef ALLOC_XPM_COLORS
7444 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7445 static void xpm_free_color_cache P_ ((void));
7446 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7447 static int xpm_color_bucket P_ ((char *));
7448 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7449 XColor *, int));
7451 /* An entry in a hash table used to cache color definitions of named
7452 colors. This cache is necessary to speed up XPM image loading in
7453 case we do color allocations ourselves. Without it, we would need
7454 a call to XParseColor per pixel in the image. */
7456 struct xpm_cached_color
7458 /* Next in collision chain. */
7459 struct xpm_cached_color *next;
7461 /* Color definition (RGB and pixel color). */
7462 XColor color;
7464 /* Color name. */
7465 char name[1];
7468 /* The hash table used for the color cache, and its bucket vector
7469 size. */
7471 #define XPM_COLOR_CACHE_BUCKETS 1001
7472 struct xpm_cached_color **xpm_color_cache;
7474 /* Initialize the color cache. */
7476 static void
7477 xpm_init_color_cache (f, attrs)
7478 struct frame *f;
7479 XpmAttributes *attrs;
7481 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7482 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7483 memset (xpm_color_cache, 0, nbytes);
7484 init_color_table ();
7486 if (attrs->valuemask & XpmColorSymbols)
7488 int i;
7489 XColor color;
7491 for (i = 0; i < attrs->numsymbols; ++i)
7492 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7493 attrs->colorsymbols[i].value, &color))
7495 color.pixel = lookup_rgb_color (f, color.red, color.green,
7496 color.blue);
7497 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7503 /* Free the color cache. */
7505 static void
7506 xpm_free_color_cache ()
7508 struct xpm_cached_color *p, *next;
7509 int i;
7511 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7512 for (p = xpm_color_cache[i]; p; p = next)
7514 next = p->next;
7515 xfree (p);
7518 xfree (xpm_color_cache);
7519 xpm_color_cache = NULL;
7520 free_color_table ();
7524 /* Return the bucket index for color named COLOR_NAME in the color
7525 cache. */
7527 static int
7528 xpm_color_bucket (color_name)
7529 char *color_name;
7531 unsigned h = 0;
7532 char *s;
7534 for (s = color_name; *s; ++s)
7535 h = (h << 2) ^ *s;
7536 return h %= XPM_COLOR_CACHE_BUCKETS;
7540 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7541 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7542 entry added. */
7544 static struct xpm_cached_color *
7545 xpm_cache_color (f, color_name, color, bucket)
7546 struct frame *f;
7547 char *color_name;
7548 XColor *color;
7549 int bucket;
7551 size_t nbytes;
7552 struct xpm_cached_color *p;
7554 if (bucket < 0)
7555 bucket = xpm_color_bucket (color_name);
7557 nbytes = sizeof *p + strlen (color_name);
7558 p = (struct xpm_cached_color *) xmalloc (nbytes);
7559 strcpy (p->name, color_name);
7560 p->color = *color;
7561 p->next = xpm_color_cache[bucket];
7562 xpm_color_cache[bucket] = p;
7563 return p;
7567 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7568 return the cached definition in *COLOR. Otherwise, make a new
7569 entry in the cache and allocate the color. Value is zero if color
7570 allocation failed. */
7572 static int
7573 xpm_lookup_color (f, color_name, color)
7574 struct frame *f;
7575 char *color_name;
7576 XColor *color;
7578 struct xpm_cached_color *p;
7579 int h = xpm_color_bucket (color_name);
7581 for (p = xpm_color_cache[h]; p; p = p->next)
7582 if (strcmp (p->name, color_name) == 0)
7583 break;
7585 if (p != NULL)
7586 *color = p->color;
7587 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7588 color_name, color))
7590 color->pixel = lookup_rgb_color (f, color->red, color->green,
7591 color->blue);
7592 p = xpm_cache_color (f, color_name, color, h);
7595 return p != NULL;
7599 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7600 CLOSURE is a pointer to the frame on which we allocate the
7601 color. Return in *COLOR the allocated color. Value is non-zero
7602 if successful. */
7604 static int
7605 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7606 Display *dpy;
7607 Colormap cmap;
7608 char *color_name;
7609 XColor *color;
7610 void *closure;
7612 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7616 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7617 is a pointer to the frame on which we allocate the color. Value is
7618 non-zero if successful. */
7620 static int
7621 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7622 Display *dpy;
7623 Colormap cmap;
7624 Pixel *pixels;
7625 int npixels;
7626 void *closure;
7628 return 1;
7631 #endif /* ALLOC_XPM_COLORS */
7634 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7635 for XPM images. Such a list must consist of conses whose car and
7636 cdr are strings. */
7638 static int
7639 xpm_valid_color_symbols_p (color_symbols)
7640 Lisp_Object color_symbols;
7642 while (CONSP (color_symbols))
7644 Lisp_Object sym = XCAR (color_symbols);
7645 if (!CONSP (sym)
7646 || !STRINGP (XCAR (sym))
7647 || !STRINGP (XCDR (sym)))
7648 break;
7649 color_symbols = XCDR (color_symbols);
7652 return NILP (color_symbols);
7656 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7658 static int
7659 xpm_image_p (object)
7660 Lisp_Object object;
7662 struct image_keyword fmt[XPM_LAST];
7663 bcopy (xpm_format, fmt, sizeof fmt);
7664 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7665 /* Either `:file' or `:data' must be present. */
7666 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7667 /* Either no `:color-symbols' or it's a list of conses
7668 whose car and cdr are strings. */
7669 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7670 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7674 /* Load image IMG which will be displayed on frame F. Value is
7675 non-zero if successful. */
7677 static int
7678 xpm_load (f, img)
7679 struct frame *f;
7680 struct image *img;
7682 int rc;
7683 XpmAttributes attrs;
7684 Lisp_Object specified_file, color_symbols;
7686 /* Configure the XPM lib. Use the visual of frame F. Allocate
7687 close colors. Return colors allocated. */
7688 bzero (&attrs, sizeof attrs);
7689 attrs.visual = FRAME_X_VISUAL (f);
7690 attrs.colormap = FRAME_X_COLORMAP (f);
7691 attrs.valuemask |= XpmVisual;
7692 attrs.valuemask |= XpmColormap;
7694 #ifdef ALLOC_XPM_COLORS
7695 /* Allocate colors with our own functions which handle
7696 failing color allocation more gracefully. */
7697 attrs.color_closure = f;
7698 attrs.alloc_color = xpm_alloc_color;
7699 attrs.free_colors = xpm_free_colors;
7700 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7701 #else /* not ALLOC_XPM_COLORS */
7702 /* Let the XPM lib allocate colors. */
7703 attrs.valuemask |= XpmReturnAllocPixels;
7704 #ifdef XpmAllocCloseColors
7705 attrs.alloc_close_colors = 1;
7706 attrs.valuemask |= XpmAllocCloseColors;
7707 #else /* not XpmAllocCloseColors */
7708 attrs.closeness = 600;
7709 attrs.valuemask |= XpmCloseness;
7710 #endif /* not XpmAllocCloseColors */
7711 #endif /* ALLOC_XPM_COLORS */
7713 /* If image specification contains symbolic color definitions, add
7714 these to `attrs'. */
7715 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7716 if (CONSP (color_symbols))
7718 Lisp_Object tail;
7719 XpmColorSymbol *xpm_syms;
7720 int i, size;
7722 attrs.valuemask |= XpmColorSymbols;
7724 /* Count number of symbols. */
7725 attrs.numsymbols = 0;
7726 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7727 ++attrs.numsymbols;
7729 /* Allocate an XpmColorSymbol array. */
7730 size = attrs.numsymbols * sizeof *xpm_syms;
7731 xpm_syms = (XpmColorSymbol *) alloca (size);
7732 bzero (xpm_syms, size);
7733 attrs.colorsymbols = xpm_syms;
7735 /* Fill the color symbol array. */
7736 for (tail = color_symbols, i = 0;
7737 CONSP (tail);
7738 ++i, tail = XCDR (tail))
7740 Lisp_Object name = XCAR (XCAR (tail));
7741 Lisp_Object color = XCDR (XCAR (tail));
7742 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7743 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7744 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7745 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7749 /* Create a pixmap for the image, either from a file, or from a
7750 string buffer containing data in the same format as an XPM file. */
7751 #ifdef ALLOC_XPM_COLORS
7752 xpm_init_color_cache (f, &attrs);
7753 #endif
7755 specified_file = image_spec_value (img->spec, QCfile, NULL);
7756 if (STRINGP (specified_file))
7758 Lisp_Object file = x_find_image_file (specified_file);
7759 if (!STRINGP (file))
7761 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7762 return 0;
7765 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7766 XSTRING (file)->data, &img->pixmap, &img->mask,
7767 &attrs);
7769 else
7771 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7772 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7773 XSTRING (buffer)->data,
7774 &img->pixmap, &img->mask,
7775 &attrs);
7778 if (rc == XpmSuccess)
7780 #ifdef ALLOC_XPM_COLORS
7781 img->colors = colors_in_color_table (&img->ncolors);
7782 #else /* not ALLOC_XPM_COLORS */
7783 int i;
7785 img->ncolors = attrs.nalloc_pixels;
7786 img->colors = (unsigned long *) xmalloc (img->ncolors
7787 * sizeof *img->colors);
7788 for (i = 0; i < attrs.nalloc_pixels; ++i)
7790 img->colors[i] = attrs.alloc_pixels[i];
7791 #ifdef DEBUG_X_COLORS
7792 register_color (img->colors[i]);
7793 #endif
7795 #endif /* not ALLOC_XPM_COLORS */
7797 img->width = attrs.width;
7798 img->height = attrs.height;
7799 xassert (img->width > 0 && img->height > 0);
7801 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7802 XpmFreeAttributes (&attrs);
7804 else
7806 switch (rc)
7808 case XpmOpenFailed:
7809 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7810 break;
7812 case XpmFileInvalid:
7813 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7814 break;
7816 case XpmNoMemory:
7817 image_error ("Out of memory (%s)", img->spec, Qnil);
7818 break;
7820 case XpmColorFailed:
7821 image_error ("Color allocation error (%s)", img->spec, Qnil);
7822 break;
7824 default:
7825 image_error ("Unknown error (%s)", img->spec, Qnil);
7826 break;
7830 #ifdef ALLOC_XPM_COLORS
7831 xpm_free_color_cache ();
7832 #endif
7833 return rc == XpmSuccess;
7836 #endif /* HAVE_XPM != 0 */
7839 /***********************************************************************
7840 Color table
7841 ***********************************************************************/
7843 /* An entry in the color table mapping an RGB color to a pixel color. */
7845 struct ct_color
7847 int r, g, b;
7848 unsigned long pixel;
7850 /* Next in color table collision list. */
7851 struct ct_color *next;
7854 /* The bucket vector size to use. Must be prime. */
7856 #define CT_SIZE 101
7858 /* Value is a hash of the RGB color given by R, G, and B. */
7860 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7862 /* The color hash table. */
7864 struct ct_color **ct_table;
7866 /* Number of entries in the color table. */
7868 int ct_colors_allocated;
7870 /* Initialize the color table. */
7872 static void
7873 init_color_table ()
7875 int size = CT_SIZE * sizeof (*ct_table);
7876 ct_table = (struct ct_color **) xmalloc (size);
7877 bzero (ct_table, size);
7878 ct_colors_allocated = 0;
7882 /* Free memory associated with the color table. */
7884 static void
7885 free_color_table ()
7887 int i;
7888 struct ct_color *p, *next;
7890 for (i = 0; i < CT_SIZE; ++i)
7891 for (p = ct_table[i]; p; p = next)
7893 next = p->next;
7894 xfree (p);
7897 xfree (ct_table);
7898 ct_table = NULL;
7902 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7903 entry for that color already is in the color table, return the
7904 pixel color of that entry. Otherwise, allocate a new color for R,
7905 G, B, and make an entry in the color table. */
7907 static unsigned long
7908 lookup_rgb_color (f, r, g, b)
7909 struct frame *f;
7910 int r, g, b;
7912 unsigned hash = CT_HASH_RGB (r, g, b);
7913 int i = hash % CT_SIZE;
7914 struct ct_color *p;
7916 for (p = ct_table[i]; p; p = p->next)
7917 if (p->r == r && p->g == g && p->b == b)
7918 break;
7920 if (p == NULL)
7922 XColor color;
7923 Colormap cmap;
7924 int rc;
7926 color.red = r;
7927 color.green = g;
7928 color.blue = b;
7930 cmap = FRAME_X_COLORMAP (f);
7931 rc = x_alloc_nearest_color (f, cmap, &color);
7933 if (rc)
7935 ++ct_colors_allocated;
7937 p = (struct ct_color *) xmalloc (sizeof *p);
7938 p->r = r;
7939 p->g = g;
7940 p->b = b;
7941 p->pixel = color.pixel;
7942 p->next = ct_table[i];
7943 ct_table[i] = p;
7945 else
7946 return FRAME_FOREGROUND_PIXEL (f);
7949 return p->pixel;
7953 /* Look up pixel color PIXEL which is used on frame F in the color
7954 table. If not already present, allocate it. Value is PIXEL. */
7956 static unsigned long
7957 lookup_pixel_color (f, pixel)
7958 struct frame *f;
7959 unsigned long pixel;
7961 int i = pixel % CT_SIZE;
7962 struct ct_color *p;
7964 for (p = ct_table[i]; p; p = p->next)
7965 if (p->pixel == pixel)
7966 break;
7968 if (p == NULL)
7970 XColor color;
7971 Colormap cmap;
7972 int rc;
7974 cmap = FRAME_X_COLORMAP (f);
7975 color.pixel = pixel;
7976 x_query_color (f, &color);
7977 rc = x_alloc_nearest_color (f, cmap, &color);
7979 if (rc)
7981 ++ct_colors_allocated;
7983 p = (struct ct_color *) xmalloc (sizeof *p);
7984 p->r = color.red;
7985 p->g = color.green;
7986 p->b = color.blue;
7987 p->pixel = pixel;
7988 p->next = ct_table[i];
7989 ct_table[i] = p;
7991 else
7992 return FRAME_FOREGROUND_PIXEL (f);
7995 return p->pixel;
7999 /* Value is a vector of all pixel colors contained in the color table,
8000 allocated via xmalloc. Set *N to the number of colors. */
8002 static unsigned long *
8003 colors_in_color_table (n)
8004 int *n;
8006 int i, j;
8007 struct ct_color *p;
8008 unsigned long *colors;
8010 if (ct_colors_allocated == 0)
8012 *n = 0;
8013 colors = NULL;
8015 else
8017 colors = (unsigned long *) xmalloc (ct_colors_allocated
8018 * sizeof *colors);
8019 *n = ct_colors_allocated;
8021 for (i = j = 0; i < CT_SIZE; ++i)
8022 for (p = ct_table[i]; p; p = p->next)
8023 colors[j++] = p->pixel;
8026 return colors;
8031 /***********************************************************************
8032 Algorithms
8033 ***********************************************************************/
8035 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
8036 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
8037 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
8039 /* Non-zero means draw a cross on images having `:conversion
8040 disabled'. */
8042 int cross_disabled_images;
8044 /* Edge detection matrices for different edge-detection
8045 strategies. */
8047 static int emboss_matrix[9] = {
8048 /* x - 1 x x + 1 */
8049 2, -1, 0, /* y - 1 */
8050 -1, 0, 1, /* y */
8051 0, 1, -2 /* y + 1 */
8054 static int laplace_matrix[9] = {
8055 /* x - 1 x x + 1 */
8056 1, 0, 0, /* y - 1 */
8057 0, 0, 0, /* y */
8058 0, 0, -1 /* y + 1 */
8061 /* Value is the intensity of the color whose red/green/blue values
8062 are R, G, and B. */
8064 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8067 /* On frame F, return an array of XColor structures describing image
8068 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8069 non-zero means also fill the red/green/blue members of the XColor
8070 structures. Value is a pointer to the array of XColors structures,
8071 allocated with xmalloc; it must be freed by the caller. */
8073 static XColor *
8074 x_to_xcolors (f, img, rgb_p)
8075 struct frame *f;
8076 struct image *img;
8077 int rgb_p;
8079 int x, y;
8080 XColor *colors, *p;
8081 XImage *ximg;
8083 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
8085 /* Get the X image IMG->pixmap. */
8086 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8087 0, 0, img->width, img->height, ~0, ZPixmap);
8089 /* Fill the `pixel' members of the XColor array. I wished there
8090 were an easy and portable way to circumvent XGetPixel. */
8091 p = colors;
8092 for (y = 0; y < img->height; ++y)
8094 XColor *row = p;
8096 for (x = 0; x < img->width; ++x, ++p)
8097 p->pixel = XGetPixel (ximg, x, y);
8099 if (rgb_p)
8100 x_query_colors (f, row, img->width);
8103 XDestroyImage (ximg);
8104 return colors;
8108 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8109 RGB members are set. F is the frame on which this all happens.
8110 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8112 static void
8113 x_from_xcolors (f, img, colors)
8114 struct frame *f;
8115 struct image *img;
8116 XColor *colors;
8118 int x, y;
8119 XImage *oimg;
8120 Pixmap pixmap;
8121 XColor *p;
8123 init_color_table ();
8125 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
8126 &oimg, &pixmap);
8127 p = colors;
8128 for (y = 0; y < img->height; ++y)
8129 for (x = 0; x < img->width; ++x, ++p)
8131 unsigned long pixel;
8132 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
8133 XPutPixel (oimg, x, y, pixel);
8136 xfree (colors);
8137 x_clear_image_1 (f, img, 1, 0, 1);
8139 x_put_x_image (f, oimg, pixmap, img->width, img->height);
8140 x_destroy_x_image (oimg);
8141 img->pixmap = pixmap;
8142 img->colors = colors_in_color_table (&img->ncolors);
8143 free_color_table ();
8147 /* On frame F, perform edge-detection on image IMG.
8149 MATRIX is a nine-element array specifying the transformation
8150 matrix. See emboss_matrix for an example.
8152 COLOR_ADJUST is a color adjustment added to each pixel of the
8153 outgoing image. */
8155 static void
8156 x_detect_edges (f, img, matrix, color_adjust)
8157 struct frame *f;
8158 struct image *img;
8159 int matrix[9], color_adjust;
8161 XColor *colors = x_to_xcolors (f, img, 1);
8162 XColor *new, *p;
8163 int x, y, i, sum;
8165 for (i = sum = 0; i < 9; ++i)
8166 sum += abs (matrix[i]);
8168 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8170 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
8172 for (y = 0; y < img->height; ++y)
8174 p = COLOR (new, 0, y);
8175 p->red = p->green = p->blue = 0xffff/2;
8176 p = COLOR (new, img->width - 1, y);
8177 p->red = p->green = p->blue = 0xffff/2;
8180 for (x = 1; x < img->width - 1; ++x)
8182 p = COLOR (new, x, 0);
8183 p->red = p->green = p->blue = 0xffff/2;
8184 p = COLOR (new, x, img->height - 1);
8185 p->red = p->green = p->blue = 0xffff/2;
8188 for (y = 1; y < img->height - 1; ++y)
8190 p = COLOR (new, 1, y);
8192 for (x = 1; x < img->width - 1; ++x, ++p)
8194 int r, g, b, y1, x1;
8196 r = g = b = i = 0;
8197 for (y1 = y - 1; y1 < y + 2; ++y1)
8198 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
8199 if (matrix[i])
8201 XColor *t = COLOR (colors, x1, y1);
8202 r += matrix[i] * t->red;
8203 g += matrix[i] * t->green;
8204 b += matrix[i] * t->blue;
8207 r = (r / sum + color_adjust) & 0xffff;
8208 g = (g / sum + color_adjust) & 0xffff;
8209 b = (b / sum + color_adjust) & 0xffff;
8210 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
8214 xfree (colors);
8215 x_from_xcolors (f, img, new);
8217 #undef COLOR
8221 /* Perform the pre-defined `emboss' edge-detection on image IMG
8222 on frame F. */
8224 static void
8225 x_emboss (f, img)
8226 struct frame *f;
8227 struct image *img;
8229 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
8233 /* Perform the pre-defined `laplace' edge-detection on image IMG
8234 on frame F. */
8236 static void
8237 x_laplace (f, img)
8238 struct frame *f;
8239 struct image *img;
8241 x_detect_edges (f, img, laplace_matrix, 45000);
8245 /* Perform edge-detection on image IMG on frame F, with specified
8246 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8248 MATRIX must be either
8250 - a list of at least 9 numbers in row-major form
8251 - a vector of at least 9 numbers
8253 COLOR_ADJUST nil means use a default; otherwise it must be a
8254 number. */
8256 static void
8257 x_edge_detection (f, img, matrix, color_adjust)
8258 struct frame *f;
8259 struct image *img;
8260 Lisp_Object matrix, color_adjust;
8262 int i = 0;
8263 int trans[9];
8265 if (CONSP (matrix))
8267 for (i = 0;
8268 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
8269 ++i, matrix = XCDR (matrix))
8270 trans[i] = XFLOATINT (XCAR (matrix));
8272 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
8274 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
8275 trans[i] = XFLOATINT (AREF (matrix, i));
8278 if (NILP (color_adjust))
8279 color_adjust = make_number (0xffff / 2);
8281 if (i == 9 && NUMBERP (color_adjust))
8282 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
8286 /* Transform image IMG on frame F so that it looks disabled. */
8288 static void
8289 x_disable_image (f, img)
8290 struct frame *f;
8291 struct image *img;
8293 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8295 if (dpyinfo->n_planes >= 2)
8297 /* Color (or grayscale). Convert to gray, and equalize. Just
8298 drawing such images with a stipple can look very odd, so
8299 we're using this method instead. */
8300 XColor *colors = x_to_xcolors (f, img, 1);
8301 XColor *p, *end;
8302 const int h = 15000;
8303 const int l = 30000;
8305 for (p = colors, end = colors + img->width * img->height;
8306 p < end;
8307 ++p)
8309 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
8310 int i2 = (0xffff - h - l) * i / 0xffff + l;
8311 p->red = p->green = p->blue = i2;
8314 x_from_xcolors (f, img, colors);
8317 /* Draw a cross over the disabled image, if we must or if we
8318 should. */
8319 if (dpyinfo->n_planes < 2 || cross_disabled_images)
8321 Display *dpy = FRAME_X_DISPLAY (f);
8322 GC gc;
8324 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
8325 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
8326 XDrawLine (dpy, img->pixmap, gc, 0, 0,
8327 img->width - 1, img->height - 1);
8328 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
8329 img->width - 1, 0);
8330 XFreeGC (dpy, gc);
8332 if (img->mask)
8334 gc = XCreateGC (dpy, img->mask, 0, NULL);
8335 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8336 XDrawLine (dpy, img->mask, gc, 0, 0,
8337 img->width - 1, img->height - 1);
8338 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8339 img->width - 1, 0);
8340 XFreeGC (dpy, gc);
8346 /* Build a mask for image IMG which is used on frame F. FILE is the
8347 name of an image file, for error messages. HOW determines how to
8348 determine the background color of IMG. If it is a list '(R G B)',
8349 with R, G, and B being integers >= 0, take that as the color of the
8350 background. Otherwise, determine the background color of IMG
8351 heuristically. Value is non-zero if successful. */
8353 static int
8354 x_build_heuristic_mask (f, img, how)
8355 struct frame *f;
8356 struct image *img;
8357 Lisp_Object how;
8359 Display *dpy = FRAME_X_DISPLAY (f);
8360 XImage *ximg, *mask_img;
8361 int x, y, rc, use_img_background;
8362 unsigned long bg = 0;
8364 if (img->mask)
8366 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8367 img->mask = None;
8368 img->background_transparent_valid = 0;
8371 /* Create an image and pixmap serving as mask. */
8372 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8373 &mask_img, &img->mask);
8374 if (!rc)
8375 return 0;
8377 /* Get the X image of IMG->pixmap. */
8378 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8379 ~0, ZPixmap);
8381 /* Determine the background color of ximg. If HOW is `(R G B)'
8382 take that as color. Otherwise, use the image's background color. */
8383 use_img_background = 1;
8385 if (CONSP (how))
8387 int rgb[3], i;
8389 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
8391 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8392 how = XCDR (how);
8395 if (i == 3 && NILP (how))
8397 char color_name[30];
8398 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8399 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
8400 use_img_background = 0;
8404 if (use_img_background)
8405 bg = four_corners_best (ximg, img->width, img->height);
8407 /* Set all bits in mask_img to 1 whose color in ximg is different
8408 from the background color bg. */
8409 for (y = 0; y < img->height; ++y)
8410 for (x = 0; x < img->width; ++x)
8411 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8413 /* Fill in the background_transparent field while we have the mask handy. */
8414 image_background_transparent (img, f, mask_img);
8416 /* Put mask_img into img->mask. */
8417 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8418 x_destroy_x_image (mask_img);
8419 XDestroyImage (ximg);
8421 return 1;
8426 /***********************************************************************
8427 PBM (mono, gray, color)
8428 ***********************************************************************/
8430 static int pbm_image_p P_ ((Lisp_Object object));
8431 static int pbm_load P_ ((struct frame *f, struct image *img));
8432 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8434 /* The symbol `pbm' identifying images of this type. */
8436 Lisp_Object Qpbm;
8438 /* Indices of image specification fields in gs_format, below. */
8440 enum pbm_keyword_index
8442 PBM_TYPE,
8443 PBM_FILE,
8444 PBM_DATA,
8445 PBM_ASCENT,
8446 PBM_MARGIN,
8447 PBM_RELIEF,
8448 PBM_ALGORITHM,
8449 PBM_HEURISTIC_MASK,
8450 PBM_MASK,
8451 PBM_FOREGROUND,
8452 PBM_BACKGROUND,
8453 PBM_LAST
8456 /* Vector of image_keyword structures describing the format
8457 of valid user-defined image specifications. */
8459 static struct image_keyword pbm_format[PBM_LAST] =
8461 {":type", IMAGE_SYMBOL_VALUE, 1},
8462 {":file", IMAGE_STRING_VALUE, 0},
8463 {":data", IMAGE_STRING_VALUE, 0},
8464 {":ascent", IMAGE_ASCENT_VALUE, 0},
8465 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8466 {":relief", IMAGE_INTEGER_VALUE, 0},
8467 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8468 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8469 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8470 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8471 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8474 /* Structure describing the image type `pbm'. */
8476 static struct image_type pbm_type =
8478 &Qpbm,
8479 pbm_image_p,
8480 pbm_load,
8481 x_clear_image,
8482 NULL
8486 /* Return non-zero if OBJECT is a valid PBM image specification. */
8488 static int
8489 pbm_image_p (object)
8490 Lisp_Object object;
8492 struct image_keyword fmt[PBM_LAST];
8494 bcopy (pbm_format, fmt, sizeof fmt);
8496 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8497 return 0;
8499 /* Must specify either :data or :file. */
8500 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8504 /* Scan a decimal number from *S and return it. Advance *S while
8505 reading the number. END is the end of the string. Value is -1 at
8506 end of input. */
8508 static int
8509 pbm_scan_number (s, end)
8510 unsigned char **s, *end;
8512 int c = 0, val = -1;
8514 while (*s < end)
8516 /* Skip white-space. */
8517 while (*s < end && (c = *(*s)++, isspace (c)))
8520 if (c == '#')
8522 /* Skip comment to end of line. */
8523 while (*s < end && (c = *(*s)++, c != '\n'))
8526 else if (isdigit (c))
8528 /* Read decimal number. */
8529 val = c - '0';
8530 while (*s < end && (c = *(*s)++, isdigit (c)))
8531 val = 10 * val + c - '0';
8532 break;
8534 else
8535 break;
8538 return val;
8542 /* Load PBM image IMG for use on frame F. */
8544 static int
8545 pbm_load (f, img)
8546 struct frame *f;
8547 struct image *img;
8549 int raw_p, x, y;
8550 int width, height, max_color_idx = 0;
8551 XImage *ximg;
8552 Lisp_Object file, specified_file;
8553 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8554 struct gcpro gcpro1;
8555 unsigned char *contents = NULL;
8556 unsigned char *end, *p;
8557 int size;
8559 specified_file = image_spec_value (img->spec, QCfile, NULL);
8560 file = Qnil;
8561 GCPRO1 (file);
8563 if (STRINGP (specified_file))
8565 file = x_find_image_file (specified_file);
8566 if (!STRINGP (file))
8568 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8569 UNGCPRO;
8570 return 0;
8573 contents = slurp_file (XSTRING (file)->data, &size);
8574 if (contents == NULL)
8576 image_error ("Error reading `%s'", file, Qnil);
8577 UNGCPRO;
8578 return 0;
8581 p = contents;
8582 end = contents + size;
8584 else
8586 Lisp_Object data;
8587 data = image_spec_value (img->spec, QCdata, NULL);
8588 p = XSTRING (data)->data;
8589 end = p + STRING_BYTES (XSTRING (data));
8592 /* Check magic number. */
8593 if (end - p < 2 || *p++ != 'P')
8595 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8596 error:
8597 xfree (contents);
8598 UNGCPRO;
8599 return 0;
8602 switch (*p++)
8604 case '1':
8605 raw_p = 0, type = PBM_MONO;
8606 break;
8608 case '2':
8609 raw_p = 0, type = PBM_GRAY;
8610 break;
8612 case '3':
8613 raw_p = 0, type = PBM_COLOR;
8614 break;
8616 case '4':
8617 raw_p = 1, type = PBM_MONO;
8618 break;
8620 case '5':
8621 raw_p = 1, type = PBM_GRAY;
8622 break;
8624 case '6':
8625 raw_p = 1, type = PBM_COLOR;
8626 break;
8628 default:
8629 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8630 goto error;
8633 /* Read width, height, maximum color-component. Characters
8634 starting with `#' up to the end of a line are ignored. */
8635 width = pbm_scan_number (&p, end);
8636 height = pbm_scan_number (&p, end);
8638 if (type != PBM_MONO)
8640 max_color_idx = pbm_scan_number (&p, end);
8641 if (raw_p && max_color_idx > 255)
8642 max_color_idx = 255;
8645 if (width < 0
8646 || height < 0
8647 || (type != PBM_MONO && max_color_idx < 0))
8648 goto error;
8650 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8651 &ximg, &img->pixmap))
8652 goto error;
8654 /* Initialize the color hash table. */
8655 init_color_table ();
8657 if (type == PBM_MONO)
8659 int c = 0, g;
8660 struct image_keyword fmt[PBM_LAST];
8661 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8662 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8664 /* Parse the image specification. */
8665 bcopy (pbm_format, fmt, sizeof fmt);
8666 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8668 /* Get foreground and background colors, maybe allocate colors. */
8669 if (fmt[PBM_FOREGROUND].count
8670 && STRINGP (fmt[PBM_FOREGROUND].value))
8671 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8672 if (fmt[PBM_BACKGROUND].count
8673 && STRINGP (fmt[PBM_BACKGROUND].value))
8675 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8676 img->background = bg;
8677 img->background_valid = 1;
8680 for (y = 0; y < height; ++y)
8681 for (x = 0; x < width; ++x)
8683 if (raw_p)
8685 if ((x & 7) == 0)
8686 c = *p++;
8687 g = c & 0x80;
8688 c <<= 1;
8690 else
8691 g = pbm_scan_number (&p, end);
8693 XPutPixel (ximg, x, y, g ? fg : bg);
8696 else
8698 for (y = 0; y < height; ++y)
8699 for (x = 0; x < width; ++x)
8701 int r, g, b;
8703 if (type == PBM_GRAY)
8704 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8705 else if (raw_p)
8707 r = *p++;
8708 g = *p++;
8709 b = *p++;
8711 else
8713 r = pbm_scan_number (&p, end);
8714 g = pbm_scan_number (&p, end);
8715 b = pbm_scan_number (&p, end);
8718 if (r < 0 || g < 0 || b < 0)
8720 xfree (ximg->data);
8721 ximg->data = NULL;
8722 XDestroyImage (ximg);
8723 image_error ("Invalid pixel value in image `%s'",
8724 img->spec, Qnil);
8725 goto error;
8728 /* RGB values are now in the range 0..max_color_idx.
8729 Scale this to the range 0..0xffff supported by X. */
8730 r = (double) r * 65535 / max_color_idx;
8731 g = (double) g * 65535 / max_color_idx;
8732 b = (double) b * 65535 / max_color_idx;
8733 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8737 /* Store in IMG->colors the colors allocated for the image, and
8738 free the color table. */
8739 img->colors = colors_in_color_table (&img->ncolors);
8740 free_color_table ();
8742 /* Maybe fill in the background field while we have ximg handy. */
8743 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8744 IMAGE_BACKGROUND (img, f, ximg);
8746 /* Put the image into a pixmap. */
8747 x_put_x_image (f, ximg, img->pixmap, width, height);
8748 x_destroy_x_image (ximg);
8750 img->width = width;
8751 img->height = height;
8753 UNGCPRO;
8754 xfree (contents);
8755 return 1;
8760 /***********************************************************************
8762 ***********************************************************************/
8764 #if HAVE_PNG
8766 #include <png.h>
8768 /* Function prototypes. */
8770 static int png_image_p P_ ((Lisp_Object object));
8771 static int png_load P_ ((struct frame *f, struct image *img));
8773 /* The symbol `png' identifying images of this type. */
8775 Lisp_Object Qpng;
8777 /* Indices of image specification fields in png_format, below. */
8779 enum png_keyword_index
8781 PNG_TYPE,
8782 PNG_DATA,
8783 PNG_FILE,
8784 PNG_ASCENT,
8785 PNG_MARGIN,
8786 PNG_RELIEF,
8787 PNG_ALGORITHM,
8788 PNG_HEURISTIC_MASK,
8789 PNG_MASK,
8790 PNG_BACKGROUND,
8791 PNG_LAST
8794 /* Vector of image_keyword structures describing the format
8795 of valid user-defined image specifications. */
8797 static struct image_keyword png_format[PNG_LAST] =
8799 {":type", IMAGE_SYMBOL_VALUE, 1},
8800 {":data", IMAGE_STRING_VALUE, 0},
8801 {":file", IMAGE_STRING_VALUE, 0},
8802 {":ascent", IMAGE_ASCENT_VALUE, 0},
8803 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8804 {":relief", IMAGE_INTEGER_VALUE, 0},
8805 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8806 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8807 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8808 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8811 /* Structure describing the image type `png'. */
8813 static struct image_type png_type =
8815 &Qpng,
8816 png_image_p,
8817 png_load,
8818 x_clear_image,
8819 NULL
8823 /* Return non-zero if OBJECT is a valid PNG image specification. */
8825 static int
8826 png_image_p (object)
8827 Lisp_Object object;
8829 struct image_keyword fmt[PNG_LAST];
8830 bcopy (png_format, fmt, sizeof fmt);
8832 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8833 return 0;
8835 /* Must specify either the :data or :file keyword. */
8836 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8840 /* Error and warning handlers installed when the PNG library
8841 is initialized. */
8843 static void
8844 my_png_error (png_ptr, msg)
8845 png_struct *png_ptr;
8846 char *msg;
8848 xassert (png_ptr != NULL);
8849 image_error ("PNG error: %s", build_string (msg), Qnil);
8850 longjmp (png_ptr->jmpbuf, 1);
8854 static void
8855 my_png_warning (png_ptr, msg)
8856 png_struct *png_ptr;
8857 char *msg;
8859 xassert (png_ptr != NULL);
8860 image_error ("PNG warning: %s", build_string (msg), Qnil);
8863 /* Memory source for PNG decoding. */
8865 struct png_memory_storage
8867 unsigned char *bytes; /* The data */
8868 size_t len; /* How big is it? */
8869 int index; /* Where are we? */
8873 /* Function set as reader function when reading PNG image from memory.
8874 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8875 bytes from the input to DATA. */
8877 static void
8878 png_read_from_memory (png_ptr, data, length)
8879 png_structp png_ptr;
8880 png_bytep data;
8881 png_size_t length;
8883 struct png_memory_storage *tbr
8884 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8886 if (length > tbr->len - tbr->index)
8887 png_error (png_ptr, "Read error");
8889 bcopy (tbr->bytes + tbr->index, data, length);
8890 tbr->index = tbr->index + length;
8893 /* Load PNG image IMG for use on frame F. Value is non-zero if
8894 successful. */
8896 static int
8897 png_load (f, img)
8898 struct frame *f;
8899 struct image *img;
8901 Lisp_Object file, specified_file;
8902 Lisp_Object specified_data;
8903 int x, y, i;
8904 XImage *ximg, *mask_img = NULL;
8905 struct gcpro gcpro1;
8906 png_struct *png_ptr = NULL;
8907 png_info *info_ptr = NULL, *end_info = NULL;
8908 FILE *volatile fp = NULL;
8909 png_byte sig[8];
8910 png_byte * volatile pixels = NULL;
8911 png_byte ** volatile rows = NULL;
8912 png_uint_32 width, height;
8913 int bit_depth, color_type, interlace_type;
8914 png_byte channels;
8915 png_uint_32 row_bytes;
8916 int transparent_p;
8917 double screen_gamma, image_gamma;
8918 int intent;
8919 struct png_memory_storage tbr; /* Data to be read */
8921 /* Find out what file to load. */
8922 specified_file = image_spec_value (img->spec, QCfile, NULL);
8923 specified_data = image_spec_value (img->spec, QCdata, NULL);
8924 file = Qnil;
8925 GCPRO1 (file);
8927 if (NILP (specified_data))
8929 file = x_find_image_file (specified_file);
8930 if (!STRINGP (file))
8932 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8933 UNGCPRO;
8934 return 0;
8937 /* Open the image file. */
8938 fp = fopen (XSTRING (file)->data, "rb");
8939 if (!fp)
8941 image_error ("Cannot open image file `%s'", file, Qnil);
8942 UNGCPRO;
8943 fclose (fp);
8944 return 0;
8947 /* Check PNG signature. */
8948 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8949 || !png_check_sig (sig, sizeof sig))
8951 image_error ("Not a PNG file: `%s'", file, Qnil);
8952 UNGCPRO;
8953 fclose (fp);
8954 return 0;
8957 else
8959 /* Read from memory. */
8960 tbr.bytes = XSTRING (specified_data)->data;
8961 tbr.len = STRING_BYTES (XSTRING (specified_data));
8962 tbr.index = 0;
8964 /* Check PNG signature. */
8965 if (tbr.len < sizeof sig
8966 || !png_check_sig (tbr.bytes, sizeof sig))
8968 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8969 UNGCPRO;
8970 return 0;
8973 /* Need to skip past the signature. */
8974 tbr.bytes += sizeof (sig);
8977 /* Initialize read and info structs for PNG lib. */
8978 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8979 my_png_error, my_png_warning);
8980 if (!png_ptr)
8982 if (fp) fclose (fp);
8983 UNGCPRO;
8984 return 0;
8987 info_ptr = png_create_info_struct (png_ptr);
8988 if (!info_ptr)
8990 png_destroy_read_struct (&png_ptr, NULL, NULL);
8991 if (fp) fclose (fp);
8992 UNGCPRO;
8993 return 0;
8996 end_info = png_create_info_struct (png_ptr);
8997 if (!end_info)
8999 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
9000 if (fp) fclose (fp);
9001 UNGCPRO;
9002 return 0;
9005 /* Set error jump-back. We come back here when the PNG library
9006 detects an error. */
9007 if (setjmp (png_ptr->jmpbuf))
9009 error:
9010 if (png_ptr)
9011 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9012 xfree (pixels);
9013 xfree (rows);
9014 if (fp) fclose (fp);
9015 UNGCPRO;
9016 return 0;
9019 /* Read image info. */
9020 if (!NILP (specified_data))
9021 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
9022 else
9023 png_init_io (png_ptr, fp);
9025 png_set_sig_bytes (png_ptr, sizeof sig);
9026 png_read_info (png_ptr, info_ptr);
9027 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
9028 &interlace_type, NULL, NULL);
9030 /* If image contains simply transparency data, we prefer to
9031 construct a clipping mask. */
9032 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
9033 transparent_p = 1;
9034 else
9035 transparent_p = 0;
9037 /* This function is easier to write if we only have to handle
9038 one data format: RGB or RGBA with 8 bits per channel. Let's
9039 transform other formats into that format. */
9041 /* Strip more than 8 bits per channel. */
9042 if (bit_depth == 16)
9043 png_set_strip_16 (png_ptr);
9045 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
9046 if available. */
9047 png_set_expand (png_ptr);
9049 /* Convert grayscale images to RGB. */
9050 if (color_type == PNG_COLOR_TYPE_GRAY
9051 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
9052 png_set_gray_to_rgb (png_ptr);
9054 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
9056 /* Tell the PNG lib to handle gamma correction for us. */
9058 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9059 if (png_get_sRGB (png_ptr, info_ptr, &intent))
9060 /* The libpng documentation says this is right in this case. */
9061 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9062 else
9063 #endif
9064 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
9065 /* Image contains gamma information. */
9066 png_set_gamma (png_ptr, screen_gamma, image_gamma);
9067 else
9068 /* Use the standard default for the image gamma. */
9069 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9071 /* Handle alpha channel by combining the image with a background
9072 color. Do this only if a real alpha channel is supplied. For
9073 simple transparency, we prefer a clipping mask. */
9074 if (!transparent_p)
9076 png_color_16 *image_bg;
9077 Lisp_Object specified_bg
9078 = image_spec_value (img->spec, QCbackground, NULL);
9080 if (STRINGP (specified_bg))
9081 /* The user specified `:background', use that. */
9083 XColor color;
9084 if (x_defined_color (f, XSTRING (specified_bg)->data, &color, 0))
9086 png_color_16 user_bg;
9088 bzero (&user_bg, sizeof user_bg);
9089 user_bg.red = color.red;
9090 user_bg.green = color.green;
9091 user_bg.blue = color.blue;
9093 png_set_background (png_ptr, &user_bg,
9094 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9097 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
9098 /* Image contains a background color with which to
9099 combine the image. */
9100 png_set_background (png_ptr, image_bg,
9101 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
9102 else
9104 /* Image does not contain a background color with which
9105 to combine the image data via an alpha channel. Use
9106 the frame's background instead. */
9107 XColor color;
9108 Colormap cmap;
9109 png_color_16 frame_background;
9111 cmap = FRAME_X_COLORMAP (f);
9112 color.pixel = FRAME_BACKGROUND_PIXEL (f);
9113 x_query_color (f, &color);
9115 bzero (&frame_background, sizeof frame_background);
9116 frame_background.red = color.red;
9117 frame_background.green = color.green;
9118 frame_background.blue = color.blue;
9120 png_set_background (png_ptr, &frame_background,
9121 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9125 /* Update info structure. */
9126 png_read_update_info (png_ptr, info_ptr);
9128 /* Get number of channels. Valid values are 1 for grayscale images
9129 and images with a palette, 2 for grayscale images with transparency
9130 information (alpha channel), 3 for RGB images, and 4 for RGB
9131 images with alpha channel, i.e. RGBA. If conversions above were
9132 sufficient we should only have 3 or 4 channels here. */
9133 channels = png_get_channels (png_ptr, info_ptr);
9134 xassert (channels == 3 || channels == 4);
9136 /* Number of bytes needed for one row of the image. */
9137 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
9139 /* Allocate memory for the image. */
9140 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
9141 rows = (png_byte **) xmalloc (height * sizeof *rows);
9142 for (i = 0; i < height; ++i)
9143 rows[i] = pixels + i * row_bytes;
9145 /* Read the entire image. */
9146 png_read_image (png_ptr, rows);
9147 png_read_end (png_ptr, info_ptr);
9148 if (fp)
9150 fclose (fp);
9151 fp = NULL;
9154 /* Create the X image and pixmap. */
9155 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
9156 &img->pixmap))
9157 goto error;
9159 /* Create an image and pixmap serving as mask if the PNG image
9160 contains an alpha channel. */
9161 if (channels == 4
9162 && !transparent_p
9163 && !x_create_x_image_and_pixmap (f, width, height, 1,
9164 &mask_img, &img->mask))
9166 x_destroy_x_image (ximg);
9167 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
9168 img->pixmap = None;
9169 goto error;
9172 /* Fill the X image and mask from PNG data. */
9173 init_color_table ();
9175 for (y = 0; y < height; ++y)
9177 png_byte *p = rows[y];
9179 for (x = 0; x < width; ++x)
9181 unsigned r, g, b;
9183 r = *p++ << 8;
9184 g = *p++ << 8;
9185 b = *p++ << 8;
9186 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
9188 /* An alpha channel, aka mask channel, associates variable
9189 transparency with an image. Where other image formats
9190 support binary transparency---fully transparent or fully
9191 opaque---PNG allows up to 254 levels of partial transparency.
9192 The PNG library implements partial transparency by combining
9193 the image with a specified background color.
9195 I'm not sure how to handle this here nicely: because the
9196 background on which the image is displayed may change, for
9197 real alpha channel support, it would be necessary to create
9198 a new image for each possible background.
9200 What I'm doing now is that a mask is created if we have
9201 boolean transparency information. Otherwise I'm using
9202 the frame's background color to combine the image with. */
9204 if (channels == 4)
9206 if (mask_img)
9207 XPutPixel (mask_img, x, y, *p > 0);
9208 ++p;
9213 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9214 /* Set IMG's background color from the PNG image, unless the user
9215 overrode it. */
9217 png_color_16 *bg;
9218 if (png_get_bKGD (png_ptr, info_ptr, &bg))
9220 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
9221 img->background_valid = 1;
9225 /* Remember colors allocated for this image. */
9226 img->colors = colors_in_color_table (&img->ncolors);
9227 free_color_table ();
9229 /* Clean up. */
9230 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9231 xfree (rows);
9232 xfree (pixels);
9234 img->width = width;
9235 img->height = height;
9237 /* Maybe fill in the background field while we have ximg handy. */
9238 IMAGE_BACKGROUND (img, f, ximg);
9240 /* Put the image into the pixmap, then free the X image and its buffer. */
9241 x_put_x_image (f, ximg, img->pixmap, width, height);
9242 x_destroy_x_image (ximg);
9244 /* Same for the mask. */
9245 if (mask_img)
9247 /* Fill in the background_transparent field while we have the mask
9248 handy. */
9249 image_background_transparent (img, f, mask_img);
9251 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
9252 x_destroy_x_image (mask_img);
9255 UNGCPRO;
9256 return 1;
9259 #endif /* HAVE_PNG != 0 */
9263 /***********************************************************************
9264 JPEG
9265 ***********************************************************************/
9267 #if HAVE_JPEG
9269 /* Work around a warning about HAVE_STDLIB_H being redefined in
9270 jconfig.h. */
9271 #ifdef HAVE_STDLIB_H
9272 #define HAVE_STDLIB_H_1
9273 #undef HAVE_STDLIB_H
9274 #endif /* HAVE_STLIB_H */
9276 #include <jpeglib.h>
9277 #include <jerror.h>
9278 #include <setjmp.h>
9280 #ifdef HAVE_STLIB_H_1
9281 #define HAVE_STDLIB_H 1
9282 #endif
9284 static int jpeg_image_p P_ ((Lisp_Object object));
9285 static int jpeg_load P_ ((struct frame *f, struct image *img));
9287 /* The symbol `jpeg' identifying images of this type. */
9289 Lisp_Object Qjpeg;
9291 /* Indices of image specification fields in gs_format, below. */
9293 enum jpeg_keyword_index
9295 JPEG_TYPE,
9296 JPEG_DATA,
9297 JPEG_FILE,
9298 JPEG_ASCENT,
9299 JPEG_MARGIN,
9300 JPEG_RELIEF,
9301 JPEG_ALGORITHM,
9302 JPEG_HEURISTIC_MASK,
9303 JPEG_MASK,
9304 JPEG_BACKGROUND,
9305 JPEG_LAST
9308 /* Vector of image_keyword structures describing the format
9309 of valid user-defined image specifications. */
9311 static struct image_keyword jpeg_format[JPEG_LAST] =
9313 {":type", IMAGE_SYMBOL_VALUE, 1},
9314 {":data", IMAGE_STRING_VALUE, 0},
9315 {":file", IMAGE_STRING_VALUE, 0},
9316 {":ascent", IMAGE_ASCENT_VALUE, 0},
9317 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9318 {":relief", IMAGE_INTEGER_VALUE, 0},
9319 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9320 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9321 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9322 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9325 /* Structure describing the image type `jpeg'. */
9327 static struct image_type jpeg_type =
9329 &Qjpeg,
9330 jpeg_image_p,
9331 jpeg_load,
9332 x_clear_image,
9333 NULL
9337 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9339 static int
9340 jpeg_image_p (object)
9341 Lisp_Object object;
9343 struct image_keyword fmt[JPEG_LAST];
9345 bcopy (jpeg_format, fmt, sizeof fmt);
9347 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
9348 return 0;
9350 /* Must specify either the :data or :file keyword. */
9351 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9355 struct my_jpeg_error_mgr
9357 struct jpeg_error_mgr pub;
9358 jmp_buf setjmp_buffer;
9362 static void
9363 my_error_exit (cinfo)
9364 j_common_ptr cinfo;
9366 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9367 longjmp (mgr->setjmp_buffer, 1);
9371 /* Init source method for JPEG data source manager. Called by
9372 jpeg_read_header() before any data is actually read. See
9373 libjpeg.doc from the JPEG lib distribution. */
9375 static void
9376 our_init_source (cinfo)
9377 j_decompress_ptr cinfo;
9382 /* Fill input buffer method for JPEG data source manager. Called
9383 whenever more data is needed. We read the whole image in one step,
9384 so this only adds a fake end of input marker at the end. */
9386 static boolean
9387 our_fill_input_buffer (cinfo)
9388 j_decompress_ptr cinfo;
9390 /* Insert a fake EOI marker. */
9391 struct jpeg_source_mgr *src = cinfo->src;
9392 static JOCTET buffer[2];
9394 buffer[0] = (JOCTET) 0xFF;
9395 buffer[1] = (JOCTET) JPEG_EOI;
9397 src->next_input_byte = buffer;
9398 src->bytes_in_buffer = 2;
9399 return TRUE;
9403 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9404 is the JPEG data source manager. */
9406 static void
9407 our_skip_input_data (cinfo, num_bytes)
9408 j_decompress_ptr cinfo;
9409 long num_bytes;
9411 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9413 if (src)
9415 if (num_bytes > src->bytes_in_buffer)
9416 ERREXIT (cinfo, JERR_INPUT_EOF);
9418 src->bytes_in_buffer -= num_bytes;
9419 src->next_input_byte += num_bytes;
9424 /* Method to terminate data source. Called by
9425 jpeg_finish_decompress() after all data has been processed. */
9427 static void
9428 our_term_source (cinfo)
9429 j_decompress_ptr cinfo;
9434 /* Set up the JPEG lib for reading an image from DATA which contains
9435 LEN bytes. CINFO is the decompression info structure created for
9436 reading the image. */
9438 static void
9439 jpeg_memory_src (cinfo, data, len)
9440 j_decompress_ptr cinfo;
9441 JOCTET *data;
9442 unsigned int len;
9444 struct jpeg_source_mgr *src;
9446 if (cinfo->src == NULL)
9448 /* First time for this JPEG object? */
9449 cinfo->src = (struct jpeg_source_mgr *)
9450 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9451 sizeof (struct jpeg_source_mgr));
9452 src = (struct jpeg_source_mgr *) cinfo->src;
9453 src->next_input_byte = data;
9456 src = (struct jpeg_source_mgr *) cinfo->src;
9457 src->init_source = our_init_source;
9458 src->fill_input_buffer = our_fill_input_buffer;
9459 src->skip_input_data = our_skip_input_data;
9460 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9461 src->term_source = our_term_source;
9462 src->bytes_in_buffer = len;
9463 src->next_input_byte = data;
9467 /* Load image IMG for use on frame F. Patterned after example.c
9468 from the JPEG lib. */
9470 static int
9471 jpeg_load (f, img)
9472 struct frame *f;
9473 struct image *img;
9475 struct jpeg_decompress_struct cinfo;
9476 struct my_jpeg_error_mgr mgr;
9477 Lisp_Object file, specified_file;
9478 Lisp_Object specified_data;
9479 FILE * volatile fp = NULL;
9480 JSAMPARRAY buffer;
9481 int row_stride, x, y;
9482 XImage *ximg = NULL;
9483 int rc;
9484 unsigned long *colors;
9485 int width, height;
9486 struct gcpro gcpro1;
9488 /* Open the JPEG file. */
9489 specified_file = image_spec_value (img->spec, QCfile, NULL);
9490 specified_data = image_spec_value (img->spec, QCdata, NULL);
9491 file = Qnil;
9492 GCPRO1 (file);
9494 if (NILP (specified_data))
9496 file = x_find_image_file (specified_file);
9497 if (!STRINGP (file))
9499 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9500 UNGCPRO;
9501 return 0;
9504 fp = fopen (XSTRING (file)->data, "r");
9505 if (fp == NULL)
9507 image_error ("Cannot open `%s'", file, Qnil);
9508 UNGCPRO;
9509 return 0;
9513 /* Customize libjpeg's error handling to call my_error_exit when an
9514 error is detected. This function will perform a longjmp. */
9515 cinfo.err = jpeg_std_error (&mgr.pub);
9516 mgr.pub.error_exit = my_error_exit;
9518 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9520 if (rc == 1)
9522 /* Called from my_error_exit. Display a JPEG error. */
9523 char buffer[JMSG_LENGTH_MAX];
9524 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9525 image_error ("Error reading JPEG image `%s': %s", img->spec,
9526 build_string (buffer));
9529 /* Close the input file and destroy the JPEG object. */
9530 if (fp)
9531 fclose ((FILE *) fp);
9532 jpeg_destroy_decompress (&cinfo);
9534 /* If we already have an XImage, free that. */
9535 x_destroy_x_image (ximg);
9537 /* Free pixmap and colors. */
9538 x_clear_image (f, img);
9540 UNGCPRO;
9541 return 0;
9544 /* Create the JPEG decompression object. Let it read from fp.
9545 Read the JPEG image header. */
9546 jpeg_create_decompress (&cinfo);
9548 if (NILP (specified_data))
9549 jpeg_stdio_src (&cinfo, (FILE *) fp);
9550 else
9551 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
9552 STRING_BYTES (XSTRING (specified_data)));
9554 jpeg_read_header (&cinfo, TRUE);
9556 /* Customize decompression so that color quantization will be used.
9557 Start decompression. */
9558 cinfo.quantize_colors = TRUE;
9559 jpeg_start_decompress (&cinfo);
9560 width = img->width = cinfo.output_width;
9561 height = img->height = cinfo.output_height;
9563 /* Create X image and pixmap. */
9564 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9565 longjmp (mgr.setjmp_buffer, 2);
9567 /* Allocate colors. When color quantization is used,
9568 cinfo.actual_number_of_colors has been set with the number of
9569 colors generated, and cinfo.colormap is a two-dimensional array
9570 of color indices in the range 0..cinfo.actual_number_of_colors.
9571 No more than 255 colors will be generated. */
9573 int i, ir, ig, ib;
9575 if (cinfo.out_color_components > 2)
9576 ir = 0, ig = 1, ib = 2;
9577 else if (cinfo.out_color_components > 1)
9578 ir = 0, ig = 1, ib = 0;
9579 else
9580 ir = 0, ig = 0, ib = 0;
9582 /* Use the color table mechanism because it handles colors that
9583 cannot be allocated nicely. Such colors will be replaced with
9584 a default color, and we don't have to care about which colors
9585 can be freed safely, and which can't. */
9586 init_color_table ();
9587 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9588 * sizeof *colors);
9590 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9592 /* Multiply RGB values with 255 because X expects RGB values
9593 in the range 0..0xffff. */
9594 int r = cinfo.colormap[ir][i] << 8;
9595 int g = cinfo.colormap[ig][i] << 8;
9596 int b = cinfo.colormap[ib][i] << 8;
9597 colors[i] = lookup_rgb_color (f, r, g, b);
9600 /* Remember those colors actually allocated. */
9601 img->colors = colors_in_color_table (&img->ncolors);
9602 free_color_table ();
9605 /* Read pixels. */
9606 row_stride = width * cinfo.output_components;
9607 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9608 row_stride, 1);
9609 for (y = 0; y < height; ++y)
9611 jpeg_read_scanlines (&cinfo, buffer, 1);
9612 for (x = 0; x < cinfo.output_width; ++x)
9613 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9616 /* Clean up. */
9617 jpeg_finish_decompress (&cinfo);
9618 jpeg_destroy_decompress (&cinfo);
9619 if (fp)
9620 fclose ((FILE *) fp);
9622 /* Maybe fill in the background field while we have ximg handy. */
9623 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9624 IMAGE_BACKGROUND (img, f, ximg);
9626 /* Put the image into the pixmap. */
9627 x_put_x_image (f, ximg, img->pixmap, width, height);
9628 x_destroy_x_image (ximg);
9629 UNGCPRO;
9630 return 1;
9633 #endif /* HAVE_JPEG */
9637 /***********************************************************************
9638 TIFF
9639 ***********************************************************************/
9641 #if HAVE_TIFF
9643 #include <tiffio.h>
9645 static int tiff_image_p P_ ((Lisp_Object object));
9646 static int tiff_load P_ ((struct frame *f, struct image *img));
9648 /* The symbol `tiff' identifying images of this type. */
9650 Lisp_Object Qtiff;
9652 /* Indices of image specification fields in tiff_format, below. */
9654 enum tiff_keyword_index
9656 TIFF_TYPE,
9657 TIFF_DATA,
9658 TIFF_FILE,
9659 TIFF_ASCENT,
9660 TIFF_MARGIN,
9661 TIFF_RELIEF,
9662 TIFF_ALGORITHM,
9663 TIFF_HEURISTIC_MASK,
9664 TIFF_MASK,
9665 TIFF_BACKGROUND,
9666 TIFF_LAST
9669 /* Vector of image_keyword structures describing the format
9670 of valid user-defined image specifications. */
9672 static struct image_keyword tiff_format[TIFF_LAST] =
9674 {":type", IMAGE_SYMBOL_VALUE, 1},
9675 {":data", IMAGE_STRING_VALUE, 0},
9676 {":file", IMAGE_STRING_VALUE, 0},
9677 {":ascent", IMAGE_ASCENT_VALUE, 0},
9678 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9679 {":relief", IMAGE_INTEGER_VALUE, 0},
9680 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9681 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9682 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9683 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9686 /* Structure describing the image type `tiff'. */
9688 static struct image_type tiff_type =
9690 &Qtiff,
9691 tiff_image_p,
9692 tiff_load,
9693 x_clear_image,
9694 NULL
9698 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9700 static int
9701 tiff_image_p (object)
9702 Lisp_Object object;
9704 struct image_keyword fmt[TIFF_LAST];
9705 bcopy (tiff_format, fmt, sizeof fmt);
9707 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9708 return 0;
9710 /* Must specify either the :data or :file keyword. */
9711 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9715 /* Reading from a memory buffer for TIFF images Based on the PNG
9716 memory source, but we have to provide a lot of extra functions.
9717 Blah.
9719 We really only need to implement read and seek, but I am not
9720 convinced that the TIFF library is smart enough not to destroy
9721 itself if we only hand it the function pointers we need to
9722 override. */
9724 typedef struct
9726 unsigned char *bytes;
9727 size_t len;
9728 int index;
9730 tiff_memory_source;
9733 static size_t
9734 tiff_read_from_memory (data, buf, size)
9735 thandle_t data;
9736 tdata_t buf;
9737 tsize_t size;
9739 tiff_memory_source *src = (tiff_memory_source *) data;
9741 if (size > src->len - src->index)
9742 return (size_t) -1;
9743 bcopy (src->bytes + src->index, buf, size);
9744 src->index += size;
9745 return size;
9749 static size_t
9750 tiff_write_from_memory (data, buf, size)
9751 thandle_t data;
9752 tdata_t buf;
9753 tsize_t size;
9755 return (size_t) -1;
9759 static toff_t
9760 tiff_seek_in_memory (data, off, whence)
9761 thandle_t data;
9762 toff_t off;
9763 int whence;
9765 tiff_memory_source *src = (tiff_memory_source *) data;
9766 int idx;
9768 switch (whence)
9770 case SEEK_SET: /* Go from beginning of source. */
9771 idx = off;
9772 break;
9774 case SEEK_END: /* Go from end of source. */
9775 idx = src->len + off;
9776 break;
9778 case SEEK_CUR: /* Go from current position. */
9779 idx = src->index + off;
9780 break;
9782 default: /* Invalid `whence'. */
9783 return -1;
9786 if (idx > src->len || idx < 0)
9787 return -1;
9789 src->index = idx;
9790 return src->index;
9794 static int
9795 tiff_close_memory (data)
9796 thandle_t data;
9798 /* NOOP */
9799 return 0;
9803 static int
9804 tiff_mmap_memory (data, pbase, psize)
9805 thandle_t data;
9806 tdata_t *pbase;
9807 toff_t *psize;
9809 /* It is already _IN_ memory. */
9810 return 0;
9814 static void
9815 tiff_unmap_memory (data, base, size)
9816 thandle_t data;
9817 tdata_t base;
9818 toff_t size;
9820 /* We don't need to do this. */
9824 static toff_t
9825 tiff_size_of_memory (data)
9826 thandle_t data;
9828 return ((tiff_memory_source *) data)->len;
9832 static void
9833 tiff_error_handler (title, format, ap)
9834 const char *title, *format;
9835 va_list ap;
9837 char buf[512];
9838 int len;
9840 len = sprintf (buf, "TIFF error: %s ", title);
9841 vsprintf (buf + len, format, ap);
9842 add_to_log (buf, Qnil, Qnil);
9846 static void
9847 tiff_warning_handler (title, format, ap)
9848 const char *title, *format;
9849 va_list ap;
9851 char buf[512];
9852 int len;
9854 len = sprintf (buf, "TIFF warning: %s ", title);
9855 vsprintf (buf + len, format, ap);
9856 add_to_log (buf, Qnil, Qnil);
9860 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9861 successful. */
9863 static int
9864 tiff_load (f, img)
9865 struct frame *f;
9866 struct image *img;
9868 Lisp_Object file, specified_file;
9869 Lisp_Object specified_data;
9870 TIFF *tiff;
9871 int width, height, x, y;
9872 uint32 *buf;
9873 int rc;
9874 XImage *ximg;
9875 struct gcpro gcpro1;
9876 tiff_memory_source memsrc;
9878 specified_file = image_spec_value (img->spec, QCfile, NULL);
9879 specified_data = image_spec_value (img->spec, QCdata, NULL);
9880 file = Qnil;
9881 GCPRO1 (file);
9883 TIFFSetErrorHandler (tiff_error_handler);
9884 TIFFSetWarningHandler (tiff_warning_handler);
9886 if (NILP (specified_data))
9888 /* Read from a file */
9889 file = x_find_image_file (specified_file);
9890 if (!STRINGP (file))
9892 image_error ("Cannot find image file `%s'", file, Qnil);
9893 UNGCPRO;
9894 return 0;
9897 /* Try to open the image file. */
9898 tiff = TIFFOpen (XSTRING (file)->data, "r");
9899 if (tiff == NULL)
9901 image_error ("Cannot open `%s'", file, Qnil);
9902 UNGCPRO;
9903 return 0;
9906 else
9908 /* Memory source! */
9909 memsrc.bytes = XSTRING (specified_data)->data;
9910 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9911 memsrc.index = 0;
9913 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9914 (TIFFReadWriteProc) tiff_read_from_memory,
9915 (TIFFReadWriteProc) tiff_write_from_memory,
9916 tiff_seek_in_memory,
9917 tiff_close_memory,
9918 tiff_size_of_memory,
9919 tiff_mmap_memory,
9920 tiff_unmap_memory);
9922 if (!tiff)
9924 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9925 UNGCPRO;
9926 return 0;
9930 /* Get width and height of the image, and allocate a raster buffer
9931 of width x height 32-bit values. */
9932 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9933 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9934 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9936 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9937 TIFFClose (tiff);
9938 if (!rc)
9940 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9941 xfree (buf);
9942 UNGCPRO;
9943 return 0;
9946 /* Create the X image and pixmap. */
9947 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9949 xfree (buf);
9950 UNGCPRO;
9951 return 0;
9954 /* Initialize the color table. */
9955 init_color_table ();
9957 /* Process the pixel raster. Origin is in the lower-left corner. */
9958 for (y = 0; y < height; ++y)
9960 uint32 *row = buf + y * width;
9962 for (x = 0; x < width; ++x)
9964 uint32 abgr = row[x];
9965 int r = TIFFGetR (abgr) << 8;
9966 int g = TIFFGetG (abgr) << 8;
9967 int b = TIFFGetB (abgr) << 8;
9968 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9972 /* Remember the colors allocated for the image. Free the color table. */
9973 img->colors = colors_in_color_table (&img->ncolors);
9974 free_color_table ();
9976 img->width = width;
9977 img->height = height;
9979 /* Maybe fill in the background field while we have ximg handy. */
9980 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9981 IMAGE_BACKGROUND (img, f, ximg);
9983 /* Put the image into the pixmap, then free the X image and its buffer. */
9984 x_put_x_image (f, ximg, img->pixmap, width, height);
9985 x_destroy_x_image (ximg);
9986 xfree (buf);
9988 UNGCPRO;
9989 return 1;
9992 #endif /* HAVE_TIFF != 0 */
9996 /***********************************************************************
9998 ***********************************************************************/
10000 #if HAVE_GIF
10002 #include <gif_lib.h>
10004 static int gif_image_p P_ ((Lisp_Object object));
10005 static int gif_load P_ ((struct frame *f, struct image *img));
10007 /* The symbol `gif' identifying images of this type. */
10009 Lisp_Object Qgif;
10011 /* Indices of image specification fields in gif_format, below. */
10013 enum gif_keyword_index
10015 GIF_TYPE,
10016 GIF_DATA,
10017 GIF_FILE,
10018 GIF_ASCENT,
10019 GIF_MARGIN,
10020 GIF_RELIEF,
10021 GIF_ALGORITHM,
10022 GIF_HEURISTIC_MASK,
10023 GIF_MASK,
10024 GIF_IMAGE,
10025 GIF_BACKGROUND,
10026 GIF_LAST
10029 /* Vector of image_keyword structures describing the format
10030 of valid user-defined image specifications. */
10032 static struct image_keyword gif_format[GIF_LAST] =
10034 {":type", IMAGE_SYMBOL_VALUE, 1},
10035 {":data", IMAGE_STRING_VALUE, 0},
10036 {":file", IMAGE_STRING_VALUE, 0},
10037 {":ascent", IMAGE_ASCENT_VALUE, 0},
10038 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10039 {":relief", IMAGE_INTEGER_VALUE, 0},
10040 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10041 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10042 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10043 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
10044 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10047 /* Structure describing the image type `gif'. */
10049 static struct image_type gif_type =
10051 &Qgif,
10052 gif_image_p,
10053 gif_load,
10054 x_clear_image,
10055 NULL
10059 /* Return non-zero if OBJECT is a valid GIF image specification. */
10061 static int
10062 gif_image_p (object)
10063 Lisp_Object object;
10065 struct image_keyword fmt[GIF_LAST];
10066 bcopy (gif_format, fmt, sizeof fmt);
10068 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
10069 return 0;
10071 /* Must specify either the :data or :file keyword. */
10072 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
10076 /* Reading a GIF image from memory
10077 Based on the PNG memory stuff to a certain extent. */
10079 typedef struct
10081 unsigned char *bytes;
10082 size_t len;
10083 int index;
10085 gif_memory_source;
10088 /* Make the current memory source available to gif_read_from_memory.
10089 It's done this way because not all versions of libungif support
10090 a UserData field in the GifFileType structure. */
10091 static gif_memory_source *current_gif_memory_src;
10093 static int
10094 gif_read_from_memory (file, buf, len)
10095 GifFileType *file;
10096 GifByteType *buf;
10097 int len;
10099 gif_memory_source *src = current_gif_memory_src;
10101 if (len > src->len - src->index)
10102 return -1;
10104 bcopy (src->bytes + src->index, buf, len);
10105 src->index += len;
10106 return len;
10110 /* Load GIF image IMG for use on frame F. Value is non-zero if
10111 successful. */
10113 static int
10114 gif_load (f, img)
10115 struct frame *f;
10116 struct image *img;
10118 Lisp_Object file, specified_file;
10119 Lisp_Object specified_data;
10120 int rc, width, height, x, y, i;
10121 XImage *ximg;
10122 ColorMapObject *gif_color_map;
10123 unsigned long pixel_colors[256];
10124 GifFileType *gif;
10125 struct gcpro gcpro1;
10126 Lisp_Object image;
10127 int ino, image_left, image_top, image_width, image_height;
10128 gif_memory_source memsrc;
10129 unsigned char *raster;
10131 specified_file = image_spec_value (img->spec, QCfile, NULL);
10132 specified_data = image_spec_value (img->spec, QCdata, NULL);
10133 file = Qnil;
10134 GCPRO1 (file);
10136 if (NILP (specified_data))
10138 file = x_find_image_file (specified_file);
10139 if (!STRINGP (file))
10141 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10142 UNGCPRO;
10143 return 0;
10146 /* Open the GIF file. */
10147 gif = DGifOpenFileName (XSTRING (file)->data);
10148 if (gif == NULL)
10150 image_error ("Cannot open `%s'", file, Qnil);
10151 UNGCPRO;
10152 return 0;
10155 else
10157 /* Read from memory! */
10158 current_gif_memory_src = &memsrc;
10159 memsrc.bytes = XSTRING (specified_data)->data;
10160 memsrc.len = STRING_BYTES (XSTRING (specified_data));
10161 memsrc.index = 0;
10163 gif = DGifOpen(&memsrc, gif_read_from_memory);
10164 if (!gif)
10166 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
10167 UNGCPRO;
10168 return 0;
10172 /* Read entire contents. */
10173 rc = DGifSlurp (gif);
10174 if (rc == GIF_ERROR)
10176 image_error ("Error reading `%s'", img->spec, Qnil);
10177 DGifCloseFile (gif);
10178 UNGCPRO;
10179 return 0;
10182 image = image_spec_value (img->spec, QCindex, NULL);
10183 ino = INTEGERP (image) ? XFASTINT (image) : 0;
10184 if (ino >= gif->ImageCount)
10186 image_error ("Invalid image number `%s' in image `%s'",
10187 image, img->spec);
10188 DGifCloseFile (gif);
10189 UNGCPRO;
10190 return 0;
10193 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
10194 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
10196 /* Create the X image and pixmap. */
10197 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10199 DGifCloseFile (gif);
10200 UNGCPRO;
10201 return 0;
10204 /* Allocate colors. */
10205 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
10206 if (!gif_color_map)
10207 gif_color_map = gif->SColorMap;
10208 init_color_table ();
10209 bzero (pixel_colors, sizeof pixel_colors);
10211 for (i = 0; i < gif_color_map->ColorCount; ++i)
10213 int r = gif_color_map->Colors[i].Red << 8;
10214 int g = gif_color_map->Colors[i].Green << 8;
10215 int b = gif_color_map->Colors[i].Blue << 8;
10216 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
10219 img->colors = colors_in_color_table (&img->ncolors);
10220 free_color_table ();
10222 /* Clear the part of the screen image that are not covered by
10223 the image from the GIF file. Full animated GIF support
10224 requires more than can be done here (see the gif89 spec,
10225 disposal methods). Let's simply assume that the part
10226 not covered by a sub-image is in the frame's background color. */
10227 image_top = gif->SavedImages[ino].ImageDesc.Top;
10228 image_left = gif->SavedImages[ino].ImageDesc.Left;
10229 image_width = gif->SavedImages[ino].ImageDesc.Width;
10230 image_height = gif->SavedImages[ino].ImageDesc.Height;
10232 for (y = 0; y < image_top; ++y)
10233 for (x = 0; x < width; ++x)
10234 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10236 for (y = image_top + image_height; y < height; ++y)
10237 for (x = 0; x < width; ++x)
10238 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10240 for (y = image_top; y < image_top + image_height; ++y)
10242 for (x = 0; x < image_left; ++x)
10243 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10244 for (x = image_left + image_width; x < width; ++x)
10245 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10248 /* Read the GIF image into the X image. We use a local variable
10249 `raster' here because RasterBits below is a char *, and invites
10250 problems with bytes >= 0x80. */
10251 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
10253 if (gif->SavedImages[ino].ImageDesc.Interlace)
10255 static int interlace_start[] = {0, 4, 2, 1};
10256 static int interlace_increment[] = {8, 8, 4, 2};
10257 int pass;
10258 int row = interlace_start[0];
10260 pass = 0;
10262 for (y = 0; y < image_height; y++)
10264 if (row >= image_height)
10266 row = interlace_start[++pass];
10267 while (row >= image_height)
10268 row = interlace_start[++pass];
10271 for (x = 0; x < image_width; x++)
10273 int i = raster[(y * image_width) + x];
10274 XPutPixel (ximg, x + image_left, row + image_top,
10275 pixel_colors[i]);
10278 row += interlace_increment[pass];
10281 else
10283 for (y = 0; y < image_height; ++y)
10284 for (x = 0; x < image_width; ++x)
10286 int i = raster[y * image_width + x];
10287 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
10291 DGifCloseFile (gif);
10293 /* Maybe fill in the background field while we have ximg handy. */
10294 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10295 IMAGE_BACKGROUND (img, f, ximg);
10297 /* Put the image into the pixmap, then free the X image and its buffer. */
10298 x_put_x_image (f, ximg, img->pixmap, width, height);
10299 x_destroy_x_image (ximg);
10301 UNGCPRO;
10302 return 1;
10305 #endif /* HAVE_GIF != 0 */
10309 /***********************************************************************
10310 Ghostscript
10311 ***********************************************************************/
10313 static int gs_image_p P_ ((Lisp_Object object));
10314 static int gs_load P_ ((struct frame *f, struct image *img));
10315 static void gs_clear_image P_ ((struct frame *f, struct image *img));
10317 /* The symbol `postscript' identifying images of this type. */
10319 Lisp_Object Qpostscript;
10321 /* Keyword symbols. */
10323 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
10325 /* Indices of image specification fields in gs_format, below. */
10327 enum gs_keyword_index
10329 GS_TYPE,
10330 GS_PT_WIDTH,
10331 GS_PT_HEIGHT,
10332 GS_FILE,
10333 GS_LOADER,
10334 GS_BOUNDING_BOX,
10335 GS_ASCENT,
10336 GS_MARGIN,
10337 GS_RELIEF,
10338 GS_ALGORITHM,
10339 GS_HEURISTIC_MASK,
10340 GS_MASK,
10341 GS_BACKGROUND,
10342 GS_LAST
10345 /* Vector of image_keyword structures describing the format
10346 of valid user-defined image specifications. */
10348 static struct image_keyword gs_format[GS_LAST] =
10350 {":type", IMAGE_SYMBOL_VALUE, 1},
10351 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10352 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10353 {":file", IMAGE_STRING_VALUE, 1},
10354 {":loader", IMAGE_FUNCTION_VALUE, 0},
10355 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
10356 {":ascent", IMAGE_ASCENT_VALUE, 0},
10357 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10358 {":relief", IMAGE_INTEGER_VALUE, 0},
10359 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10360 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10361 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10362 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10365 /* Structure describing the image type `ghostscript'. */
10367 static struct image_type gs_type =
10369 &Qpostscript,
10370 gs_image_p,
10371 gs_load,
10372 gs_clear_image,
10373 NULL
10377 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10379 static void
10380 gs_clear_image (f, img)
10381 struct frame *f;
10382 struct image *img;
10384 /* IMG->data.ptr_val may contain a recorded colormap. */
10385 xfree (img->data.ptr_val);
10386 x_clear_image (f, img);
10390 /* Return non-zero if OBJECT is a valid Ghostscript image
10391 specification. */
10393 static int
10394 gs_image_p (object)
10395 Lisp_Object object;
10397 struct image_keyword fmt[GS_LAST];
10398 Lisp_Object tem;
10399 int i;
10401 bcopy (gs_format, fmt, sizeof fmt);
10403 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10404 return 0;
10406 /* Bounding box must be a list or vector containing 4 integers. */
10407 tem = fmt[GS_BOUNDING_BOX].value;
10408 if (CONSP (tem))
10410 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10411 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10412 return 0;
10413 if (!NILP (tem))
10414 return 0;
10416 else if (VECTORP (tem))
10418 if (XVECTOR (tem)->size != 4)
10419 return 0;
10420 for (i = 0; i < 4; ++i)
10421 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10422 return 0;
10424 else
10425 return 0;
10427 return 1;
10431 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10432 if successful. */
10434 static int
10435 gs_load (f, img)
10436 struct frame *f;
10437 struct image *img;
10439 char buffer[100];
10440 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10441 struct gcpro gcpro1, gcpro2;
10442 Lisp_Object frame;
10443 double in_width, in_height;
10444 Lisp_Object pixel_colors = Qnil;
10446 /* Compute pixel size of pixmap needed from the given size in the
10447 image specification. Sizes in the specification are in pt. 1 pt
10448 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10449 info. */
10450 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10451 in_width = XFASTINT (pt_width) / 72.0;
10452 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10453 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10454 in_height = XFASTINT (pt_height) / 72.0;
10455 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10457 /* Create the pixmap. */
10458 xassert (img->pixmap == None);
10459 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10460 img->width, img->height,
10461 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10463 if (!img->pixmap)
10465 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10466 return 0;
10469 /* Call the loader to fill the pixmap. It returns a process object
10470 if successful. We do not record_unwind_protect here because
10471 other places in redisplay like calling window scroll functions
10472 don't either. Let the Lisp loader use `unwind-protect' instead. */
10473 GCPRO2 (window_and_pixmap_id, pixel_colors);
10475 sprintf (buffer, "%lu %lu",
10476 (unsigned long) FRAME_X_WINDOW (f),
10477 (unsigned long) img->pixmap);
10478 window_and_pixmap_id = build_string (buffer);
10480 sprintf (buffer, "%lu %lu",
10481 FRAME_FOREGROUND_PIXEL (f),
10482 FRAME_BACKGROUND_PIXEL (f));
10483 pixel_colors = build_string (buffer);
10485 XSETFRAME (frame, f);
10486 loader = image_spec_value (img->spec, QCloader, NULL);
10487 if (NILP (loader))
10488 loader = intern ("gs-load-image");
10490 img->data.lisp_val = call6 (loader, frame, img->spec,
10491 make_number (img->width),
10492 make_number (img->height),
10493 window_and_pixmap_id,
10494 pixel_colors);
10495 UNGCPRO;
10496 return PROCESSP (img->data.lisp_val);
10500 /* Kill the Ghostscript process that was started to fill PIXMAP on
10501 frame F. Called from XTread_socket when receiving an event
10502 telling Emacs that Ghostscript has finished drawing. */
10504 void
10505 x_kill_gs_process (pixmap, f)
10506 Pixmap pixmap;
10507 struct frame *f;
10509 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10510 int class, i;
10511 struct image *img;
10513 /* Find the image containing PIXMAP. */
10514 for (i = 0; i < c->used; ++i)
10515 if (c->images[i]->pixmap == pixmap)
10516 break;
10518 /* Should someone in between have cleared the image cache, for
10519 instance, give up. */
10520 if (i == c->used)
10521 return;
10523 /* Kill the GS process. We should have found PIXMAP in the image
10524 cache and its image should contain a process object. */
10525 img = c->images[i];
10526 xassert (PROCESSP (img->data.lisp_val));
10527 Fkill_process (img->data.lisp_val, Qnil);
10528 img->data.lisp_val = Qnil;
10530 /* On displays with a mutable colormap, figure out the colors
10531 allocated for the image by looking at the pixels of an XImage for
10532 img->pixmap. */
10533 class = FRAME_X_VISUAL (f)->class;
10534 if (class != StaticColor && class != StaticGray && class != TrueColor)
10536 XImage *ximg;
10538 BLOCK_INPUT;
10540 /* Try to get an XImage for img->pixmep. */
10541 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10542 0, 0, img->width, img->height, ~0, ZPixmap);
10543 if (ximg)
10545 int x, y;
10547 /* Initialize the color table. */
10548 init_color_table ();
10550 /* For each pixel of the image, look its color up in the
10551 color table. After having done so, the color table will
10552 contain an entry for each color used by the image. */
10553 for (y = 0; y < img->height; ++y)
10554 for (x = 0; x < img->width; ++x)
10556 unsigned long pixel = XGetPixel (ximg, x, y);
10557 lookup_pixel_color (f, pixel);
10560 /* Record colors in the image. Free color table and XImage. */
10561 img->colors = colors_in_color_table (&img->ncolors);
10562 free_color_table ();
10563 XDestroyImage (ximg);
10565 #if 0 /* This doesn't seem to be the case. If we free the colors
10566 here, we get a BadAccess later in x_clear_image when
10567 freeing the colors. */
10568 /* We have allocated colors once, but Ghostscript has also
10569 allocated colors on behalf of us. So, to get the
10570 reference counts right, free them once. */
10571 if (img->ncolors)
10572 x_free_colors (f, img->colors, img->ncolors);
10573 #endif
10575 else
10576 image_error ("Cannot get X image of `%s'; colors will not be freed",
10577 img->spec, Qnil);
10579 UNBLOCK_INPUT;
10582 /* Now that we have the pixmap, compute mask and transform the
10583 image if requested. */
10584 BLOCK_INPUT;
10585 postprocess_image (f, img);
10586 UNBLOCK_INPUT;
10591 /***********************************************************************
10592 Window properties
10593 ***********************************************************************/
10595 DEFUN ("x-change-window-property", Fx_change_window_property,
10596 Sx_change_window_property, 2, 3, 0,
10597 doc: /* Change window property PROP to VALUE on the X window of FRAME.
10598 PROP and VALUE must be strings. FRAME nil or omitted means use the
10599 selected frame. Value is VALUE. */)
10600 (prop, value, frame)
10601 Lisp_Object frame, prop, value;
10603 struct frame *f = check_x_frame (frame);
10604 Atom prop_atom;
10606 CHECK_STRING (prop);
10607 CHECK_STRING (value);
10609 BLOCK_INPUT;
10610 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10611 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10612 prop_atom, XA_STRING, 8, PropModeReplace,
10613 XSTRING (value)->data, XSTRING (value)->size);
10615 /* Make sure the property is set when we return. */
10616 XFlush (FRAME_X_DISPLAY (f));
10617 UNBLOCK_INPUT;
10619 return value;
10623 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10624 Sx_delete_window_property, 1, 2, 0,
10625 doc: /* Remove window property PROP from X window of FRAME.
10626 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10627 (prop, frame)
10628 Lisp_Object prop, frame;
10630 struct frame *f = check_x_frame (frame);
10631 Atom prop_atom;
10633 CHECK_STRING (prop);
10634 BLOCK_INPUT;
10635 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10636 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10638 /* Make sure the property is removed when we return. */
10639 XFlush (FRAME_X_DISPLAY (f));
10640 UNBLOCK_INPUT;
10642 return prop;
10646 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10647 1, 2, 0,
10648 doc: /* Value is the value of window property PROP on FRAME.
10649 If FRAME is nil or omitted, use the selected frame. Value is nil
10650 if FRAME hasn't a property with name PROP or if PROP has no string
10651 value. */)
10652 (prop, frame)
10653 Lisp_Object prop, frame;
10655 struct frame *f = check_x_frame (frame);
10656 Atom prop_atom;
10657 int rc;
10658 Lisp_Object prop_value = Qnil;
10659 char *tmp_data = NULL;
10660 Atom actual_type;
10661 int actual_format;
10662 unsigned long actual_size, bytes_remaining;
10664 CHECK_STRING (prop);
10665 BLOCK_INPUT;
10666 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10667 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10668 prop_atom, 0, 0, False, XA_STRING,
10669 &actual_type, &actual_format, &actual_size,
10670 &bytes_remaining, (unsigned char **) &tmp_data);
10671 if (rc == Success)
10673 int size = bytes_remaining;
10675 XFree (tmp_data);
10676 tmp_data = NULL;
10678 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10679 prop_atom, 0, bytes_remaining,
10680 False, XA_STRING,
10681 &actual_type, &actual_format,
10682 &actual_size, &bytes_remaining,
10683 (unsigned char **) &tmp_data);
10684 if (rc == Success && tmp_data)
10685 prop_value = make_string (tmp_data, size);
10687 XFree (tmp_data);
10690 UNBLOCK_INPUT;
10691 return prop_value;
10696 /***********************************************************************
10697 Busy cursor
10698 ***********************************************************************/
10700 /* If non-null, an asynchronous timer that, when it expires, displays
10701 an hourglass cursor on all frames. */
10703 static struct atimer *hourglass_atimer;
10705 /* Non-zero means an hourglass cursor is currently shown. */
10707 static int hourglass_shown_p;
10709 /* Number of seconds to wait before displaying an hourglass cursor. */
10711 static Lisp_Object Vhourglass_delay;
10713 /* Default number of seconds to wait before displaying an hourglass
10714 cursor. */
10716 #define DEFAULT_HOURGLASS_DELAY 1
10718 /* Function prototypes. */
10720 static void show_hourglass P_ ((struct atimer *));
10721 static void hide_hourglass P_ ((void));
10724 /* Cancel a currently active hourglass timer, and start a new one. */
10726 void
10727 start_hourglass ()
10729 EMACS_TIME delay;
10730 int secs, usecs = 0;
10732 cancel_hourglass ();
10734 if (INTEGERP (Vhourglass_delay)
10735 && XINT (Vhourglass_delay) > 0)
10736 secs = XFASTINT (Vhourglass_delay);
10737 else if (FLOATP (Vhourglass_delay)
10738 && XFLOAT_DATA (Vhourglass_delay) > 0)
10740 Lisp_Object tem;
10741 tem = Ftruncate (Vhourglass_delay, Qnil);
10742 secs = XFASTINT (tem);
10743 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10745 else
10746 secs = DEFAULT_HOURGLASS_DELAY;
10748 EMACS_SET_SECS_USECS (delay, secs, usecs);
10749 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10750 show_hourglass, NULL);
10754 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10755 shown. */
10757 void
10758 cancel_hourglass ()
10760 if (hourglass_atimer)
10762 cancel_atimer (hourglass_atimer);
10763 hourglass_atimer = NULL;
10766 if (hourglass_shown_p)
10767 hide_hourglass ();
10771 /* Timer function of hourglass_atimer. TIMER is equal to
10772 hourglass_atimer.
10774 Display an hourglass pointer on all frames by mapping the frames'
10775 hourglass_window. Set the hourglass_p flag in the frames'
10776 output_data.x structure to indicate that an hourglass cursor is
10777 shown on the frames. */
10779 static void
10780 show_hourglass (timer)
10781 struct atimer *timer;
10783 /* The timer implementation will cancel this timer automatically
10784 after this function has run. Set hourglass_atimer to null
10785 so that we know the timer doesn't have to be canceled. */
10786 hourglass_atimer = NULL;
10788 if (!hourglass_shown_p)
10790 Lisp_Object rest, frame;
10792 BLOCK_INPUT;
10794 FOR_EACH_FRAME (rest, frame)
10796 struct frame *f = XFRAME (frame);
10798 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10800 Display *dpy = FRAME_X_DISPLAY (f);
10802 #ifdef USE_X_TOOLKIT
10803 if (f->output_data.x->widget)
10804 #else
10805 if (FRAME_OUTER_WINDOW (f))
10806 #endif
10808 f->output_data.x->hourglass_p = 1;
10810 if (!f->output_data.x->hourglass_window)
10812 unsigned long mask = CWCursor;
10813 XSetWindowAttributes attrs;
10815 attrs.cursor = f->output_data.x->hourglass_cursor;
10817 f->output_data.x->hourglass_window
10818 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10819 0, 0, 32000, 32000, 0, 0,
10820 InputOnly,
10821 CopyFromParent,
10822 mask, &attrs);
10825 XMapRaised (dpy, f->output_data.x->hourglass_window);
10826 XFlush (dpy);
10831 hourglass_shown_p = 1;
10832 UNBLOCK_INPUT;
10837 /* Hide the hourglass pointer on all frames, if it is currently
10838 shown. */
10840 static void
10841 hide_hourglass ()
10843 if (hourglass_shown_p)
10845 Lisp_Object rest, frame;
10847 BLOCK_INPUT;
10848 FOR_EACH_FRAME (rest, frame)
10850 struct frame *f = XFRAME (frame);
10852 if (FRAME_X_P (f)
10853 /* Watch out for newly created frames. */
10854 && f->output_data.x->hourglass_window)
10856 XUnmapWindow (FRAME_X_DISPLAY (f),
10857 f->output_data.x->hourglass_window);
10858 /* Sync here because XTread_socket looks at the
10859 hourglass_p flag that is reset to zero below. */
10860 XSync (FRAME_X_DISPLAY (f), False);
10861 f->output_data.x->hourglass_p = 0;
10865 hourglass_shown_p = 0;
10866 UNBLOCK_INPUT;
10872 /***********************************************************************
10873 Tool tips
10874 ***********************************************************************/
10876 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10877 Lisp_Object, Lisp_Object));
10878 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10879 Lisp_Object, int, int, int *, int *));
10881 /* The frame of a currently visible tooltip. */
10883 Lisp_Object tip_frame;
10885 /* If non-nil, a timer started that hides the last tooltip when it
10886 fires. */
10888 Lisp_Object tip_timer;
10889 Window tip_window;
10891 /* If non-nil, a vector of 3 elements containing the last args
10892 with which x-show-tip was called. See there. */
10894 Lisp_Object last_show_tip_args;
10896 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10898 Lisp_Object Vx_max_tooltip_size;
10901 static Lisp_Object
10902 unwind_create_tip_frame (frame)
10903 Lisp_Object frame;
10905 Lisp_Object deleted;
10907 deleted = unwind_create_frame (frame);
10908 if (EQ (deleted, Qt))
10910 tip_window = None;
10911 tip_frame = Qnil;
10914 return deleted;
10918 /* Create a frame for a tooltip on the display described by DPYINFO.
10919 PARMS is a list of frame parameters. TEXT is the string to
10920 display in the tip frame. Value is the frame.
10922 Note that functions called here, esp. x_default_parameter can
10923 signal errors, for instance when a specified color name is
10924 undefined. We have to make sure that we're in a consistent state
10925 when this happens. */
10927 static Lisp_Object
10928 x_create_tip_frame (dpyinfo, parms, text)
10929 struct x_display_info *dpyinfo;
10930 Lisp_Object parms, text;
10932 struct frame *f;
10933 Lisp_Object frame, tem;
10934 Lisp_Object name;
10935 long window_prompting = 0;
10936 int width, height;
10937 int count = BINDING_STACK_SIZE ();
10938 struct gcpro gcpro1, gcpro2, gcpro3;
10939 struct kboard *kb;
10940 int face_change_count_before = face_change_count;
10941 Lisp_Object buffer;
10942 struct buffer *old_buffer;
10944 check_x ();
10946 /* Use this general default value to start with until we know if
10947 this frame has a specified name. */
10948 Vx_resource_name = Vinvocation_name;
10950 #ifdef MULTI_KBOARD
10951 kb = dpyinfo->kboard;
10952 #else
10953 kb = &the_only_kboard;
10954 #endif
10956 /* Get the name of the frame to use for resource lookup. */
10957 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10958 if (!STRINGP (name)
10959 && !EQ (name, Qunbound)
10960 && !NILP (name))
10961 error ("Invalid frame name--not a string or nil");
10962 Vx_resource_name = name;
10964 frame = Qnil;
10965 GCPRO3 (parms, name, frame);
10966 f = make_frame (1);
10967 XSETFRAME (frame, f);
10969 buffer = Fget_buffer_create (build_string (" *tip*"));
10970 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10971 old_buffer = current_buffer;
10972 set_buffer_internal_1 (XBUFFER (buffer));
10973 current_buffer->truncate_lines = Qnil;
10974 Ferase_buffer ();
10975 Finsert (1, &text);
10976 set_buffer_internal_1 (old_buffer);
10978 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10979 record_unwind_protect (unwind_create_tip_frame, frame);
10981 /* By setting the output method, we're essentially saying that
10982 the frame is live, as per FRAME_LIVE_P. If we get a signal
10983 from this point on, x_destroy_window might screw up reference
10984 counts etc. */
10985 f->output_method = output_x_window;
10986 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10987 bzero (f->output_data.x, sizeof (struct x_output));
10988 f->output_data.x->icon_bitmap = -1;
10989 f->output_data.x->fontset = -1;
10990 f->output_data.x->scroll_bar_foreground_pixel = -1;
10991 f->output_data.x->scroll_bar_background_pixel = -1;
10992 #ifdef USE_TOOLKIT_SCROLL_BARS
10993 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
10994 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
10995 #endif /* USE_TOOLKIT_SCROLL_BARS */
10996 f->icon_name = Qnil;
10997 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10998 #if GLYPH_DEBUG
10999 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
11000 dpyinfo_refcount = dpyinfo->reference_count;
11001 #endif /* GLYPH_DEBUG */
11002 #ifdef MULTI_KBOARD
11003 FRAME_KBOARD (f) = kb;
11004 #endif
11005 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
11006 f->output_data.x->explicit_parent = 0;
11008 /* These colors will be set anyway later, but it's important
11009 to get the color reference counts right, so initialize them! */
11011 Lisp_Object black;
11012 struct gcpro gcpro1;
11014 black = build_string ("black");
11015 GCPRO1 (black);
11016 f->output_data.x->foreground_pixel
11017 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11018 f->output_data.x->background_pixel
11019 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11020 f->output_data.x->cursor_pixel
11021 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11022 f->output_data.x->cursor_foreground_pixel
11023 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11024 f->output_data.x->border_pixel
11025 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11026 f->output_data.x->mouse_pixel
11027 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
11028 UNGCPRO;
11031 /* Set the name; the functions to which we pass f expect the name to
11032 be set. */
11033 if (EQ (name, Qunbound) || NILP (name))
11035 f->name = build_string (dpyinfo->x_id_name);
11036 f->explicit_name = 0;
11038 else
11040 f->name = name;
11041 f->explicit_name = 1;
11042 /* use the frame's title when getting resources for this frame. */
11043 specbind (Qx_resource_name, name);
11046 /* Extract the window parameters from the supplied values that are
11047 needed to determine window geometry. */
11049 Lisp_Object font;
11051 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
11053 BLOCK_INPUT;
11054 /* First, try whatever font the caller has specified. */
11055 if (STRINGP (font))
11057 tem = Fquery_fontset (font, Qnil);
11058 if (STRINGP (tem))
11059 font = x_new_fontset (f, XSTRING (tem)->data);
11060 else
11061 font = x_new_font (f, XSTRING (font)->data);
11064 /* Try out a font which we hope has bold and italic variations. */
11065 if (!STRINGP (font))
11066 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11067 if (!STRINGP (font))
11068 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11069 if (! STRINGP (font))
11070 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11071 if (! STRINGP (font))
11072 /* This was formerly the first thing tried, but it finds too many fonts
11073 and takes too long. */
11074 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11075 /* If those didn't work, look for something which will at least work. */
11076 if (! STRINGP (font))
11077 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11078 UNBLOCK_INPUT;
11079 if (! STRINGP (font))
11080 font = build_string ("fixed");
11082 x_default_parameter (f, parms, Qfont, font,
11083 "font", "Font", RES_TYPE_STRING);
11086 x_default_parameter (f, parms, Qborder_width, make_number (2),
11087 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
11089 /* This defaults to 2 in order to match xterm. We recognize either
11090 internalBorderWidth or internalBorder (which is what xterm calls
11091 it). */
11092 if (NILP (Fassq (Qinternal_border_width, parms)))
11094 Lisp_Object value;
11096 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
11097 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
11098 if (! EQ (value, Qunbound))
11099 parms = Fcons (Fcons (Qinternal_border_width, value),
11100 parms);
11103 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
11104 "internalBorderWidth", "internalBorderWidth",
11105 RES_TYPE_NUMBER);
11107 /* Also do the stuff which must be set before the window exists. */
11108 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
11109 "foreground", "Foreground", RES_TYPE_STRING);
11110 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
11111 "background", "Background", RES_TYPE_STRING);
11112 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
11113 "pointerColor", "Foreground", RES_TYPE_STRING);
11114 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
11115 "cursorColor", "Foreground", RES_TYPE_STRING);
11116 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
11117 "borderColor", "BorderColor", RES_TYPE_STRING);
11119 /* Init faces before x_default_parameter is called for scroll-bar
11120 parameters because that function calls x_set_scroll_bar_width,
11121 which calls change_frame_size, which calls Fset_window_buffer,
11122 which runs hooks, which call Fvertical_motion. At the end, we
11123 end up in init_iterator with a null face cache, which should not
11124 happen. */
11125 init_frame_faces (f);
11127 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
11128 window_prompting = x_figure_window_size (f, parms);
11130 if (window_prompting & XNegative)
11132 if (window_prompting & YNegative)
11133 f->output_data.x->win_gravity = SouthEastGravity;
11134 else
11135 f->output_data.x->win_gravity = NorthEastGravity;
11137 else
11139 if (window_prompting & YNegative)
11140 f->output_data.x->win_gravity = SouthWestGravity;
11141 else
11142 f->output_data.x->win_gravity = NorthWestGravity;
11145 f->output_data.x->size_hint_flags = window_prompting;
11147 XSetWindowAttributes attrs;
11148 unsigned long mask;
11150 BLOCK_INPUT;
11151 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
11152 if (DoesSaveUnders (dpyinfo->screen))
11153 mask |= CWSaveUnder;
11155 /* Window managers look at the override-redirect flag to determine
11156 whether or net to give windows a decoration (Xlib spec, chapter
11157 3.2.8). */
11158 attrs.override_redirect = True;
11159 attrs.save_under = True;
11160 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
11161 /* Arrange for getting MapNotify and UnmapNotify events. */
11162 attrs.event_mask = StructureNotifyMask;
11163 tip_window
11164 = FRAME_X_WINDOW (f)
11165 = XCreateWindow (FRAME_X_DISPLAY (f),
11166 FRAME_X_DISPLAY_INFO (f)->root_window,
11167 /* x, y, width, height */
11168 0, 0, 1, 1,
11169 /* Border. */
11171 CopyFromParent, InputOutput, CopyFromParent,
11172 mask, &attrs);
11173 UNBLOCK_INPUT;
11176 x_make_gc (f);
11178 x_default_parameter (f, parms, Qauto_raise, Qnil,
11179 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11180 x_default_parameter (f, parms, Qauto_lower, Qnil,
11181 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11182 x_default_parameter (f, parms, Qcursor_type, Qbox,
11183 "cursorType", "CursorType", RES_TYPE_SYMBOL);
11185 /* Dimensions, especially f->height, must be done via change_frame_size.
11186 Change will not be effected unless different from the current
11187 f->height. */
11188 width = f->width;
11189 height = f->height;
11190 f->height = 0;
11191 SET_FRAME_WIDTH (f, 0);
11192 change_frame_size (f, height, width, 1, 0, 0);
11194 /* Set up faces after all frame parameters are known. This call
11195 also merges in face attributes specified for new frames.
11197 Frame parameters may be changed if .Xdefaults contains
11198 specifications for the default font. For example, if there is an
11199 `Emacs.default.attributeBackground: pink', the `background-color'
11200 attribute of the frame get's set, which let's the internal border
11201 of the tooltip frame appear in pink. Prevent this. */
11203 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
11205 /* Set tip_frame here, so that */
11206 tip_frame = frame;
11207 call1 (Qface_set_after_frame_default, frame);
11209 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
11210 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
11211 Qnil));
11214 f->no_split = 1;
11216 UNGCPRO;
11218 /* It is now ok to make the frame official even if we get an error
11219 below. And the frame needs to be on Vframe_list or making it
11220 visible won't work. */
11221 Vframe_list = Fcons (frame, Vframe_list);
11223 /* Now that the frame is official, it counts as a reference to
11224 its display. */
11225 FRAME_X_DISPLAY_INFO (f)->reference_count++;
11227 /* Setting attributes of faces of the tooltip frame from resources
11228 and similar will increment face_change_count, which leads to the
11229 clearing of all current matrices. Since this isn't necessary
11230 here, avoid it by resetting face_change_count to the value it
11231 had before we created the tip frame. */
11232 face_change_count = face_change_count_before;
11234 /* Discard the unwind_protect. */
11235 return unbind_to (count, frame);
11239 /* Compute where to display tip frame F. PARMS is the list of frame
11240 parameters for F. DX and DY are specified offsets from the current
11241 location of the mouse. WIDTH and HEIGHT are the width and height
11242 of the tooltip. Return coordinates relative to the root window of
11243 the display in *ROOT_X, and *ROOT_Y. */
11245 static void
11246 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
11247 struct frame *f;
11248 Lisp_Object parms, dx, dy;
11249 int width, height;
11250 int *root_x, *root_y;
11252 Lisp_Object left, top;
11253 int win_x, win_y;
11254 Window root, child;
11255 unsigned pmask;
11257 /* User-specified position? */
11258 left = Fcdr (Fassq (Qleft, parms));
11259 top = Fcdr (Fassq (Qtop, parms));
11261 /* Move the tooltip window where the mouse pointer is. Resize and
11262 show it. */
11263 if (!INTEGERP (left) || !INTEGERP (top))
11265 BLOCK_INPUT;
11266 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
11267 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
11268 UNBLOCK_INPUT;
11271 if (INTEGERP (top))
11272 *root_y = XINT (top);
11273 else if (*root_y + XINT (dy) - height < 0)
11274 *root_y -= XINT (dy);
11275 else
11277 *root_y -= height;
11278 *root_y += XINT (dy);
11281 if (INTEGERP (left))
11282 *root_x = XINT (left);
11283 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
11284 /* It fits to the right of the pointer. */
11285 *root_x += XINT (dx);
11286 else if (width + XINT (dx) <= *root_x)
11287 /* It fits to the left of the pointer. */
11288 *root_x -= width + XINT (dx);
11289 else
11290 /* Put it left-justified on the screen--it ought to fit that way. */
11291 *root_x = 0;
11295 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
11296 doc: /* Show STRING in a "tooltip" window on frame FRAME.
11297 A tooltip window is a small X window displaying a string.
11299 FRAME nil or omitted means use the selected frame.
11301 PARMS is an optional list of frame parameters which can be used to
11302 change the tooltip's appearance.
11304 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11305 means use the default timeout of 5 seconds.
11307 If the list of frame parameters PARAMS contains a `left' parameters,
11308 the tooltip is displayed at that x-position. Otherwise it is
11309 displayed at the mouse position, with offset DX added (default is 5 if
11310 DX isn't specified). Likewise for the y-position; if a `top' frame
11311 parameter is specified, it determines the y-position of the tooltip
11312 window, otherwise it is displayed at the mouse position, with offset
11313 DY added (default is -10).
11315 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11316 Text larger than the specified size is clipped. */)
11317 (string, frame, parms, timeout, dx, dy)
11318 Lisp_Object string, frame, parms, timeout, dx, dy;
11320 struct frame *f;
11321 struct window *w;
11322 int root_x, root_y;
11323 struct buffer *old_buffer;
11324 struct text_pos pos;
11325 int i, width, height;
11326 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
11327 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11328 int count = BINDING_STACK_SIZE ();
11330 specbind (Qinhibit_redisplay, Qt);
11332 GCPRO4 (string, parms, frame, timeout);
11334 CHECK_STRING (string);
11335 f = check_x_frame (frame);
11336 if (NILP (timeout))
11337 timeout = make_number (5);
11338 else
11339 CHECK_NATNUM (timeout);
11341 if (NILP (dx))
11342 dx = make_number (5);
11343 else
11344 CHECK_NUMBER (dx);
11346 if (NILP (dy))
11347 dy = make_number (-10);
11348 else
11349 CHECK_NUMBER (dy);
11351 if (NILP (last_show_tip_args))
11352 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
11354 if (!NILP (tip_frame))
11356 Lisp_Object last_string = AREF (last_show_tip_args, 0);
11357 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
11358 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
11360 if (EQ (frame, last_frame)
11361 && !NILP (Fequal (last_string, string))
11362 && !NILP (Fequal (last_parms, parms)))
11364 struct frame *f = XFRAME (tip_frame);
11366 /* Only DX and DY have changed. */
11367 if (!NILP (tip_timer))
11369 Lisp_Object timer = tip_timer;
11370 tip_timer = Qnil;
11371 call1 (Qcancel_timer, timer);
11374 BLOCK_INPUT;
11375 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
11376 PIXEL_HEIGHT (f), &root_x, &root_y);
11377 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11378 root_x, root_y);
11379 UNBLOCK_INPUT;
11380 goto start_timer;
11384 /* Hide a previous tip, if any. */
11385 Fx_hide_tip ();
11387 ASET (last_show_tip_args, 0, string);
11388 ASET (last_show_tip_args, 1, frame);
11389 ASET (last_show_tip_args, 2, parms);
11391 /* Add default values to frame parameters. */
11392 if (NILP (Fassq (Qname, parms)))
11393 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
11394 if (NILP (Fassq (Qinternal_border_width, parms)))
11395 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
11396 if (NILP (Fassq (Qborder_width, parms)))
11397 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
11398 if (NILP (Fassq (Qborder_color, parms)))
11399 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
11400 if (NILP (Fassq (Qbackground_color, parms)))
11401 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
11402 parms);
11404 /* Create a frame for the tooltip, and record it in the global
11405 variable tip_frame. */
11406 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
11407 f = XFRAME (frame);
11409 /* Set up the frame's root window. */
11410 w = XWINDOW (FRAME_ROOT_WINDOW (f));
11411 w->left = w->top = make_number (0);
11413 if (CONSP (Vx_max_tooltip_size)
11414 && INTEGERP (XCAR (Vx_max_tooltip_size))
11415 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11416 && INTEGERP (XCDR (Vx_max_tooltip_size))
11417 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11419 w->width = XCAR (Vx_max_tooltip_size);
11420 w->height = XCDR (Vx_max_tooltip_size);
11422 else
11424 w->width = make_number (80);
11425 w->height = make_number (40);
11428 f->window_width = XINT (w->width);
11429 adjust_glyphs (f);
11430 w->pseudo_window_p = 1;
11432 /* Display the tooltip text in a temporary buffer. */
11433 old_buffer = current_buffer;
11434 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11435 current_buffer->truncate_lines = Qnil;
11436 clear_glyph_matrix (w->desired_matrix);
11437 clear_glyph_matrix (w->current_matrix);
11438 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11439 try_window (FRAME_ROOT_WINDOW (f), pos);
11441 /* Compute width and height of the tooltip. */
11442 width = height = 0;
11443 for (i = 0; i < w->desired_matrix->nrows; ++i)
11445 struct glyph_row *row = &w->desired_matrix->rows[i];
11446 struct glyph *last;
11447 int row_width;
11449 /* Stop at the first empty row at the end. */
11450 if (!row->enabled_p || !row->displays_text_p)
11451 break;
11453 /* Let the row go over the full width of the frame. */
11454 row->full_width_p = 1;
11456 /* There's a glyph at the end of rows that is used to place
11457 the cursor there. Don't include the width of this glyph. */
11458 if (row->used[TEXT_AREA])
11460 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
11461 row_width = row->pixel_width - last->pixel_width;
11463 else
11464 row_width = row->pixel_width;
11466 height += row->height;
11467 width = max (width, row_width);
11470 /* Add the frame's internal border to the width and height the X
11471 window should have. */
11472 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11473 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11475 /* Move the tooltip window where the mouse pointer is. Resize and
11476 show it. */
11477 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
11479 BLOCK_INPUT;
11480 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11481 root_x, root_y, width, height);
11482 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11483 UNBLOCK_INPUT;
11485 /* Draw into the window. */
11486 w->must_be_updated_p = 1;
11487 update_single_window (w, 1);
11489 /* Restore original current buffer. */
11490 set_buffer_internal_1 (old_buffer);
11491 windows_or_buffers_changed = old_windows_or_buffers_changed;
11493 start_timer:
11494 /* Let the tip disappear after timeout seconds. */
11495 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11496 intern ("x-hide-tip"));
11498 UNGCPRO;
11499 return unbind_to (count, Qnil);
11503 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11504 doc: /* Hide the current tooltip window, if there is any.
11505 Value is t if tooltip was open, nil otherwise. */)
11508 int count;
11509 Lisp_Object deleted, frame, timer;
11510 struct gcpro gcpro1, gcpro2;
11512 /* Return quickly if nothing to do. */
11513 if (NILP (tip_timer) && NILP (tip_frame))
11514 return Qnil;
11516 frame = tip_frame;
11517 timer = tip_timer;
11518 GCPRO2 (frame, timer);
11519 tip_frame = tip_timer = deleted = Qnil;
11521 count = BINDING_STACK_SIZE ();
11522 specbind (Qinhibit_redisplay, Qt);
11523 specbind (Qinhibit_quit, Qt);
11525 if (!NILP (timer))
11526 call1 (Qcancel_timer, timer);
11528 if (FRAMEP (frame))
11530 Fdelete_frame (frame, Qnil);
11531 deleted = Qt;
11533 #ifdef USE_LUCID
11534 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11535 redisplay procedure is not called when a tip frame over menu
11536 items is unmapped. Redisplay the menu manually... */
11538 struct frame *f = SELECTED_FRAME ();
11539 Widget w = f->output_data.x->menubar_widget;
11540 extern void xlwmenu_redisplay P_ ((Widget));
11542 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11543 && w != NULL)
11545 BLOCK_INPUT;
11546 xlwmenu_redisplay (w);
11547 UNBLOCK_INPUT;
11550 #endif /* USE_LUCID */
11553 UNGCPRO;
11554 return unbind_to (count, deleted);
11559 /***********************************************************************
11560 File selection dialog
11561 ***********************************************************************/
11563 #ifdef USE_MOTIF
11565 /* Callback for "OK" and "Cancel" on file selection dialog. */
11567 static void
11568 file_dialog_cb (widget, client_data, call_data)
11569 Widget widget;
11570 XtPointer call_data, client_data;
11572 int *result = (int *) client_data;
11573 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11574 *result = cb->reason;
11578 /* Callback for unmapping a file selection dialog. This is used to
11579 capture the case where a dialog is closed via a window manager's
11580 closer button, for example. Using a XmNdestroyCallback didn't work
11581 in this case. */
11583 static void
11584 file_dialog_unmap_cb (widget, client_data, call_data)
11585 Widget widget;
11586 XtPointer call_data, client_data;
11588 int *result = (int *) client_data;
11589 *result = XmCR_CANCEL;
11593 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11594 doc: /* Read file name, prompting with PROMPT in directory DIR.
11595 Use a file selection dialog.
11596 Select DEFAULT-FILENAME in the dialog's file selection box, if
11597 specified. Don't let the user enter a file name in the file
11598 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11599 (prompt, dir, default_filename, mustmatch)
11600 Lisp_Object prompt, dir, default_filename, mustmatch;
11602 int result;
11603 struct frame *f = SELECTED_FRAME ();
11604 Lisp_Object file = Qnil;
11605 Widget dialog, text, list, help;
11606 Arg al[10];
11607 int ac = 0;
11608 extern XtAppContext Xt_app_con;
11609 XmString dir_xmstring, pattern_xmstring;
11610 int count = specpdl_ptr - specpdl;
11611 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11613 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11614 CHECK_STRING (prompt);
11615 CHECK_STRING (dir);
11617 /* Prevent redisplay. */
11618 specbind (Qinhibit_redisplay, Qt);
11620 BLOCK_INPUT;
11622 /* Create the dialog with PROMPT as title, using DIR as initial
11623 directory and using "*" as pattern. */
11624 dir = Fexpand_file_name (dir, Qnil);
11625 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
11626 pattern_xmstring = XmStringCreateLocalized ("*");
11628 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
11629 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11630 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11631 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11632 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11633 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11634 "fsb", al, ac);
11635 XmStringFree (dir_xmstring);
11636 XmStringFree (pattern_xmstring);
11638 /* Add callbacks for OK and Cancel. */
11639 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11640 (XtPointer) &result);
11641 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11642 (XtPointer) &result);
11643 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11644 (XtPointer) &result);
11646 /* Disable the help button since we can't display help. */
11647 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11648 XtSetSensitive (help, False);
11650 /* Mark OK button as default. */
11651 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11652 XmNshowAsDefault, True, NULL);
11654 /* If MUSTMATCH is non-nil, disable the file entry field of the
11655 dialog, so that the user must select a file from the files list
11656 box. We can't remove it because we wouldn't have a way to get at
11657 the result file name, then. */
11658 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11659 if (!NILP (mustmatch))
11661 Widget label;
11662 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11663 XtSetSensitive (text, False);
11664 XtSetSensitive (label, False);
11667 /* Manage the dialog, so that list boxes get filled. */
11668 XtManageChild (dialog);
11670 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11671 must include the path for this to work. */
11672 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11673 if (STRINGP (default_filename))
11675 XmString default_xmstring;
11676 int item_pos;
11678 default_xmstring
11679 = XmStringCreateLocalized (XSTRING (default_filename)->data);
11681 if (!XmListItemExists (list, default_xmstring))
11683 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11684 XmListAddItem (list, default_xmstring, 0);
11685 item_pos = 0;
11687 else
11688 item_pos = XmListItemPos (list, default_xmstring);
11689 XmStringFree (default_xmstring);
11691 /* Select the item and scroll it into view. */
11692 XmListSelectPos (list, item_pos, True);
11693 XmListSetPos (list, item_pos);
11696 /* Process events until the user presses Cancel or OK. Block
11697 and unblock input here so that we get a chance of processing
11698 expose events. */
11699 UNBLOCK_INPUT;
11700 result = 0;
11701 while (result == 0)
11703 BLOCK_INPUT;
11704 XtAppProcessEvent (Xt_app_con, XtIMAll);
11705 UNBLOCK_INPUT;
11707 BLOCK_INPUT;
11709 /* Get the result. */
11710 if (result == XmCR_OK)
11712 XmString text;
11713 String data;
11715 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11716 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11717 XmStringFree (text);
11718 file = build_string (data);
11719 XtFree (data);
11721 else
11722 file = Qnil;
11724 /* Clean up. */
11725 XtUnmanageChild (dialog);
11726 XtDestroyWidget (dialog);
11727 UNBLOCK_INPUT;
11728 UNGCPRO;
11730 /* Make "Cancel" equivalent to C-g. */
11731 if (NILP (file))
11732 Fsignal (Qquit, Qnil);
11734 return unbind_to (count, file);
11737 #endif /* USE_MOTIF */
11741 /***********************************************************************
11742 Keyboard
11743 ***********************************************************************/
11745 #ifdef HAVE_XKBGETKEYBOARD
11746 #include <X11/XKBlib.h>
11747 #include <X11/keysym.h>
11748 #endif
11750 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11751 Sx_backspace_delete_keys_p, 0, 1, 0,
11752 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11753 FRAME nil means use the selected frame.
11754 Value is t if we know that both keys are present, and are mapped to the
11755 usual X keysyms. */)
11756 (frame)
11757 Lisp_Object frame;
11759 #ifdef HAVE_XKBGETKEYBOARD
11760 XkbDescPtr kb;
11761 struct frame *f = check_x_frame (frame);
11762 Display *dpy = FRAME_X_DISPLAY (f);
11763 Lisp_Object have_keys;
11764 int major, minor, op, event, error;
11766 BLOCK_INPUT;
11768 /* Check library version in case we're dynamically linked. */
11769 major = XkbMajorVersion;
11770 minor = XkbMinorVersion;
11771 if (!XkbLibraryVersion (&major, &minor))
11773 UNBLOCK_INPUT;
11774 return Qnil;
11777 /* Check that the server supports XKB. */
11778 major = XkbMajorVersion;
11779 minor = XkbMinorVersion;
11780 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11782 UNBLOCK_INPUT;
11783 return Qnil;
11786 have_keys = Qnil;
11787 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11788 if (kb)
11790 int delete_keycode = 0, backspace_keycode = 0, i;
11792 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11794 for (i = kb->min_key_code;
11795 (i < kb->max_key_code
11796 && (delete_keycode == 0 || backspace_keycode == 0));
11797 ++i)
11799 /* The XKB symbolic key names can be seen most easily in
11800 the PS file generated by `xkbprint -label name
11801 $DISPLAY'. */
11802 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11803 delete_keycode = i;
11804 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11805 backspace_keycode = i;
11808 XkbFreeNames (kb, 0, True);
11811 XkbFreeClientMap (kb, 0, True);
11813 if (delete_keycode
11814 && backspace_keycode
11815 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11816 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11817 have_keys = Qt;
11819 UNBLOCK_INPUT;
11820 return have_keys;
11821 #else /* not HAVE_XKBGETKEYBOARD */
11822 return Qnil;
11823 #endif /* not HAVE_XKBGETKEYBOARD */
11828 /***********************************************************************
11829 Initialization
11830 ***********************************************************************/
11832 void
11833 syms_of_xfns ()
11835 /* This is zero if not using X windows. */
11836 x_in_use = 0;
11838 /* The section below is built by the lisp expression at the top of the file,
11839 just above where these variables are declared. */
11840 /*&&& init symbols here &&&*/
11841 Qauto_raise = intern ("auto-raise");
11842 staticpro (&Qauto_raise);
11843 Qauto_lower = intern ("auto-lower");
11844 staticpro (&Qauto_lower);
11845 Qbar = intern ("bar");
11846 staticpro (&Qbar);
11847 Qhbar = intern ("hbar");
11848 staticpro (&Qhbar);
11849 Qborder_color = intern ("border-color");
11850 staticpro (&Qborder_color);
11851 Qborder_width = intern ("border-width");
11852 staticpro (&Qborder_width);
11853 Qbox = intern ("box");
11854 staticpro (&Qbox);
11855 Qcursor_color = intern ("cursor-color");
11856 staticpro (&Qcursor_color);
11857 Qcursor_type = intern ("cursor-type");
11858 staticpro (&Qcursor_type);
11859 Qgeometry = intern ("geometry");
11860 staticpro (&Qgeometry);
11861 Qicon_left = intern ("icon-left");
11862 staticpro (&Qicon_left);
11863 Qicon_top = intern ("icon-top");
11864 staticpro (&Qicon_top);
11865 Qicon_type = intern ("icon-type");
11866 staticpro (&Qicon_type);
11867 Qicon_name = intern ("icon-name");
11868 staticpro (&Qicon_name);
11869 Qinternal_border_width = intern ("internal-border-width");
11870 staticpro (&Qinternal_border_width);
11871 Qleft = intern ("left");
11872 staticpro (&Qleft);
11873 Qright = intern ("right");
11874 staticpro (&Qright);
11875 Qmouse_color = intern ("mouse-color");
11876 staticpro (&Qmouse_color);
11877 Qnone = intern ("none");
11878 staticpro (&Qnone);
11879 Qparent_id = intern ("parent-id");
11880 staticpro (&Qparent_id);
11881 Qscroll_bar_width = intern ("scroll-bar-width");
11882 staticpro (&Qscroll_bar_width);
11883 Qsuppress_icon = intern ("suppress-icon");
11884 staticpro (&Qsuppress_icon);
11885 Qundefined_color = intern ("undefined-color");
11886 staticpro (&Qundefined_color);
11887 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11888 staticpro (&Qvertical_scroll_bars);
11889 Qvisibility = intern ("visibility");
11890 staticpro (&Qvisibility);
11891 Qwindow_id = intern ("window-id");
11892 staticpro (&Qwindow_id);
11893 Qouter_window_id = intern ("outer-window-id");
11894 staticpro (&Qouter_window_id);
11895 Qx_frame_parameter = intern ("x-frame-parameter");
11896 staticpro (&Qx_frame_parameter);
11897 Qx_resource_name = intern ("x-resource-name");
11898 staticpro (&Qx_resource_name);
11899 Quser_position = intern ("user-position");
11900 staticpro (&Quser_position);
11901 Quser_size = intern ("user-size");
11902 staticpro (&Quser_size);
11903 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11904 staticpro (&Qscroll_bar_foreground);
11905 Qscroll_bar_background = intern ("scroll-bar-background");
11906 staticpro (&Qscroll_bar_background);
11907 Qscreen_gamma = intern ("screen-gamma");
11908 staticpro (&Qscreen_gamma);
11909 Qline_spacing = intern ("line-spacing");
11910 staticpro (&Qline_spacing);
11911 Qcenter = intern ("center");
11912 staticpro (&Qcenter);
11913 Qcompound_text = intern ("compound-text");
11914 staticpro (&Qcompound_text);
11915 Qcancel_timer = intern ("cancel-timer");
11916 staticpro (&Qcancel_timer);
11917 Qwait_for_wm = intern ("wait-for-wm");
11918 staticpro (&Qwait_for_wm);
11919 Qfullscreen = intern ("fullscreen");
11920 staticpro (&Qfullscreen);
11921 Qfullwidth = intern ("fullwidth");
11922 staticpro (&Qfullwidth);
11923 Qfullheight = intern ("fullheight");
11924 staticpro (&Qfullheight);
11925 Qfullboth = intern ("fullboth");
11926 staticpro (&Qfullboth);
11927 /* This is the end of symbol initialization. */
11929 /* Text property `display' should be nonsticky by default. */
11930 Vtext_property_default_nonsticky
11931 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11934 Qlaplace = intern ("laplace");
11935 staticpro (&Qlaplace);
11936 Qemboss = intern ("emboss");
11937 staticpro (&Qemboss);
11938 Qedge_detection = intern ("edge-detection");
11939 staticpro (&Qedge_detection);
11940 Qheuristic = intern ("heuristic");
11941 staticpro (&Qheuristic);
11942 QCmatrix = intern (":matrix");
11943 staticpro (&QCmatrix);
11944 QCcolor_adjustment = intern (":color-adjustment");
11945 staticpro (&QCcolor_adjustment);
11946 QCmask = intern (":mask");
11947 staticpro (&QCmask);
11949 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11950 staticpro (&Qface_set_after_frame_default);
11952 Fput (Qundefined_color, Qerror_conditions,
11953 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11954 Fput (Qundefined_color, Qerror_message,
11955 build_string ("Undefined color"));
11957 init_x_parm_symbols ();
11959 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11960 doc: /* Non-nil means always draw a cross over disabled images.
11961 Disabled images are those having an `:conversion disabled' property.
11962 A cross is always drawn on black & white displays. */);
11963 cross_disabled_images = 0;
11965 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11966 doc: /* List of directories to search for bitmap files for X. */);
11967 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11969 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11970 doc: /* The shape of the pointer when over text.
11971 Changing the value does not affect existing frames
11972 unless you set the mouse color. */);
11973 Vx_pointer_shape = Qnil;
11975 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11976 doc: /* The name Emacs uses to look up X resources.
11977 `x-get-resource' uses this as the first component of the instance name
11978 when requesting resource values.
11979 Emacs initially sets `x-resource-name' to the name under which Emacs
11980 was invoked, or to the value specified with the `-name' or `-rn'
11981 switches, if present.
11983 It may be useful to bind this variable locally around a call
11984 to `x-get-resource'. See also the variable `x-resource-class'. */);
11985 Vx_resource_name = Qnil;
11987 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11988 doc: /* The class Emacs uses to look up X resources.
11989 `x-get-resource' uses this as the first component of the instance class
11990 when requesting resource values.
11992 Emacs initially sets `x-resource-class' to "Emacs".
11994 Setting this variable permanently is not a reasonable thing to do,
11995 but binding this variable locally around a call to `x-get-resource'
11996 is a reasonable practice. See also the variable `x-resource-name'. */);
11997 Vx_resource_class = build_string (EMACS_CLASS);
11999 #if 0 /* This doesn't really do anything. */
12000 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
12001 doc: /* The shape of the pointer when not over text.
12002 This variable takes effect when you create a new frame
12003 or when you set the mouse color. */);
12004 #endif
12005 Vx_nontext_pointer_shape = Qnil;
12007 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
12008 doc: /* The shape of the pointer when Emacs is busy.
12009 This variable takes effect when you create a new frame
12010 or when you set the mouse color. */);
12011 Vx_hourglass_pointer_shape = Qnil;
12013 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
12014 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
12015 display_hourglass_p = 1;
12017 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
12018 doc: /* *Seconds to wait before displaying an hourglass pointer.
12019 Value must be an integer or float. */);
12020 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
12022 #if 0 /* This doesn't really do anything. */
12023 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
12024 doc: /* The shape of the pointer when over the mode line.
12025 This variable takes effect when you create a new frame
12026 or when you set the mouse color. */);
12027 #endif
12028 Vx_mode_pointer_shape = Qnil;
12030 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
12031 &Vx_sensitive_text_pointer_shape,
12032 doc: /* The shape of the pointer when over mouse-sensitive text.
12033 This variable takes effect when you create a new frame
12034 or when you set the mouse color. */);
12035 Vx_sensitive_text_pointer_shape = Qnil;
12037 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
12038 &Vx_window_horizontal_drag_shape,
12039 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
12040 This variable takes effect when you create a new frame
12041 or when you set the mouse color. */);
12042 Vx_window_horizontal_drag_shape = Qnil;
12044 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
12045 doc: /* A string indicating the foreground color of the cursor box. */);
12046 Vx_cursor_fore_pixel = Qnil;
12048 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
12049 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12050 Text larger than this is clipped. */);
12051 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
12053 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
12054 doc: /* Non-nil if no X window manager is in use.
12055 Emacs doesn't try to figure this out; this is always nil
12056 unless you set it to something else. */);
12057 /* We don't have any way to find this out, so set it to nil
12058 and maybe the user would like to set it to t. */
12059 Vx_no_window_manager = Qnil;
12061 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12062 &Vx_pixel_size_width_font_regexp,
12063 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12065 Since Emacs gets width of a font matching with this regexp from
12066 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12067 such a font. This is especially effective for such large fonts as
12068 Chinese, Japanese, and Korean. */);
12069 Vx_pixel_size_width_font_regexp = Qnil;
12071 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
12072 doc: /* Time after which cached images are removed from the cache.
12073 When an image has not been displayed this many seconds, remove it
12074 from the image cache. Value must be an integer or nil with nil
12075 meaning don't clear the cache. */);
12076 Vimage_cache_eviction_delay = make_number (30 * 60);
12078 #ifdef USE_X_TOOLKIT
12079 Fprovide (intern ("x-toolkit"), Qnil);
12080 #ifdef USE_MOTIF
12081 Fprovide (intern ("motif"), Qnil);
12083 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
12084 doc: /* Version info for LessTif/Motif. */);
12085 Vmotif_version_string = build_string (XmVERSION_STRING);
12086 #endif /* USE_MOTIF */
12087 #endif /* USE_X_TOOLKIT */
12089 defsubr (&Sx_get_resource);
12091 /* X window properties. */
12092 defsubr (&Sx_change_window_property);
12093 defsubr (&Sx_delete_window_property);
12094 defsubr (&Sx_window_property);
12096 defsubr (&Sxw_display_color_p);
12097 defsubr (&Sx_display_grayscale_p);
12098 defsubr (&Sxw_color_defined_p);
12099 defsubr (&Sxw_color_values);
12100 defsubr (&Sx_server_max_request_size);
12101 defsubr (&Sx_server_vendor);
12102 defsubr (&Sx_server_version);
12103 defsubr (&Sx_display_pixel_width);
12104 defsubr (&Sx_display_pixel_height);
12105 defsubr (&Sx_display_mm_width);
12106 defsubr (&Sx_display_mm_height);
12107 defsubr (&Sx_display_screens);
12108 defsubr (&Sx_display_planes);
12109 defsubr (&Sx_display_color_cells);
12110 defsubr (&Sx_display_visual_class);
12111 defsubr (&Sx_display_backing_store);
12112 defsubr (&Sx_display_save_under);
12113 defsubr (&Sx_parse_geometry);
12114 defsubr (&Sx_create_frame);
12115 defsubr (&Sx_open_connection);
12116 defsubr (&Sx_close_connection);
12117 defsubr (&Sx_display_list);
12118 defsubr (&Sx_synchronize);
12119 defsubr (&Sx_focus_frame);
12120 defsubr (&Sx_backspace_delete_keys_p);
12122 /* Setting callback functions for fontset handler. */
12123 get_font_info_func = x_get_font_info;
12125 #if 0 /* This function pointer doesn't seem to be used anywhere.
12126 And the pointer assigned has the wrong type, anyway. */
12127 list_fonts_func = x_list_fonts;
12128 #endif
12130 load_font_func = x_load_font;
12131 find_ccl_program_func = x_find_ccl_program;
12132 query_font_func = x_query_font;
12133 set_frame_fontset_func = x_set_font;
12134 check_window_system_func = check_x;
12136 /* Images. */
12137 Qxbm = intern ("xbm");
12138 staticpro (&Qxbm);
12139 QCconversion = intern (":conversion");
12140 staticpro (&QCconversion);
12141 QCheuristic_mask = intern (":heuristic-mask");
12142 staticpro (&QCheuristic_mask);
12143 QCcolor_symbols = intern (":color-symbols");
12144 staticpro (&QCcolor_symbols);
12145 QCascent = intern (":ascent");
12146 staticpro (&QCascent);
12147 QCmargin = intern (":margin");
12148 staticpro (&QCmargin);
12149 QCrelief = intern (":relief");
12150 staticpro (&QCrelief);
12151 Qpostscript = intern ("postscript");
12152 staticpro (&Qpostscript);
12153 QCloader = intern (":loader");
12154 staticpro (&QCloader);
12155 QCbounding_box = intern (":bounding-box");
12156 staticpro (&QCbounding_box);
12157 QCpt_width = intern (":pt-width");
12158 staticpro (&QCpt_width);
12159 QCpt_height = intern (":pt-height");
12160 staticpro (&QCpt_height);
12161 QCindex = intern (":index");
12162 staticpro (&QCindex);
12163 Qpbm = intern ("pbm");
12164 staticpro (&Qpbm);
12166 #if HAVE_XPM
12167 Qxpm = intern ("xpm");
12168 staticpro (&Qxpm);
12169 #endif
12171 #if HAVE_JPEG
12172 Qjpeg = intern ("jpeg");
12173 staticpro (&Qjpeg);
12174 #endif
12176 #if HAVE_TIFF
12177 Qtiff = intern ("tiff");
12178 staticpro (&Qtiff);
12179 #endif
12181 #if HAVE_GIF
12182 Qgif = intern ("gif");
12183 staticpro (&Qgif);
12184 #endif
12186 #if HAVE_PNG
12187 Qpng = intern ("png");
12188 staticpro (&Qpng);
12189 #endif
12191 defsubr (&Sclear_image_cache);
12192 defsubr (&Simage_size);
12193 defsubr (&Simage_mask_p);
12195 hourglass_atimer = NULL;
12196 hourglass_shown_p = 0;
12198 defsubr (&Sx_show_tip);
12199 defsubr (&Sx_hide_tip);
12200 tip_timer = Qnil;
12201 staticpro (&tip_timer);
12202 tip_frame = Qnil;
12203 staticpro (&tip_frame);
12205 last_show_tip_args = Qnil;
12206 staticpro (&last_show_tip_args);
12208 #ifdef USE_MOTIF
12209 defsubr (&Sx_file_dialog);
12210 #endif
12214 void
12215 init_xfns ()
12217 image_types = NULL;
12218 Vimage_types = Qnil;
12220 define_image_type (&xbm_type);
12221 define_image_type (&gs_type);
12222 define_image_type (&pbm_type);
12224 #if HAVE_XPM
12225 define_image_type (&xpm_type);
12226 #endif
12228 #if HAVE_JPEG
12229 define_image_type (&jpeg_type);
12230 #endif
12232 #if HAVE_TIFF
12233 define_image_type (&tiff_type);
12234 #endif
12236 #if HAVE_GIF
12237 define_image_type (&gif_type);
12238 #endif
12240 #if HAVE_PNG
12241 define_image_type (&png_type);
12242 #endif
12245 #endif /* HAVE_X_WINDOWS */