(find-composition): Check if (char-after POS)
[emacs.git] / src / xfns.c
blobd26ce6466fe4af7f8bca16fed31ebd7a6b9c9977
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 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include <epaths.h>
41 #include "charset.h"
42 #include "coding.h"
43 #include "fontset.h"
44 #include "systime.h"
45 #include "termhooks.h"
46 #include "atimer.h"
48 #ifdef HAVE_X_WINDOWS
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
54 #ifndef VMS
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
57 #else
58 #include <X11/bitmaps/gray>
59 #endif
60 #else
61 #include "[.bitmaps]gray.xbm"
62 #endif
64 #ifdef USE_X_TOOLKIT
65 #include <X11/Shell.h>
67 #ifndef USE_MOTIF
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
72 #ifdef USG
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
74 #include <X11/Xos.h>
75 #define USG
76 #else
77 #include <X11/Xos.h>
78 #endif
80 #include "widget.h"
82 #include "../lwlib/lwlib.h"
84 #ifdef USE_MOTIF
85 #include <Xm/Xm.h>
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
88 #endif
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
94 #define HACK_EDITRES
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick;
102 #ifdef USE_LUCID
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct *xlwmenu_default_font;
105 #endif
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #ifdef USE_MOTIF
112 /* LessTif/Motif version info. */
114 static Lisp_Object Vmotif_version_string;
116 #endif /* USE_MOTIF */
118 #endif /* USE_X_TOOLKIT */
120 #define min(a,b) ((a) < (b) ? (a) : (b))
121 #define max(a,b) ((a) > (b) ? (a) : (b))
123 #ifdef HAVE_X11R4
124 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
125 #else
126 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
127 #endif
129 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
130 it, and including `bitmaps/gray' more than once is a problem when
131 config.h defines `static' as an empty replacement string. */
133 int gray_bitmap_width = gray_width;
134 int gray_bitmap_height = gray_height;
135 char *gray_bitmap_bits = gray_bits;
137 /* The name we're using in resource queries. Most often "emacs". */
139 Lisp_Object Vx_resource_name;
141 /* The application class we're using in resource queries.
142 Normally "Emacs". */
144 Lisp_Object Vx_resource_class;
146 /* Non-zero means we're allowed to display an hourglass cursor. */
148 int display_hourglass_p;
150 /* The background and shape of the mouse pointer, and shape when not
151 over text or in the modeline. */
153 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
154 Lisp_Object Vx_hourglass_pointer_shape;
156 /* The shape when over mouse-sensitive text. */
158 Lisp_Object Vx_sensitive_text_pointer_shape;
160 /* If non-nil, the pointer shape to indicate that windows can be
161 dragged horizontally. */
163 Lisp_Object Vx_window_horizontal_drag_shape;
165 /* Color of chars displayed in cursor box. */
167 Lisp_Object Vx_cursor_fore_pixel;
169 /* Nonzero if using X. */
171 static int x_in_use;
173 /* Non nil if no window manager is in use. */
175 Lisp_Object Vx_no_window_manager;
177 /* Search path for bitmap files. */
179 Lisp_Object Vx_bitmap_file_path;
181 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
183 Lisp_Object Vx_pixel_size_width_font_regexp;
185 Lisp_Object Qauto_raise;
186 Lisp_Object Qauto_lower;
187 Lisp_Object Qbar;
188 Lisp_Object Qborder_color;
189 Lisp_Object Qborder_width;
190 Lisp_Object Qbox;
191 Lisp_Object Qcursor_color;
192 Lisp_Object Qcursor_type;
193 Lisp_Object Qgeometry;
194 Lisp_Object Qicon_left;
195 Lisp_Object Qicon_top;
196 Lisp_Object Qicon_type;
197 Lisp_Object Qicon_name;
198 Lisp_Object Qinternal_border_width;
199 Lisp_Object Qleft;
200 Lisp_Object Qright;
201 Lisp_Object Qmouse_color;
202 Lisp_Object Qnone;
203 Lisp_Object Qouter_window_id;
204 Lisp_Object Qparent_id;
205 Lisp_Object Qscroll_bar_width;
206 Lisp_Object Qsuppress_icon;
207 extern Lisp_Object Qtop;
208 Lisp_Object Qundefined_color;
209 Lisp_Object Qvertical_scroll_bars;
210 Lisp_Object Qvisibility;
211 Lisp_Object Qwindow_id;
212 Lisp_Object Qx_frame_parameter;
213 Lisp_Object Qx_resource_name;
214 Lisp_Object Quser_position;
215 Lisp_Object Quser_size;
216 extern Lisp_Object Qdisplay;
217 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
218 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
219 Lisp_Object Qcompound_text, Qcancel_timer;
220 Lisp_Object Qwait_for_wm;
222 /* The below are defined in frame.c. */
224 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
225 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
226 extern Lisp_Object Qtool_bar_lines;
228 extern Lisp_Object Vwindow_system_version;
230 Lisp_Object Qface_set_after_frame_default;
232 #if GLYPH_DEBUG
233 int image_cache_refcount, dpyinfo_refcount;
234 #endif
238 /* Error if we are not connected to X. */
240 void
241 check_x ()
243 if (! x_in_use)
244 error ("X windows are not in use or not initialized");
247 /* Nonzero if we can use mouse menus.
248 You should not call this unless HAVE_MENUS is defined. */
251 have_menus_p ()
253 return x_in_use;
256 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
257 and checking validity for X. */
259 FRAME_PTR
260 check_x_frame (frame)
261 Lisp_Object frame;
263 FRAME_PTR f;
265 if (NILP (frame))
266 frame = selected_frame;
267 CHECK_LIVE_FRAME (frame, 0);
268 f = XFRAME (frame);
269 if (! FRAME_X_P (f))
270 error ("Non-X frame used");
271 return f;
274 /* Let the user specify an X display with a frame.
275 nil stands for the selected frame--or, if that is not an X frame,
276 the first X display on the list. */
278 static struct x_display_info *
279 check_x_display_info (frame)
280 Lisp_Object frame;
282 struct x_display_info *dpyinfo = NULL;
284 if (NILP (frame))
286 struct frame *sf = XFRAME (selected_frame);
288 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
289 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
290 else if (x_display_list != 0)
291 dpyinfo = x_display_list;
292 else
293 error ("X windows are not in use or not initialized");
295 else if (STRINGP (frame))
296 dpyinfo = x_display_info_for_name (frame);
297 else
299 FRAME_PTR f;
301 CHECK_LIVE_FRAME (frame, 0);
302 f = XFRAME (frame);
303 if (! FRAME_X_P (f))
304 error ("Non-X frame used");
305 dpyinfo = FRAME_X_DISPLAY_INFO (f);
308 return dpyinfo;
312 /* Return the Emacs frame-object corresponding to an X window.
313 It could be the frame's main window or an icon window. */
315 /* This function can be called during GC, so use GC_xxx type test macros. */
317 struct frame *
318 x_window_to_frame (dpyinfo, wdesc)
319 struct x_display_info *dpyinfo;
320 int wdesc;
322 Lisp_Object tail, frame;
323 struct frame *f;
325 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
327 frame = XCAR (tail);
328 if (!GC_FRAMEP (frame))
329 continue;
330 f = XFRAME (frame);
331 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
332 continue;
333 if (f->output_data.x->hourglass_window == wdesc)
334 return f;
335 #ifdef USE_X_TOOLKIT
336 if ((f->output_data.x->edit_widget
337 && XtWindow (f->output_data.x->edit_widget) == wdesc)
338 /* A tooltip frame? */
339 || (!f->output_data.x->edit_widget
340 && FRAME_X_WINDOW (f) == wdesc)
341 || f->output_data.x->icon_desc == wdesc)
342 return f;
343 #else /* not USE_X_TOOLKIT */
344 if (FRAME_X_WINDOW (f) == wdesc
345 || f->output_data.x->icon_desc == wdesc)
346 return f;
347 #endif /* not USE_X_TOOLKIT */
349 return 0;
352 #ifdef USE_X_TOOLKIT
353 /* Like x_window_to_frame but also compares the window with the widget's
354 windows. */
356 struct frame *
357 x_any_window_to_frame (dpyinfo, wdesc)
358 struct x_display_info *dpyinfo;
359 int wdesc;
361 Lisp_Object tail, frame;
362 struct frame *f, *found;
363 struct x_output *x;
365 found = NULL;
366 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
368 frame = XCAR (tail);
369 if (!GC_FRAMEP (frame))
370 continue;
372 f = XFRAME (frame);
373 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
375 /* This frame matches if the window is any of its widgets. */
376 x = f->output_data.x;
377 if (x->hourglass_window == wdesc)
378 found = f;
379 else if (x->widget)
381 if (wdesc == XtWindow (x->widget)
382 || wdesc == XtWindow (x->column_widget)
383 || wdesc == XtWindow (x->edit_widget))
384 found = f;
385 /* Match if the window is this frame's menubar. */
386 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
387 found = f;
389 else if (FRAME_X_WINDOW (f) == wdesc)
390 /* A tooltip frame. */
391 found = f;
395 return found;
398 /* Likewise, but exclude the menu bar widget. */
400 struct frame *
401 x_non_menubar_window_to_frame (dpyinfo, wdesc)
402 struct x_display_info *dpyinfo;
403 int wdesc;
405 Lisp_Object tail, frame;
406 struct frame *f;
407 struct x_output *x;
409 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
411 frame = XCAR (tail);
412 if (!GC_FRAMEP (frame))
413 continue;
414 f = XFRAME (frame);
415 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
416 continue;
417 x = f->output_data.x;
418 /* This frame matches if the window is any of its widgets. */
419 if (x->hourglass_window == wdesc)
420 return f;
421 else if (x->widget)
423 if (wdesc == XtWindow (x->widget)
424 || wdesc == XtWindow (x->column_widget)
425 || wdesc == XtWindow (x->edit_widget))
426 return f;
428 else if (FRAME_X_WINDOW (f) == wdesc)
429 /* A tooltip frame. */
430 return f;
432 return 0;
435 /* Likewise, but consider only the menu bar widget. */
437 struct frame *
438 x_menubar_window_to_frame (dpyinfo, wdesc)
439 struct x_display_info *dpyinfo;
440 int wdesc;
442 Lisp_Object tail, frame;
443 struct frame *f;
444 struct x_output *x;
446 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
448 frame = XCAR (tail);
449 if (!GC_FRAMEP (frame))
450 continue;
451 f = XFRAME (frame);
452 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
453 continue;
454 x = f->output_data.x;
455 /* Match if the window is this frame's menubar. */
456 if (x->menubar_widget
457 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
458 return f;
460 return 0;
463 /* Return the frame whose principal (outermost) window is WDESC.
464 If WDESC is some other (smaller) window, we return 0. */
466 struct frame *
467 x_top_window_to_frame (dpyinfo, wdesc)
468 struct x_display_info *dpyinfo;
469 int wdesc;
471 Lisp_Object tail, frame;
472 struct frame *f;
473 struct x_output *x;
475 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
477 frame = XCAR (tail);
478 if (!GC_FRAMEP (frame))
479 continue;
480 f = XFRAME (frame);
481 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
482 continue;
483 x = f->output_data.x;
485 if (x->widget)
487 /* This frame matches if the window is its topmost widget. */
488 if (wdesc == XtWindow (x->widget))
489 return f;
490 #if 0 /* I don't know why it did this,
491 but it seems logically wrong,
492 and it causes trouble for MapNotify events. */
493 /* Match if the window is this frame's menubar. */
494 if (x->menubar_widget
495 && wdesc == XtWindow (x->menubar_widget))
496 return f;
497 #endif
499 else if (FRAME_X_WINDOW (f) == wdesc)
500 /* Tooltip frame. */
501 return f;
503 return 0;
505 #endif /* USE_X_TOOLKIT */
509 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
510 id, which is just an int that this section returns. Bitmaps are
511 reference counted so they can be shared among frames.
513 Bitmap indices are guaranteed to be > 0, so a negative number can
514 be used to indicate no bitmap.
516 If you use x_create_bitmap_from_data, then you must keep track of
517 the bitmaps yourself. That is, creating a bitmap from the same
518 data more than once will not be caught. */
521 /* Functions to access the contents of a bitmap, given an id. */
524 x_bitmap_height (f, id)
525 FRAME_PTR f;
526 int id;
528 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
532 x_bitmap_width (f, id)
533 FRAME_PTR f;
534 int id;
536 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
540 x_bitmap_pixmap (f, id)
541 FRAME_PTR f;
542 int id;
544 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
548 /* Allocate a new bitmap record. Returns index of new record. */
550 static int
551 x_allocate_bitmap_record (f)
552 FRAME_PTR f;
554 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
555 int i;
557 if (dpyinfo->bitmaps == NULL)
559 dpyinfo->bitmaps_size = 10;
560 dpyinfo->bitmaps
561 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
562 dpyinfo->bitmaps_last = 1;
563 return 1;
566 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
567 return ++dpyinfo->bitmaps_last;
569 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
570 if (dpyinfo->bitmaps[i].refcount == 0)
571 return i + 1;
573 dpyinfo->bitmaps_size *= 2;
574 dpyinfo->bitmaps
575 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
576 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
577 return ++dpyinfo->bitmaps_last;
580 /* Add one reference to the reference count of the bitmap with id ID. */
582 void
583 x_reference_bitmap (f, id)
584 FRAME_PTR f;
585 int id;
587 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
590 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
593 x_create_bitmap_from_data (f, bits, width, height)
594 struct frame *f;
595 char *bits;
596 unsigned int width, height;
598 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
599 Pixmap bitmap;
600 int id;
602 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
603 bits, width, height);
605 if (! bitmap)
606 return -1;
608 id = x_allocate_bitmap_record (f);
609 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
610 dpyinfo->bitmaps[id - 1].file = NULL;
611 dpyinfo->bitmaps[id - 1].refcount = 1;
612 dpyinfo->bitmaps[id - 1].depth = 1;
613 dpyinfo->bitmaps[id - 1].height = height;
614 dpyinfo->bitmaps[id - 1].width = width;
616 return id;
619 /* Create bitmap from file FILE for frame F. */
622 x_create_bitmap_from_file (f, file)
623 struct frame *f;
624 Lisp_Object file;
626 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
627 unsigned int width, height;
628 Pixmap bitmap;
629 int xhot, yhot, result, id;
630 Lisp_Object found;
631 int fd;
632 char *filename;
634 /* Look for an existing bitmap with the same name. */
635 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
637 if (dpyinfo->bitmaps[id].refcount
638 && dpyinfo->bitmaps[id].file
639 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
641 ++dpyinfo->bitmaps[id].refcount;
642 return id + 1;
646 /* Search bitmap-file-path for the file, if appropriate. */
647 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
648 if (fd < 0)
649 return -1;
650 emacs_close (fd);
652 filename = (char *) XSTRING (found)->data;
654 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
655 filename, &width, &height, &bitmap, &xhot, &yhot);
656 if (result != BitmapSuccess)
657 return -1;
659 id = x_allocate_bitmap_record (f);
660 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
661 dpyinfo->bitmaps[id - 1].refcount = 1;
662 dpyinfo->bitmaps[id - 1].file
663 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
664 dpyinfo->bitmaps[id - 1].depth = 1;
665 dpyinfo->bitmaps[id - 1].height = height;
666 dpyinfo->bitmaps[id - 1].width = width;
667 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
669 return id;
672 /* Remove reference to bitmap with id number ID. */
674 void
675 x_destroy_bitmap (f, id)
676 FRAME_PTR f;
677 int id;
679 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
681 if (id > 0)
683 --dpyinfo->bitmaps[id - 1].refcount;
684 if (dpyinfo->bitmaps[id - 1].refcount == 0)
686 BLOCK_INPUT;
687 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
688 if (dpyinfo->bitmaps[id - 1].file)
690 xfree (dpyinfo->bitmaps[id - 1].file);
691 dpyinfo->bitmaps[id - 1].file = NULL;
693 UNBLOCK_INPUT;
698 /* Free all the bitmaps for the display specified by DPYINFO. */
700 static void
701 x_destroy_all_bitmaps (dpyinfo)
702 struct x_display_info *dpyinfo;
704 int i;
705 for (i = 0; i < dpyinfo->bitmaps_last; i++)
706 if (dpyinfo->bitmaps[i].refcount > 0)
708 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
709 if (dpyinfo->bitmaps[i].file)
710 xfree (dpyinfo->bitmaps[i].file);
712 dpyinfo->bitmaps_last = 0;
715 /* Connect the frame-parameter names for X frames
716 to the ways of passing the parameter values to the window system.
718 The name of a parameter, as a Lisp symbol,
719 has an `x-frame-parameter' property which is an integer in Lisp
720 that is an index in this table. */
722 struct x_frame_parm_table
724 char *name;
725 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
728 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
729 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
730 static void x_change_window_heights P_ ((Lisp_Object, int));
731 static void x_disable_image P_ ((struct frame *, struct image *));
732 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
733 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
734 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
735 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
736 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
745 Lisp_Object));
746 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
750 Lisp_Object));
751 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
758 Lisp_Object));
759 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
760 Lisp_Object));
761 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
762 Lisp_Object,
763 Lisp_Object,
764 char *, char *,
765 int));
766 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
767 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
768 Lisp_Object));
769 static void init_color_table P_ ((void));
770 static void free_color_table P_ ((void));
771 static unsigned long *colors_in_color_table P_ ((int *n));
772 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
773 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
777 static struct x_frame_parm_table x_frame_parms[] =
779 "auto-raise", x_set_autoraise,
780 "auto-lower", x_set_autolower,
781 "background-color", x_set_background_color,
782 "border-color", x_set_border_color,
783 "border-width", x_set_border_width,
784 "cursor-color", x_set_cursor_color,
785 "cursor-type", x_set_cursor_type,
786 "font", x_set_font,
787 "foreground-color", x_set_foreground_color,
788 "icon-name", x_set_icon_name,
789 "icon-type", x_set_icon_type,
790 "internal-border-width", x_set_internal_border_width,
791 "menu-bar-lines", x_set_menu_bar_lines,
792 "mouse-color", x_set_mouse_color,
793 "name", x_explicitly_set_name,
794 "scroll-bar-width", x_set_scroll_bar_width,
795 "title", x_set_title,
796 "unsplittable", x_set_unsplittable,
797 "vertical-scroll-bars", x_set_vertical_scroll_bars,
798 "visibility", x_set_visibility,
799 "tool-bar-lines", x_set_tool_bar_lines,
800 "scroll-bar-foreground", x_set_scroll_bar_foreground,
801 "scroll-bar-background", x_set_scroll_bar_background,
802 "screen-gamma", x_set_screen_gamma,
803 "line-spacing", x_set_line_spacing,
804 "wait-for-wm", x_set_wait_for_wm
807 /* Attach the `x-frame-parameter' properties to
808 the Lisp symbol names of parameters relevant to X. */
810 void
811 init_x_parm_symbols ()
813 int i;
815 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
816 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
817 make_number (i));
820 /* Change the parameters of frame F as specified by ALIST.
821 If a parameter is not specially recognized, do nothing special;
822 otherwise call the `x_set_...' function for that parameter.
823 Except for certain geometry properties, always call store_frame_param
824 to store the new value in the parameter alist. */
826 void
827 x_set_frame_parameters (f, alist)
828 FRAME_PTR f;
829 Lisp_Object alist;
831 Lisp_Object tail;
833 /* If both of these parameters are present, it's more efficient to
834 set them both at once. So we wait until we've looked at the
835 entire list before we set them. */
836 int width, height;
838 /* Same here. */
839 Lisp_Object left, top;
841 /* Same with these. */
842 Lisp_Object icon_left, icon_top;
844 /* Record in these vectors all the parms specified. */
845 Lisp_Object *parms;
846 Lisp_Object *values;
847 int i, p;
848 int left_no_change = 0, top_no_change = 0;
849 int icon_left_no_change = 0, icon_top_no_change = 0;
851 struct gcpro gcpro1, gcpro2;
853 i = 0;
854 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
855 i++;
857 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
858 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
860 /* Extract parm names and values into those vectors. */
862 i = 0;
863 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
865 Lisp_Object elt;
867 elt = Fcar (tail);
868 parms[i] = Fcar (elt);
869 values[i] = Fcdr (elt);
870 i++;
872 /* TAIL and ALIST are not used again below here. */
873 alist = tail = Qnil;
875 GCPRO2 (*parms, *values);
876 gcpro1.nvars = i;
877 gcpro2.nvars = i;
879 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
880 because their values appear in VALUES and strings are not valid. */
881 top = left = Qunbound;
882 icon_left = icon_top = Qunbound;
884 /* Provide default values for HEIGHT and WIDTH. */
885 if (FRAME_NEW_WIDTH (f))
886 width = FRAME_NEW_WIDTH (f);
887 else
888 width = FRAME_WIDTH (f);
890 if (FRAME_NEW_HEIGHT (f))
891 height = FRAME_NEW_HEIGHT (f);
892 else
893 height = FRAME_HEIGHT (f);
895 /* Process foreground_color and background_color before anything else.
896 They are independent of other properties, but other properties (e.g.,
897 cursor_color) are dependent upon them. */
898 for (p = 0; p < i; p++)
900 Lisp_Object prop, val;
902 prop = parms[p];
903 val = values[p];
904 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
906 register Lisp_Object param_index, old_value;
908 param_index = Fget (prop, Qx_frame_parameter);
909 old_value = get_frame_param (f, prop);
910 store_frame_param (f, prop, val);
911 if (NATNUMP (param_index)
912 && (XFASTINT (param_index)
913 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
914 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
918 /* Now process them in reverse of specified order. */
919 for (i--; i >= 0; i--)
921 Lisp_Object prop, val;
923 prop = parms[i];
924 val = values[i];
926 if (EQ (prop, Qwidth) && NUMBERP (val))
927 width = XFASTINT (val);
928 else if (EQ (prop, Qheight) && NUMBERP (val))
929 height = XFASTINT (val);
930 else if (EQ (prop, Qtop))
931 top = val;
932 else if (EQ (prop, Qleft))
933 left = val;
934 else if (EQ (prop, Qicon_top))
935 icon_top = val;
936 else if (EQ (prop, Qicon_left))
937 icon_left = val;
938 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
939 /* Processed above. */
940 continue;
941 else
943 register Lisp_Object param_index, old_value;
945 param_index = Fget (prop, Qx_frame_parameter);
946 old_value = get_frame_param (f, prop);
947 store_frame_param (f, prop, val);
948 if (NATNUMP (param_index)
949 && (XFASTINT (param_index)
950 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
951 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
955 /* Don't die if just one of these was set. */
956 if (EQ (left, Qunbound))
958 left_no_change = 1;
959 if (f->output_data.x->left_pos < 0)
960 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
961 else
962 XSETINT (left, f->output_data.x->left_pos);
964 if (EQ (top, Qunbound))
966 top_no_change = 1;
967 if (f->output_data.x->top_pos < 0)
968 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
969 else
970 XSETINT (top, f->output_data.x->top_pos);
973 /* If one of the icon positions was not set, preserve or default it. */
974 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
976 icon_left_no_change = 1;
977 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
978 if (NILP (icon_left))
979 XSETINT (icon_left, 0);
981 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
983 icon_top_no_change = 1;
984 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
985 if (NILP (icon_top))
986 XSETINT (icon_top, 0);
989 /* Don't set these parameters unless they've been explicitly
990 specified. The window might be mapped or resized while we're in
991 this function, and we don't want to override that unless the lisp
992 code has asked for it.
994 Don't set these parameters unless they actually differ from the
995 window's current parameters; the window may not actually exist
996 yet. */
998 Lisp_Object frame;
1000 check_frame_size (f, &height, &width);
1002 XSETFRAME (frame, f);
1004 if (width != FRAME_WIDTH (f)
1005 || height != FRAME_HEIGHT (f)
1006 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1007 Fset_frame_size (frame, make_number (width), make_number (height));
1009 if ((!NILP (left) || !NILP (top))
1010 && ! (left_no_change && top_no_change)
1011 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1012 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1014 int leftpos = 0;
1015 int toppos = 0;
1017 /* Record the signs. */
1018 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1019 if (EQ (left, Qminus))
1020 f->output_data.x->size_hint_flags |= XNegative;
1021 else if (INTEGERP (left))
1023 leftpos = XINT (left);
1024 if (leftpos < 0)
1025 f->output_data.x->size_hint_flags |= XNegative;
1027 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1028 && CONSP (XCDR (left))
1029 && INTEGERP (XCAR (XCDR (left))))
1031 leftpos = - XINT (XCAR (XCDR (left)));
1032 f->output_data.x->size_hint_flags |= XNegative;
1034 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1035 && CONSP (XCDR (left))
1036 && INTEGERP (XCAR (XCDR (left))))
1038 leftpos = XINT (XCAR (XCDR (left)));
1041 if (EQ (top, Qminus))
1042 f->output_data.x->size_hint_flags |= YNegative;
1043 else if (INTEGERP (top))
1045 toppos = XINT (top);
1046 if (toppos < 0)
1047 f->output_data.x->size_hint_flags |= YNegative;
1049 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1050 && CONSP (XCDR (top))
1051 && INTEGERP (XCAR (XCDR (top))))
1053 toppos = - XINT (XCAR (XCDR (top)));
1054 f->output_data.x->size_hint_flags |= YNegative;
1056 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1057 && CONSP (XCDR (top))
1058 && INTEGERP (XCAR (XCDR (top))))
1060 toppos = XINT (XCAR (XCDR (top)));
1064 /* Store the numeric value of the position. */
1065 f->output_data.x->top_pos = toppos;
1066 f->output_data.x->left_pos = leftpos;
1068 f->output_data.x->win_gravity = NorthWestGravity;
1070 /* Actually set that position, and convert to absolute. */
1071 x_set_offset (f, leftpos, toppos, -1);
1074 if ((!NILP (icon_left) || !NILP (icon_top))
1075 && ! (icon_left_no_change && icon_top_no_change))
1076 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1079 UNGCPRO;
1082 /* Store the screen positions of frame F into XPTR and YPTR.
1083 These are the positions of the containing window manager window,
1084 not Emacs's own window. */
1086 void
1087 x_real_positions (f, xptr, yptr)
1088 FRAME_PTR f;
1089 int *xptr, *yptr;
1091 int win_x, win_y;
1092 Window child;
1094 /* This is pretty gross, but seems to be the easiest way out of
1095 the problem that arises when restarting window-managers. */
1097 #ifdef USE_X_TOOLKIT
1098 Window outer = (f->output_data.x->widget
1099 ? XtWindow (f->output_data.x->widget)
1100 : FRAME_X_WINDOW (f));
1101 #else
1102 Window outer = f->output_data.x->window_desc;
1103 #endif
1104 Window tmp_root_window;
1105 Window *tmp_children;
1106 unsigned int tmp_nchildren;
1108 while (1)
1110 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1111 Window outer_window;
1113 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1114 &f->output_data.x->parent_desc,
1115 &tmp_children, &tmp_nchildren);
1116 XFree ((char *) tmp_children);
1118 win_x = win_y = 0;
1120 /* Find the position of the outside upper-left corner of
1121 the inner window, with respect to the outer window. */
1122 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1123 outer_window = f->output_data.x->parent_desc;
1124 else
1125 outer_window = outer;
1127 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1129 /* From-window, to-window. */
1130 outer_window,
1131 FRAME_X_DISPLAY_INFO (f)->root_window,
1133 /* From-position, to-position. */
1134 0, 0, &win_x, &win_y,
1136 /* Child of win. */
1137 &child);
1139 /* It is possible for the window returned by the XQueryNotify
1140 to become invalid by the time we call XTranslateCoordinates.
1141 That can happen when you restart some window managers.
1142 If so, we get an error in XTranslateCoordinates.
1143 Detect that and try the whole thing over. */
1144 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1146 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1147 break;
1150 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1153 *xptr = win_x;
1154 *yptr = win_y;
1157 /* Insert a description of internally-recorded parameters of frame X
1158 into the parameter alist *ALISTPTR that is to be given to the user.
1159 Only parameters that are specific to the X window system
1160 and whose values are not correctly recorded in the frame's
1161 param_alist need to be considered here. */
1163 void
1164 x_report_frame_params (f, alistptr)
1165 struct frame *f;
1166 Lisp_Object *alistptr;
1168 char buf[16];
1169 Lisp_Object tem;
1171 /* Represent negative positions (off the top or left screen edge)
1172 in a way that Fmodify_frame_parameters will understand correctly. */
1173 XSETINT (tem, f->output_data.x->left_pos);
1174 if (f->output_data.x->left_pos >= 0)
1175 store_in_alist (alistptr, Qleft, tem);
1176 else
1177 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1179 XSETINT (tem, f->output_data.x->top_pos);
1180 if (f->output_data.x->top_pos >= 0)
1181 store_in_alist (alistptr, Qtop, tem);
1182 else
1183 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1185 store_in_alist (alistptr, Qborder_width,
1186 make_number (f->output_data.x->border_width));
1187 store_in_alist (alistptr, Qinternal_border_width,
1188 make_number (f->output_data.x->internal_border_width));
1189 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1190 store_in_alist (alistptr, Qwindow_id,
1191 build_string (buf));
1192 #ifdef USE_X_TOOLKIT
1193 /* Tooltip frame may not have this widget. */
1194 if (f->output_data.x->widget)
1195 #endif
1196 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1197 store_in_alist (alistptr, Qouter_window_id,
1198 build_string (buf));
1199 store_in_alist (alistptr, Qicon_name, f->icon_name);
1200 FRAME_SAMPLE_VISIBILITY (f);
1201 store_in_alist (alistptr, Qvisibility,
1202 (FRAME_VISIBLE_P (f) ? Qt
1203 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1204 store_in_alist (alistptr, Qdisplay,
1205 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1207 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1208 tem = Qnil;
1209 else
1210 XSETFASTINT (tem, f->output_data.x->parent_desc);
1211 store_in_alist (alistptr, Qparent_id, tem);
1216 /* Gamma-correct COLOR on frame F. */
1218 void
1219 gamma_correct (f, color)
1220 struct frame *f;
1221 XColor *color;
1223 if (f->gamma)
1225 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1226 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1227 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1232 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1233 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1234 allocate the color. Value is zero if COLOR_NAME is invalid, or
1235 no color could be allocated. */
1238 x_defined_color (f, color_name, color, alloc_p)
1239 struct frame *f;
1240 char *color_name;
1241 XColor *color;
1242 int alloc_p;
1244 int success_p;
1245 Display *dpy = FRAME_X_DISPLAY (f);
1246 Colormap cmap = FRAME_X_COLORMAP (f);
1248 BLOCK_INPUT;
1249 success_p = XParseColor (dpy, cmap, color_name, color);
1250 if (success_p && alloc_p)
1251 success_p = x_alloc_nearest_color (f, cmap, color);
1252 UNBLOCK_INPUT;
1254 return success_p;
1258 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1259 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1260 Signal an error if color can't be allocated. */
1263 x_decode_color (f, color_name, mono_color)
1264 FRAME_PTR f;
1265 Lisp_Object color_name;
1266 int mono_color;
1268 XColor cdef;
1270 CHECK_STRING (color_name, 0);
1272 #if 0 /* Don't do this. It's wrong when we're not using the default
1273 colormap, it makes freeing difficult, and it's probably not
1274 an important optimization. */
1275 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1276 return BLACK_PIX_DEFAULT (f);
1277 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1278 return WHITE_PIX_DEFAULT (f);
1279 #endif
1281 /* Return MONO_COLOR for monochrome frames. */
1282 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1283 return mono_color;
1285 /* x_defined_color is responsible for coping with failures
1286 by looking for a near-miss. */
1287 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1288 return cdef.pixel;
1290 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1291 Fcons (color_name, Qnil)));
1292 return 0;
1297 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1298 the previous value of that parameter, NEW_VALUE is the new value. */
1300 static void
1301 x_set_line_spacing (f, new_value, old_value)
1302 struct frame *f;
1303 Lisp_Object new_value, old_value;
1305 if (NILP (new_value))
1306 f->extra_line_spacing = 0;
1307 else if (NATNUMP (new_value))
1308 f->extra_line_spacing = XFASTINT (new_value);
1309 else
1310 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1311 Fcons (new_value, Qnil)));
1312 if (FRAME_VISIBLE_P (f))
1313 redraw_frame (f);
1317 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1318 the previous value of that parameter, NEW_VALUE is the new value.
1319 See also the comment of wait_for_wm in struct x_output. */
1321 static void
1322 x_set_wait_for_wm (f, new_value, old_value)
1323 struct frame *f;
1324 Lisp_Object new_value, old_value;
1326 f->output_data.x->wait_for_wm = !NILP (new_value);
1330 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1331 the previous value of that parameter, NEW_VALUE is the new
1332 value. */
1334 static void
1335 x_set_screen_gamma (f, new_value, old_value)
1336 struct frame *f;
1337 Lisp_Object new_value, old_value;
1339 if (NILP (new_value))
1340 f->gamma = 0;
1341 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1342 /* The value 0.4545 is the normal viewing gamma. */
1343 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1344 else
1345 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1346 Fcons (new_value, Qnil)));
1348 clear_face_cache (0);
1352 /* Functions called only from `x_set_frame_param'
1353 to set individual parameters.
1355 If FRAME_X_WINDOW (f) is 0,
1356 the frame is being created and its X-window does not exist yet.
1357 In that case, just record the parameter's new value
1358 in the standard place; do not attempt to change the window. */
1360 void
1361 x_set_foreground_color (f, arg, oldval)
1362 struct frame *f;
1363 Lisp_Object arg, oldval;
1365 struct x_output *x = f->output_data.x;
1366 unsigned long fg, old_fg;
1368 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1369 old_fg = x->foreground_pixel;
1370 x->foreground_pixel = fg;
1372 if (FRAME_X_WINDOW (f) != 0)
1374 Display *dpy = FRAME_X_DISPLAY (f);
1376 BLOCK_INPUT;
1377 XSetForeground (dpy, x->normal_gc, fg);
1378 XSetBackground (dpy, x->reverse_gc, fg);
1380 if (x->cursor_pixel == old_fg)
1382 unload_color (f, x->cursor_pixel);
1383 x->cursor_pixel = x_copy_color (f, fg);
1384 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1387 UNBLOCK_INPUT;
1389 update_face_from_frame_parameter (f, Qforeground_color, arg);
1391 if (FRAME_VISIBLE_P (f))
1392 redraw_frame (f);
1395 unload_color (f, old_fg);
1398 void
1399 x_set_background_color (f, arg, oldval)
1400 struct frame *f;
1401 Lisp_Object arg, oldval;
1403 struct x_output *x = f->output_data.x;
1404 unsigned long bg;
1406 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1407 unload_color (f, x->background_pixel);
1408 x->background_pixel = bg;
1410 if (FRAME_X_WINDOW (f) != 0)
1412 Display *dpy = FRAME_X_DISPLAY (f);
1413 Lisp_Object bar;
1415 BLOCK_INPUT;
1416 XSetBackground (dpy, x->normal_gc, bg);
1417 XSetForeground (dpy, x->reverse_gc, bg);
1418 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1419 XSetForeground (dpy, x->cursor_gc, bg);
1421 for (bar = FRAME_SCROLL_BARS (f);
1422 !NILP (bar);
1423 bar = XSCROLL_BAR (bar)->next)
1425 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1426 XSetWindowBackground (dpy, window, bg);
1429 UNBLOCK_INPUT;
1430 update_face_from_frame_parameter (f, Qbackground_color, arg);
1432 if (FRAME_VISIBLE_P (f))
1433 redraw_frame (f);
1437 void
1438 x_set_mouse_color (f, arg, oldval)
1439 struct frame *f;
1440 Lisp_Object arg, oldval;
1442 struct x_output *x = f->output_data.x;
1443 Display *dpy = FRAME_X_DISPLAY (f);
1444 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1445 Cursor hourglass_cursor, horizontal_drag_cursor;
1446 int count;
1447 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1448 unsigned long mask_color = x->background_pixel;
1450 /* Don't let pointers be invisible. */
1451 if (mask_color == pixel)
1453 x_free_colors (f, &pixel, 1);
1454 pixel = x_copy_color (f, x->foreground_pixel);
1457 unload_color (f, x->mouse_pixel);
1458 x->mouse_pixel = pixel;
1460 BLOCK_INPUT;
1462 /* It's not okay to crash if the user selects a screwy cursor. */
1463 count = x_catch_errors (dpy);
1465 if (!NILP (Vx_pointer_shape))
1467 CHECK_NUMBER (Vx_pointer_shape, 0);
1468 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1470 else
1471 cursor = XCreateFontCursor (dpy, XC_xterm);
1472 x_check_errors (dpy, "bad text pointer cursor: %s");
1474 if (!NILP (Vx_nontext_pointer_shape))
1476 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1477 nontext_cursor
1478 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1480 else
1481 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1482 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1484 if (!NILP (Vx_hourglass_pointer_shape))
1486 CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
1487 hourglass_cursor
1488 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1490 else
1491 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1492 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1494 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1495 if (!NILP (Vx_mode_pointer_shape))
1497 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1498 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1500 else
1501 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1502 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1504 if (!NILP (Vx_sensitive_text_pointer_shape))
1506 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1507 cross_cursor
1508 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1510 else
1511 cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
1513 if (!NILP (Vx_window_horizontal_drag_shape))
1515 CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
1516 horizontal_drag_cursor
1517 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1519 else
1520 horizontal_drag_cursor
1521 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1523 /* Check and report errors with the above calls. */
1524 x_check_errors (dpy, "can't set cursor shape: %s");
1525 x_uncatch_errors (dpy, count);
1528 XColor fore_color, back_color;
1530 fore_color.pixel = x->mouse_pixel;
1531 x_query_color (f, &fore_color);
1532 back_color.pixel = mask_color;
1533 x_query_color (f, &back_color);
1535 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1536 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1537 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1538 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1539 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1540 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1543 if (FRAME_X_WINDOW (f) != 0)
1544 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1546 if (cursor != x->text_cursor
1547 && x->text_cursor != 0)
1548 XFreeCursor (dpy, x->text_cursor);
1549 x->text_cursor = cursor;
1551 if (nontext_cursor != x->nontext_cursor
1552 && x->nontext_cursor != 0)
1553 XFreeCursor (dpy, x->nontext_cursor);
1554 x->nontext_cursor = nontext_cursor;
1556 if (hourglass_cursor != x->hourglass_cursor
1557 && x->hourglass_cursor != 0)
1558 XFreeCursor (dpy, x->hourglass_cursor);
1559 x->hourglass_cursor = hourglass_cursor;
1561 if (mode_cursor != x->modeline_cursor
1562 && x->modeline_cursor != 0)
1563 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1564 x->modeline_cursor = mode_cursor;
1566 if (cross_cursor != x->cross_cursor
1567 && x->cross_cursor != 0)
1568 XFreeCursor (dpy, x->cross_cursor);
1569 x->cross_cursor = cross_cursor;
1571 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1572 && x->horizontal_drag_cursor != 0)
1573 XFreeCursor (dpy, x->horizontal_drag_cursor);
1574 x->horizontal_drag_cursor = horizontal_drag_cursor;
1576 XFlush (dpy);
1577 UNBLOCK_INPUT;
1579 update_face_from_frame_parameter (f, Qmouse_color, arg);
1582 void
1583 x_set_cursor_color (f, arg, oldval)
1584 struct frame *f;
1585 Lisp_Object arg, oldval;
1587 unsigned long fore_pixel, pixel;
1588 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1589 struct x_output *x = f->output_data.x;
1591 if (!NILP (Vx_cursor_fore_pixel))
1593 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1594 WHITE_PIX_DEFAULT (f));
1595 fore_pixel_allocated_p = 1;
1597 else
1598 fore_pixel = x->background_pixel;
1600 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1601 pixel_allocated_p = 1;
1603 /* Make sure that the cursor color differs from the background color. */
1604 if (pixel == x->background_pixel)
1606 if (pixel_allocated_p)
1608 x_free_colors (f, &pixel, 1);
1609 pixel_allocated_p = 0;
1612 pixel = x->mouse_pixel;
1613 if (pixel == fore_pixel)
1615 if (fore_pixel_allocated_p)
1617 x_free_colors (f, &fore_pixel, 1);
1618 fore_pixel_allocated_p = 0;
1620 fore_pixel = x->background_pixel;
1624 unload_color (f, x->cursor_foreground_pixel);
1625 if (!fore_pixel_allocated_p)
1626 fore_pixel = x_copy_color (f, fore_pixel);
1627 x->cursor_foreground_pixel = fore_pixel;
1629 unload_color (f, x->cursor_pixel);
1630 if (!pixel_allocated_p)
1631 pixel = x_copy_color (f, pixel);
1632 x->cursor_pixel = pixel;
1634 if (FRAME_X_WINDOW (f) != 0)
1636 BLOCK_INPUT;
1637 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1638 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1639 UNBLOCK_INPUT;
1641 if (FRAME_VISIBLE_P (f))
1643 x_update_cursor (f, 0);
1644 x_update_cursor (f, 1);
1648 update_face_from_frame_parameter (f, Qcursor_color, arg);
1651 /* Set the border-color of frame F to value described by ARG.
1652 ARG can be a string naming a color.
1653 The border-color is used for the border that is drawn by the X server.
1654 Note that this does not fully take effect if done before
1655 F has an x-window; it must be redone when the window is created.
1657 Note: this is done in two routines because of the way X10 works.
1659 Note: under X11, this is normally the province of the window manager,
1660 and so emacs' border colors may be overridden. */
1662 void
1663 x_set_border_color (f, arg, oldval)
1664 struct frame *f;
1665 Lisp_Object arg, oldval;
1667 int pix;
1669 CHECK_STRING (arg, 0);
1670 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1671 x_set_border_pixel (f, pix);
1672 update_face_from_frame_parameter (f, Qborder_color, arg);
1675 /* Set the border-color of frame F to pixel value PIX.
1676 Note that this does not fully take effect if done before
1677 F has an x-window. */
1679 void
1680 x_set_border_pixel (f, pix)
1681 struct frame *f;
1682 int pix;
1684 unload_color (f, f->output_data.x->border_pixel);
1685 f->output_data.x->border_pixel = pix;
1687 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1689 BLOCK_INPUT;
1690 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1691 (unsigned long)pix);
1692 UNBLOCK_INPUT;
1694 if (FRAME_VISIBLE_P (f))
1695 redraw_frame (f);
1700 /* Value is the internal representation of the specified cursor type
1701 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1702 of the bar cursor. */
1704 enum text_cursor_kinds
1705 x_specified_cursor_type (arg, width)
1706 Lisp_Object arg;
1707 int *width;
1709 enum text_cursor_kinds type;
1711 if (EQ (arg, Qbar))
1713 type = BAR_CURSOR;
1714 *width = 2;
1716 else if (CONSP (arg)
1717 && EQ (XCAR (arg), Qbar)
1718 && INTEGERP (XCDR (arg))
1719 && XINT (XCDR (arg)) >= 0)
1721 type = BAR_CURSOR;
1722 *width = XINT (XCDR (arg));
1724 else if (NILP (arg))
1725 type = NO_CURSOR;
1726 else
1727 /* Treat anything unknown as "box cursor".
1728 It was bad to signal an error; people have trouble fixing
1729 .Xdefaults with Emacs, when it has something bad in it. */
1730 type = FILLED_BOX_CURSOR;
1732 return type;
1735 void
1736 x_set_cursor_type (f, arg, oldval)
1737 FRAME_PTR f;
1738 Lisp_Object arg, oldval;
1740 int width;
1742 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1743 f->output_data.x->cursor_width = width;
1745 /* Make sure the cursor gets redrawn. This is overkill, but how
1746 often do people change cursor types? */
1747 update_mode_lines++;
1750 void
1751 x_set_icon_type (f, arg, oldval)
1752 struct frame *f;
1753 Lisp_Object arg, oldval;
1755 int result;
1757 if (STRINGP (arg))
1759 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1760 return;
1762 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1763 return;
1765 BLOCK_INPUT;
1766 if (NILP (arg))
1767 result = x_text_icon (f,
1768 (char *) XSTRING ((!NILP (f->icon_name)
1769 ? f->icon_name
1770 : f->name))->data);
1771 else
1772 result = x_bitmap_icon (f, arg);
1774 if (result)
1776 UNBLOCK_INPUT;
1777 error ("No icon window available");
1780 XFlush (FRAME_X_DISPLAY (f));
1781 UNBLOCK_INPUT;
1784 /* Return non-nil if frame F wants a bitmap icon. */
1786 Lisp_Object
1787 x_icon_type (f)
1788 FRAME_PTR f;
1790 Lisp_Object tem;
1792 tem = assq_no_quit (Qicon_type, f->param_alist);
1793 if (CONSP (tem))
1794 return XCDR (tem);
1795 else
1796 return Qnil;
1799 void
1800 x_set_icon_name (f, arg, oldval)
1801 struct frame *f;
1802 Lisp_Object arg, oldval;
1804 int result;
1806 if (STRINGP (arg))
1808 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1809 return;
1811 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1812 return;
1814 f->icon_name = arg;
1816 if (f->output_data.x->icon_bitmap != 0)
1817 return;
1819 BLOCK_INPUT;
1821 result = x_text_icon (f,
1822 (char *) XSTRING ((!NILP (f->icon_name)
1823 ? f->icon_name
1824 : !NILP (f->title)
1825 ? f->title
1826 : f->name))->data);
1828 if (result)
1830 UNBLOCK_INPUT;
1831 error ("No icon window available");
1834 XFlush (FRAME_X_DISPLAY (f));
1835 UNBLOCK_INPUT;
1838 void
1839 x_set_font (f, arg, oldval)
1840 struct frame *f;
1841 Lisp_Object arg, oldval;
1843 Lisp_Object result;
1844 Lisp_Object fontset_name;
1845 Lisp_Object frame;
1846 int old_fontset = f->output_data.x->fontset;
1848 CHECK_STRING (arg, 1);
1850 fontset_name = Fquery_fontset (arg, Qnil);
1852 BLOCK_INPUT;
1853 result = (STRINGP (fontset_name)
1854 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1855 : x_new_font (f, XSTRING (arg)->data));
1856 UNBLOCK_INPUT;
1858 if (EQ (result, Qnil))
1859 error ("Font `%s' is not defined", XSTRING (arg)->data);
1860 else if (EQ (result, Qt))
1861 error ("The characters of the given font have varying widths");
1862 else if (STRINGP (result))
1864 if (STRINGP (fontset_name))
1866 /* Fontset names are built from ASCII font names, so the
1867 names may be equal despite there was a change. */
1868 if (old_fontset == f->output_data.x->fontset)
1869 return;
1871 else if (!NILP (Fequal (result, oldval)))
1872 return;
1874 store_frame_param (f, Qfont, result);
1875 recompute_basic_faces (f);
1877 else
1878 abort ();
1880 do_pending_window_change (0);
1882 /* Don't call `face-set-after-frame-default' when faces haven't been
1883 initialized yet. This is the case when called from
1884 Fx_create_frame. In that case, the X widget or window doesn't
1885 exist either, and we can end up in x_report_frame_params with a
1886 null widget which gives a segfault. */
1887 if (FRAME_FACE_CACHE (f))
1889 XSETFRAME (frame, f);
1890 call1 (Qface_set_after_frame_default, frame);
1894 void
1895 x_set_border_width (f, arg, oldval)
1896 struct frame *f;
1897 Lisp_Object arg, oldval;
1899 CHECK_NUMBER (arg, 0);
1901 if (XINT (arg) == f->output_data.x->border_width)
1902 return;
1904 if (FRAME_X_WINDOW (f) != 0)
1905 error ("Cannot change the border width of a window");
1907 f->output_data.x->border_width = XINT (arg);
1910 void
1911 x_set_internal_border_width (f, arg, oldval)
1912 struct frame *f;
1913 Lisp_Object arg, oldval;
1915 int old = f->output_data.x->internal_border_width;
1917 CHECK_NUMBER (arg, 0);
1918 f->output_data.x->internal_border_width = XINT (arg);
1919 if (f->output_data.x->internal_border_width < 0)
1920 f->output_data.x->internal_border_width = 0;
1922 #ifdef USE_X_TOOLKIT
1923 if (f->output_data.x->edit_widget)
1924 widget_store_internal_border (f->output_data.x->edit_widget);
1925 #endif
1927 if (f->output_data.x->internal_border_width == old)
1928 return;
1930 if (FRAME_X_WINDOW (f) != 0)
1932 x_set_window_size (f, 0, f->width, f->height);
1933 SET_FRAME_GARBAGED (f);
1934 do_pending_window_change (0);
1938 void
1939 x_set_visibility (f, value, oldval)
1940 struct frame *f;
1941 Lisp_Object value, oldval;
1943 Lisp_Object frame;
1944 XSETFRAME (frame, f);
1946 if (NILP (value))
1947 Fmake_frame_invisible (frame, Qt);
1948 else if (EQ (value, Qicon))
1949 Ficonify_frame (frame);
1950 else
1951 Fmake_frame_visible (frame);
1955 /* Change window heights in windows rooted in WINDOW by N lines. */
1957 static void
1958 x_change_window_heights (window, n)
1959 Lisp_Object window;
1960 int n;
1962 struct window *w = XWINDOW (window);
1964 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1965 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1967 if (INTEGERP (w->orig_top))
1968 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1969 if (INTEGERP (w->orig_height))
1970 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1972 /* Handle just the top child in a vertical split. */
1973 if (!NILP (w->vchild))
1974 x_change_window_heights (w->vchild, n);
1976 /* Adjust all children in a horizontal split. */
1977 for (window = w->hchild; !NILP (window); window = w->next)
1979 w = XWINDOW (window);
1980 x_change_window_heights (window, n);
1984 void
1985 x_set_menu_bar_lines (f, value, oldval)
1986 struct frame *f;
1987 Lisp_Object value, oldval;
1989 int nlines;
1990 #ifndef USE_X_TOOLKIT
1991 int olines = FRAME_MENU_BAR_LINES (f);
1992 #endif
1994 /* Right now, menu bars don't work properly in minibuf-only frames;
1995 most of the commands try to apply themselves to the minibuffer
1996 frame itself, and get an error because you can't switch buffers
1997 in or split the minibuffer window. */
1998 if (FRAME_MINIBUF_ONLY_P (f))
1999 return;
2001 if (INTEGERP (value))
2002 nlines = XINT (value);
2003 else
2004 nlines = 0;
2006 /* Make sure we redisplay all windows in this frame. */
2007 windows_or_buffers_changed++;
2009 #ifdef USE_X_TOOLKIT
2010 FRAME_MENU_BAR_LINES (f) = 0;
2011 if (nlines)
2013 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2014 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
2015 /* Make sure next redisplay shows the menu bar. */
2016 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2018 else
2020 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2021 free_frame_menubar (f);
2022 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2023 if (FRAME_X_P (f))
2024 f->output_data.x->menubar_widget = 0;
2026 #else /* not USE_X_TOOLKIT */
2027 FRAME_MENU_BAR_LINES (f) = nlines;
2028 x_change_window_heights (f->root_window, nlines - olines);
2029 #endif /* not USE_X_TOOLKIT */
2030 adjust_glyphs (f);
2034 /* Set the number of lines used for the tool bar of frame F to VALUE.
2035 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2036 is the old number of tool bar lines. This function changes the
2037 height of all windows on frame F to match the new tool bar height.
2038 The frame's height doesn't change. */
2040 void
2041 x_set_tool_bar_lines (f, value, oldval)
2042 struct frame *f;
2043 Lisp_Object value, oldval;
2045 int delta, nlines, root_height;
2046 Lisp_Object root_window;
2048 /* Treat tool bars like menu bars. */
2049 if (FRAME_MINIBUF_ONLY_P (f))
2050 return;
2052 /* Use VALUE only if an integer >= 0. */
2053 if (INTEGERP (value) && XINT (value) >= 0)
2054 nlines = XFASTINT (value);
2055 else
2056 nlines = 0;
2058 /* Make sure we redisplay all windows in this frame. */
2059 ++windows_or_buffers_changed;
2061 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2063 /* Don't resize the tool-bar to more than we have room for. */
2064 root_window = FRAME_ROOT_WINDOW (f);
2065 root_height = XINT (XWINDOW (root_window)->height);
2066 if (root_height - delta < 1)
2068 delta = root_height - 1;
2069 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2072 FRAME_TOOL_BAR_LINES (f) = nlines;
2073 x_change_window_heights (root_window, delta);
2074 adjust_glyphs (f);
2076 /* We also have to make sure that the internal border at the top of
2077 the frame, below the menu bar or tool bar, is redrawn when the
2078 tool bar disappears. This is so because the internal border is
2079 below the tool bar if one is displayed, but is below the menu bar
2080 if there isn't a tool bar. The tool bar draws into the area
2081 below the menu bar. */
2082 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2084 updating_frame = f;
2085 clear_frame ();
2086 clear_current_matrices (f);
2087 updating_frame = NULL;
2090 /* If the tool bar gets smaller, the internal border below it
2091 has to be cleared. It was formerly part of the display
2092 of the larger tool bar, and updating windows won't clear it. */
2093 if (delta < 0)
2095 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2096 int width = PIXEL_WIDTH (f);
2097 int y = nlines * CANON_Y_UNIT (f);
2099 BLOCK_INPUT;
2100 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2101 0, y, width, height, False);
2102 UNBLOCK_INPUT;
2104 if (WINDOWP (f->tool_bar_window))
2105 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2110 /* Set the foreground color for scroll bars on frame F to VALUE.
2111 VALUE should be a string, a color name. If it isn't a string or
2112 isn't a valid color name, do nothing. OLDVAL is the old value of
2113 the frame parameter. */
2115 void
2116 x_set_scroll_bar_foreground (f, value, oldval)
2117 struct frame *f;
2118 Lisp_Object value, oldval;
2120 unsigned long pixel;
2122 if (STRINGP (value))
2123 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2124 else
2125 pixel = -1;
2127 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2128 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2130 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2131 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2133 /* Remove all scroll bars because they have wrong colors. */
2134 if (condemn_scroll_bars_hook)
2135 (*condemn_scroll_bars_hook) (f);
2136 if (judge_scroll_bars_hook)
2137 (*judge_scroll_bars_hook) (f);
2139 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2140 redraw_frame (f);
2145 /* Set the background color for scroll bars on frame F to VALUE VALUE
2146 should be a string, a color name. If it isn't a string or isn't a
2147 valid color name, do nothing. OLDVAL is the old value of the frame
2148 parameter. */
2150 void
2151 x_set_scroll_bar_background (f, value, oldval)
2152 struct frame *f;
2153 Lisp_Object value, oldval;
2155 unsigned long pixel;
2157 if (STRINGP (value))
2158 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2159 else
2160 pixel = -1;
2162 if (f->output_data.x->scroll_bar_background_pixel != -1)
2163 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2165 f->output_data.x->scroll_bar_background_pixel = pixel;
2166 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2168 /* Remove all scroll bars because they have wrong colors. */
2169 if (condemn_scroll_bars_hook)
2170 (*condemn_scroll_bars_hook) (f);
2171 if (judge_scroll_bars_hook)
2172 (*judge_scroll_bars_hook) (f);
2174 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2175 redraw_frame (f);
2180 /* Encode Lisp string STRING as a text in a format appropriate for
2181 XICCC (X Inter Client Communication Conventions).
2183 If STRING contains only ASCII characters, do no conversion and
2184 return the string data of STRING. Otherwise, encode the text by
2185 CODING_SYSTEM, and return a newly allocated memory area which
2186 should be freed by `xfree' by a caller.
2188 Store the byte length of resulting text in *TEXT_BYTES.
2190 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2191 which means that the `encoding' of the result can be `STRING'.
2192 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2193 the result should be `COMPOUND_TEXT'. */
2195 unsigned char *
2196 x_encode_text (string, coding_system, text_bytes, stringp)
2197 Lisp_Object string, coding_system;
2198 int *text_bytes, *stringp;
2200 unsigned char *str = XSTRING (string)->data;
2201 int chars = XSTRING (string)->size;
2202 int bytes = STRING_BYTES (XSTRING (string));
2203 int charset_info;
2204 int bufsize;
2205 unsigned char *buf;
2206 struct coding_system coding;
2208 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2209 if (charset_info == 0)
2211 /* No multibyte character in OBJ. We need not encode it. */
2212 *text_bytes = bytes;
2213 *stringp = 1;
2214 return str;
2217 setup_coding_system (coding_system, &coding);
2218 coding.src_multibyte = 1;
2219 coding.dst_multibyte = 0;
2220 coding.mode |= CODING_MODE_LAST_BLOCK;
2221 if (coding.type == coding_type_iso2022)
2222 coding.flags |= CODING_FLAG_ISO_SAFE;
2223 /* We suppress producing escape sequences for composition. */
2224 coding.composing = COMPOSITION_DISABLED;
2225 bufsize = encoding_buffer_size (&coding, bytes);
2226 buf = (unsigned char *) xmalloc (bufsize);
2227 encode_coding (&coding, str, buf, bytes, bufsize);
2228 *text_bytes = coding.produced;
2229 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2230 return buf;
2234 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2235 x_id_name.
2237 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2238 name; if NAME is a string, set F's name to NAME and set
2239 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2241 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2242 suggesting a new name, which lisp code should override; if
2243 F->explicit_name is set, ignore the new name; otherwise, set it. */
2245 void
2246 x_set_name (f, name, explicit)
2247 struct frame *f;
2248 Lisp_Object name;
2249 int explicit;
2251 /* Make sure that requests from lisp code override requests from
2252 Emacs redisplay code. */
2253 if (explicit)
2255 /* If we're switching from explicit to implicit, we had better
2256 update the mode lines and thereby update the title. */
2257 if (f->explicit_name && NILP (name))
2258 update_mode_lines = 1;
2260 f->explicit_name = ! NILP (name);
2262 else if (f->explicit_name)
2263 return;
2265 /* If NAME is nil, set the name to the x_id_name. */
2266 if (NILP (name))
2268 /* Check for no change needed in this very common case
2269 before we do any consing. */
2270 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2271 XSTRING (f->name)->data))
2272 return;
2273 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2275 else
2276 CHECK_STRING (name, 0);
2278 /* Don't change the name if it's already NAME. */
2279 if (! NILP (Fstring_equal (name, f->name)))
2280 return;
2282 f->name = name;
2284 /* For setting the frame title, the title parameter should override
2285 the name parameter. */
2286 if (! NILP (f->title))
2287 name = f->title;
2289 if (FRAME_X_WINDOW (f))
2291 BLOCK_INPUT;
2292 #ifdef HAVE_X11R4
2294 XTextProperty text, icon;
2295 int bytes, stringp;
2296 Lisp_Object coding_system;
2298 coding_system = Vlocale_coding_system;
2299 if (NILP (coding_system))
2300 coding_system = Qcompound_text;
2301 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2302 text.encoding = (stringp ? XA_STRING
2303 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2304 text.format = 8;
2305 text.nitems = bytes;
2307 if (NILP (f->icon_name))
2309 icon = text;
2311 else
2313 icon.value = x_encode_text (f->icon_name, coding_system,
2314 &bytes, &stringp);
2315 icon.encoding = (stringp ? XA_STRING
2316 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2317 icon.format = 8;
2318 icon.nitems = bytes;
2320 #ifdef USE_X_TOOLKIT
2321 XSetWMName (FRAME_X_DISPLAY (f),
2322 XtWindow (f->output_data.x->widget), &text);
2323 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2324 &icon);
2325 #else /* not USE_X_TOOLKIT */
2326 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2327 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2328 #endif /* not USE_X_TOOLKIT */
2329 if (!NILP (f->icon_name)
2330 && icon.value != XSTRING (f->icon_name)->data)
2331 xfree (icon.value);
2332 if (text.value != XSTRING (name)->data)
2333 xfree (text.value);
2335 #else /* not HAVE_X11R4 */
2336 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2337 XSTRING (name)->data);
2338 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2339 XSTRING (name)->data);
2340 #endif /* not HAVE_X11R4 */
2341 UNBLOCK_INPUT;
2345 /* This function should be called when the user's lisp code has
2346 specified a name for the frame; the name will override any set by the
2347 redisplay code. */
2348 void
2349 x_explicitly_set_name (f, arg, oldval)
2350 FRAME_PTR f;
2351 Lisp_Object arg, oldval;
2353 x_set_name (f, arg, 1);
2356 /* This function should be called by Emacs redisplay code to set the
2357 name; names set this way will never override names set by the user's
2358 lisp code. */
2359 void
2360 x_implicitly_set_name (f, arg, oldval)
2361 FRAME_PTR f;
2362 Lisp_Object arg, oldval;
2364 x_set_name (f, arg, 0);
2367 /* Change the title of frame F to NAME.
2368 If NAME is nil, use the frame name as the title.
2370 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2371 name; if NAME is a string, set F's name to NAME and set
2372 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2374 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2375 suggesting a new name, which lisp code should override; if
2376 F->explicit_name is set, ignore the new name; otherwise, set it. */
2378 void
2379 x_set_title (f, name, old_name)
2380 struct frame *f;
2381 Lisp_Object name, old_name;
2383 /* Don't change the title if it's already NAME. */
2384 if (EQ (name, f->title))
2385 return;
2387 update_mode_lines = 1;
2389 f->title = name;
2391 if (NILP (name))
2392 name = f->name;
2393 else
2394 CHECK_STRING (name, 0);
2396 if (FRAME_X_WINDOW (f))
2398 BLOCK_INPUT;
2399 #ifdef HAVE_X11R4
2401 XTextProperty text, icon;
2402 int bytes, stringp;
2403 Lisp_Object coding_system;
2405 coding_system = Vlocale_coding_system;
2406 if (NILP (coding_system))
2407 coding_system = Qcompound_text;
2408 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2409 text.encoding = (stringp ? XA_STRING
2410 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2411 text.format = 8;
2412 text.nitems = bytes;
2414 if (NILP (f->icon_name))
2416 icon = text;
2418 else
2420 icon.value = x_encode_text (f->icon_name, coding_system,
2421 &bytes, &stringp);
2422 icon.encoding = (stringp ? XA_STRING
2423 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2424 icon.format = 8;
2425 icon.nitems = bytes;
2427 #ifdef USE_X_TOOLKIT
2428 XSetWMName (FRAME_X_DISPLAY (f),
2429 XtWindow (f->output_data.x->widget), &text);
2430 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2431 &icon);
2432 #else /* not USE_X_TOOLKIT */
2433 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2434 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2435 #endif /* not USE_X_TOOLKIT */
2436 if (!NILP (f->icon_name)
2437 && icon.value != XSTRING (f->icon_name)->data)
2438 xfree (icon.value);
2439 if (text.value != XSTRING (name)->data)
2440 xfree (text.value);
2442 #else /* not HAVE_X11R4 */
2443 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2444 XSTRING (name)->data);
2445 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2446 XSTRING (name)->data);
2447 #endif /* not HAVE_X11R4 */
2448 UNBLOCK_INPUT;
2452 void
2453 x_set_autoraise (f, arg, oldval)
2454 struct frame *f;
2455 Lisp_Object arg, oldval;
2457 f->auto_raise = !EQ (Qnil, arg);
2460 void
2461 x_set_autolower (f, arg, oldval)
2462 struct frame *f;
2463 Lisp_Object arg, oldval;
2465 f->auto_lower = !EQ (Qnil, arg);
2468 void
2469 x_set_unsplittable (f, arg, oldval)
2470 struct frame *f;
2471 Lisp_Object arg, oldval;
2473 f->no_split = !NILP (arg);
2476 void
2477 x_set_vertical_scroll_bars (f, arg, oldval)
2478 struct frame *f;
2479 Lisp_Object arg, oldval;
2481 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2482 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2483 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2484 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2486 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2487 = (NILP (arg)
2488 ? vertical_scroll_bar_none
2489 : EQ (Qright, arg)
2490 ? vertical_scroll_bar_right
2491 : vertical_scroll_bar_left);
2493 /* We set this parameter before creating the X window for the
2494 frame, so we can get the geometry right from the start.
2495 However, if the window hasn't been created yet, we shouldn't
2496 call x_set_window_size. */
2497 if (FRAME_X_WINDOW (f))
2498 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2499 do_pending_window_change (0);
2503 void
2504 x_set_scroll_bar_width (f, arg, oldval)
2505 struct frame *f;
2506 Lisp_Object arg, oldval;
2508 int wid = FONT_WIDTH (f->output_data.x->font);
2510 if (NILP (arg))
2512 #ifdef USE_TOOLKIT_SCROLL_BARS
2513 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2514 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2515 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2516 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2517 #else
2518 /* Make the actual width at least 14 pixels and a multiple of a
2519 character width. */
2520 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2522 /* Use all of that space (aside from required margins) for the
2523 scroll bar. */
2524 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2525 #endif
2527 if (FRAME_X_WINDOW (f))
2528 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2529 do_pending_window_change (0);
2531 else if (INTEGERP (arg) && XINT (arg) > 0
2532 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2534 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2535 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2537 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2538 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2539 if (FRAME_X_WINDOW (f))
2540 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2543 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2544 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2545 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2550 /* Subroutines of creating an X frame. */
2552 /* Make sure that Vx_resource_name is set to a reasonable value.
2553 Fix it up, or set it to `emacs' if it is too hopeless. */
2555 static void
2556 validate_x_resource_name ()
2558 int len = 0;
2559 /* Number of valid characters in the resource name. */
2560 int good_count = 0;
2561 /* Number of invalid characters in the resource name. */
2562 int bad_count = 0;
2563 Lisp_Object new;
2564 int i;
2566 if (!STRINGP (Vx_resource_class))
2567 Vx_resource_class = build_string (EMACS_CLASS);
2569 if (STRINGP (Vx_resource_name))
2571 unsigned char *p = XSTRING (Vx_resource_name)->data;
2572 int i;
2574 len = STRING_BYTES (XSTRING (Vx_resource_name));
2576 /* Only letters, digits, - and _ are valid in resource names.
2577 Count the valid characters and count the invalid ones. */
2578 for (i = 0; i < len; i++)
2580 int c = p[i];
2581 if (! ((c >= 'a' && c <= 'z')
2582 || (c >= 'A' && c <= 'Z')
2583 || (c >= '0' && c <= '9')
2584 || c == '-' || c == '_'))
2585 bad_count++;
2586 else
2587 good_count++;
2590 else
2591 /* Not a string => completely invalid. */
2592 bad_count = 5, good_count = 0;
2594 /* If name is valid already, return. */
2595 if (bad_count == 0)
2596 return;
2598 /* If name is entirely invalid, or nearly so, use `emacs'. */
2599 if (good_count == 0
2600 || (good_count == 1 && bad_count > 0))
2602 Vx_resource_name = build_string ("emacs");
2603 return;
2606 /* Name is partly valid. Copy it and replace the invalid characters
2607 with underscores. */
2609 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2611 for (i = 0; i < len; i++)
2613 int c = XSTRING (new)->data[i];
2614 if (! ((c >= 'a' && c <= 'z')
2615 || (c >= 'A' && c <= 'Z')
2616 || (c >= '0' && c <= '9')
2617 || c == '-' || c == '_'))
2618 XSTRING (new)->data[i] = '_';
2623 extern char *x_get_string_resource ();
2625 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2626 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2627 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2628 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2629 the name specified by the `-name' or `-rn' command-line arguments.\n\
2631 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2632 class, respectively. You must specify both of them or neither.\n\
2633 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2634 and the class is `Emacs.CLASS.SUBCLASS'.")
2635 (attribute, class, component, subclass)
2636 Lisp_Object attribute, class, component, subclass;
2638 register char *value;
2639 char *name_key;
2640 char *class_key;
2642 check_x ();
2644 CHECK_STRING (attribute, 0);
2645 CHECK_STRING (class, 0);
2647 if (!NILP (component))
2648 CHECK_STRING (component, 1);
2649 if (!NILP (subclass))
2650 CHECK_STRING (subclass, 2);
2651 if (NILP (component) != NILP (subclass))
2652 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2654 validate_x_resource_name ();
2656 /* Allocate space for the components, the dots which separate them,
2657 and the final '\0'. Make them big enough for the worst case. */
2658 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2659 + (STRINGP (component)
2660 ? STRING_BYTES (XSTRING (component)) : 0)
2661 + STRING_BYTES (XSTRING (attribute))
2662 + 3);
2664 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2665 + STRING_BYTES (XSTRING (class))
2666 + (STRINGP (subclass)
2667 ? STRING_BYTES (XSTRING (subclass)) : 0)
2668 + 3);
2670 /* Start with emacs.FRAMENAME for the name (the specific one)
2671 and with `Emacs' for the class key (the general one). */
2672 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2673 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2675 strcat (class_key, ".");
2676 strcat (class_key, XSTRING (class)->data);
2678 if (!NILP (component))
2680 strcat (class_key, ".");
2681 strcat (class_key, XSTRING (subclass)->data);
2683 strcat (name_key, ".");
2684 strcat (name_key, XSTRING (component)->data);
2687 strcat (name_key, ".");
2688 strcat (name_key, XSTRING (attribute)->data);
2690 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2691 name_key, class_key);
2693 if (value != (char *) 0)
2694 return build_string (value);
2695 else
2696 return Qnil;
2699 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2701 Lisp_Object
2702 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2703 struct x_display_info *dpyinfo;
2704 Lisp_Object attribute, class, component, subclass;
2706 register char *value;
2707 char *name_key;
2708 char *class_key;
2710 CHECK_STRING (attribute, 0);
2711 CHECK_STRING (class, 0);
2713 if (!NILP (component))
2714 CHECK_STRING (component, 1);
2715 if (!NILP (subclass))
2716 CHECK_STRING (subclass, 2);
2717 if (NILP (component) != NILP (subclass))
2718 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2720 validate_x_resource_name ();
2722 /* Allocate space for the components, the dots which separate them,
2723 and the final '\0'. Make them big enough for the worst case. */
2724 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2725 + (STRINGP (component)
2726 ? STRING_BYTES (XSTRING (component)) : 0)
2727 + STRING_BYTES (XSTRING (attribute))
2728 + 3);
2730 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2731 + STRING_BYTES (XSTRING (class))
2732 + (STRINGP (subclass)
2733 ? STRING_BYTES (XSTRING (subclass)) : 0)
2734 + 3);
2736 /* Start with emacs.FRAMENAME for the name (the specific one)
2737 and with `Emacs' for the class key (the general one). */
2738 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2739 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2741 strcat (class_key, ".");
2742 strcat (class_key, XSTRING (class)->data);
2744 if (!NILP (component))
2746 strcat (class_key, ".");
2747 strcat (class_key, XSTRING (subclass)->data);
2749 strcat (name_key, ".");
2750 strcat (name_key, XSTRING (component)->data);
2753 strcat (name_key, ".");
2754 strcat (name_key, XSTRING (attribute)->data);
2756 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2758 if (value != (char *) 0)
2759 return build_string (value);
2760 else
2761 return Qnil;
2764 /* Used when C code wants a resource value. */
2766 char *
2767 x_get_resource_string (attribute, class)
2768 char *attribute, *class;
2770 char *name_key;
2771 char *class_key;
2772 struct frame *sf = SELECTED_FRAME ();
2774 /* Allocate space for the components, the dots which separate them,
2775 and the final '\0'. */
2776 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2777 + strlen (attribute) + 2);
2778 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2779 + strlen (class) + 2);
2781 sprintf (name_key, "%s.%s",
2782 XSTRING (Vinvocation_name)->data,
2783 attribute);
2784 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2786 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2787 name_key, class_key);
2790 /* Types we might convert a resource string into. */
2791 enum resource_types
2793 RES_TYPE_NUMBER,
2794 RES_TYPE_FLOAT,
2795 RES_TYPE_BOOLEAN,
2796 RES_TYPE_STRING,
2797 RES_TYPE_SYMBOL
2800 /* Return the value of parameter PARAM.
2802 First search ALIST, then Vdefault_frame_alist, then the X defaults
2803 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2805 Convert the resource to the type specified by desired_type.
2807 If no default is specified, return Qunbound. If you call
2808 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2809 and don't let it get stored in any Lisp-visible variables! */
2811 static Lisp_Object
2812 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2813 struct x_display_info *dpyinfo;
2814 Lisp_Object alist, param;
2815 char *attribute;
2816 char *class;
2817 enum resource_types type;
2819 register Lisp_Object tem;
2821 tem = Fassq (param, alist);
2822 if (EQ (tem, Qnil))
2823 tem = Fassq (param, Vdefault_frame_alist);
2824 if (EQ (tem, Qnil))
2827 if (attribute)
2829 tem = display_x_get_resource (dpyinfo,
2830 build_string (attribute),
2831 build_string (class),
2832 Qnil, Qnil);
2834 if (NILP (tem))
2835 return Qunbound;
2837 switch (type)
2839 case RES_TYPE_NUMBER:
2840 return make_number (atoi (XSTRING (tem)->data));
2842 case RES_TYPE_FLOAT:
2843 return make_float (atof (XSTRING (tem)->data));
2845 case RES_TYPE_BOOLEAN:
2846 tem = Fdowncase (tem);
2847 if (!strcmp (XSTRING (tem)->data, "on")
2848 || !strcmp (XSTRING (tem)->data, "true"))
2849 return Qt;
2850 else
2851 return Qnil;
2853 case RES_TYPE_STRING:
2854 return tem;
2856 case RES_TYPE_SYMBOL:
2857 /* As a special case, we map the values `true' and `on'
2858 to Qt, and `false' and `off' to Qnil. */
2860 Lisp_Object lower;
2861 lower = Fdowncase (tem);
2862 if (!strcmp (XSTRING (lower)->data, "on")
2863 || !strcmp (XSTRING (lower)->data, "true"))
2864 return Qt;
2865 else if (!strcmp (XSTRING (lower)->data, "off")
2866 || !strcmp (XSTRING (lower)->data, "false"))
2867 return Qnil;
2868 else
2869 return Fintern (tem, Qnil);
2872 default:
2873 abort ();
2876 else
2877 return Qunbound;
2879 return Fcdr (tem);
2882 /* Like x_get_arg, but also record the value in f->param_alist. */
2884 static Lisp_Object
2885 x_get_and_record_arg (f, alist, param, attribute, class, type)
2886 struct frame *f;
2887 Lisp_Object alist, param;
2888 char *attribute;
2889 char *class;
2890 enum resource_types type;
2892 Lisp_Object value;
2894 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2895 attribute, class, type);
2896 if (! NILP (value))
2897 store_frame_param (f, param, value);
2899 return value;
2902 /* Record in frame F the specified or default value according to ALIST
2903 of the parameter named PROP (a Lisp symbol).
2904 If no value is specified for PROP, look for an X default for XPROP
2905 on the frame named NAME.
2906 If that is not found either, use the value DEFLT. */
2908 static Lisp_Object
2909 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2910 struct frame *f;
2911 Lisp_Object alist;
2912 Lisp_Object prop;
2913 Lisp_Object deflt;
2914 char *xprop;
2915 char *xclass;
2916 enum resource_types type;
2918 Lisp_Object tem;
2920 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2921 if (EQ (tem, Qunbound))
2922 tem = deflt;
2923 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2924 return tem;
2928 /* Record in frame F the specified or default value according to ALIST
2929 of the parameter named PROP (a Lisp symbol). If no value is
2930 specified for PROP, look for an X default for XPROP on the frame
2931 named NAME. If that is not found either, use the value DEFLT. */
2933 static Lisp_Object
2934 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2935 foreground_p)
2936 struct frame *f;
2937 Lisp_Object alist;
2938 Lisp_Object prop;
2939 char *xprop;
2940 char *xclass;
2941 int foreground_p;
2943 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2944 Lisp_Object tem;
2946 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2947 if (EQ (tem, Qunbound))
2949 #ifdef USE_TOOLKIT_SCROLL_BARS
2951 /* See if an X resource for the scroll bar color has been
2952 specified. */
2953 tem = display_x_get_resource (dpyinfo,
2954 build_string (foreground_p
2955 ? "foreground"
2956 : "background"),
2957 build_string (""),
2958 build_string ("verticalScrollBar"),
2959 build_string (""));
2960 if (!STRINGP (tem))
2962 /* If nothing has been specified, scroll bars will use a
2963 toolkit-dependent default. Because these defaults are
2964 difficult to get at without actually creating a scroll
2965 bar, use nil to indicate that no color has been
2966 specified. */
2967 tem = Qnil;
2970 #else /* not USE_TOOLKIT_SCROLL_BARS */
2972 tem = Qnil;
2974 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2977 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2978 return tem;
2983 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2984 "Parse an X-style geometry string STRING.\n\
2985 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2986 The properties returned may include `top', `left', `height', and `width'.\n\
2987 The value of `left' or `top' may be an integer,\n\
2988 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2989 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2990 (string)
2991 Lisp_Object string;
2993 int geometry, x, y;
2994 unsigned int width, height;
2995 Lisp_Object result;
2997 CHECK_STRING (string, 0);
2999 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3000 &x, &y, &width, &height);
3002 #if 0
3003 if (!!(geometry & XValue) != !!(geometry & YValue))
3004 error ("Must specify both x and y position, or neither");
3005 #endif
3007 result = Qnil;
3008 if (geometry & XValue)
3010 Lisp_Object element;
3012 if (x >= 0 && (geometry & XNegative))
3013 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3014 else if (x < 0 && ! (geometry & XNegative))
3015 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3016 else
3017 element = Fcons (Qleft, make_number (x));
3018 result = Fcons (element, result);
3021 if (geometry & YValue)
3023 Lisp_Object element;
3025 if (y >= 0 && (geometry & YNegative))
3026 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3027 else if (y < 0 && ! (geometry & YNegative))
3028 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3029 else
3030 element = Fcons (Qtop, make_number (y));
3031 result = Fcons (element, result);
3034 if (geometry & WidthValue)
3035 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3036 if (geometry & HeightValue)
3037 result = Fcons (Fcons (Qheight, make_number (height)), result);
3039 return result;
3042 /* Calculate the desired size and position of this window,
3043 and return the flags saying which aspects were specified.
3045 This function does not make the coordinates positive. */
3047 #define DEFAULT_ROWS 40
3048 #define DEFAULT_COLS 80
3050 static int
3051 x_figure_window_size (f, parms)
3052 struct frame *f;
3053 Lisp_Object parms;
3055 register Lisp_Object tem0, tem1, tem2;
3056 long window_prompting = 0;
3057 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3059 /* Default values if we fall through.
3060 Actually, if that happens we should get
3061 window manager prompting. */
3062 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3063 f->height = DEFAULT_ROWS;
3064 /* Window managers expect that if program-specified
3065 positions are not (0,0), they're intentional, not defaults. */
3066 f->output_data.x->top_pos = 0;
3067 f->output_data.x->left_pos = 0;
3069 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3070 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3071 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3072 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3074 if (!EQ (tem0, Qunbound))
3076 CHECK_NUMBER (tem0, 0);
3077 f->height = XINT (tem0);
3079 if (!EQ (tem1, Qunbound))
3081 CHECK_NUMBER (tem1, 0);
3082 SET_FRAME_WIDTH (f, XINT (tem1));
3084 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3085 window_prompting |= USSize;
3086 else
3087 window_prompting |= PSize;
3090 f->output_data.x->vertical_scroll_bar_extra
3091 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3093 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3094 f->output_data.x->flags_areas_extra
3095 = FRAME_FLAGS_AREA_WIDTH (f);
3096 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3097 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3099 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3100 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3101 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3102 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3104 if (EQ (tem0, Qminus))
3106 f->output_data.x->top_pos = 0;
3107 window_prompting |= YNegative;
3109 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3110 && CONSP (XCDR (tem0))
3111 && INTEGERP (XCAR (XCDR (tem0))))
3113 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3114 window_prompting |= YNegative;
3116 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3117 && CONSP (XCDR (tem0))
3118 && INTEGERP (XCAR (XCDR (tem0))))
3120 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3122 else if (EQ (tem0, Qunbound))
3123 f->output_data.x->top_pos = 0;
3124 else
3126 CHECK_NUMBER (tem0, 0);
3127 f->output_data.x->top_pos = XINT (tem0);
3128 if (f->output_data.x->top_pos < 0)
3129 window_prompting |= YNegative;
3132 if (EQ (tem1, Qminus))
3134 f->output_data.x->left_pos = 0;
3135 window_prompting |= XNegative;
3137 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3138 && CONSP (XCDR (tem1))
3139 && INTEGERP (XCAR (XCDR (tem1))))
3141 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3142 window_prompting |= XNegative;
3144 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3145 && CONSP (XCDR (tem1))
3146 && INTEGERP (XCAR (XCDR (tem1))))
3148 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3150 else if (EQ (tem1, Qunbound))
3151 f->output_data.x->left_pos = 0;
3152 else
3154 CHECK_NUMBER (tem1, 0);
3155 f->output_data.x->left_pos = XINT (tem1);
3156 if (f->output_data.x->left_pos < 0)
3157 window_prompting |= XNegative;
3160 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3161 window_prompting |= USPosition;
3162 else
3163 window_prompting |= PPosition;
3166 return window_prompting;
3169 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3171 Status
3172 XSetWMProtocols (dpy, w, protocols, count)
3173 Display *dpy;
3174 Window w;
3175 Atom *protocols;
3176 int count;
3178 Atom prop;
3179 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3180 if (prop == None) return False;
3181 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3182 (unsigned char *) protocols, count);
3183 return True;
3185 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3187 #ifdef USE_X_TOOLKIT
3189 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3190 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3191 already be present because of the toolkit (Motif adds some of them,
3192 for example, but Xt doesn't). */
3194 static void
3195 hack_wm_protocols (f, widget)
3196 FRAME_PTR f;
3197 Widget widget;
3199 Display *dpy = XtDisplay (widget);
3200 Window w = XtWindow (widget);
3201 int need_delete = 1;
3202 int need_focus = 1;
3203 int need_save = 1;
3205 BLOCK_INPUT;
3207 Atom type, *atoms = 0;
3208 int format = 0;
3209 unsigned long nitems = 0;
3210 unsigned long bytes_after;
3212 if ((XGetWindowProperty (dpy, w,
3213 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3214 (long)0, (long)100, False, XA_ATOM,
3215 &type, &format, &nitems, &bytes_after,
3216 (unsigned char **) &atoms)
3217 == Success)
3218 && format == 32 && type == XA_ATOM)
3219 while (nitems > 0)
3221 nitems--;
3222 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3223 need_delete = 0;
3224 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3225 need_focus = 0;
3226 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3227 need_save = 0;
3229 if (atoms) XFree ((char *) atoms);
3232 Atom props [10];
3233 int count = 0;
3234 if (need_delete)
3235 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3236 if (need_focus)
3237 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3238 if (need_save)
3239 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3240 if (count)
3241 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3242 XA_ATOM, 32, PropModeAppend,
3243 (unsigned char *) props, count);
3245 UNBLOCK_INPUT;
3247 #endif
3251 /* Support routines for XIC (X Input Context). */
3253 #ifdef HAVE_X_I18N
3255 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3256 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3259 /* Supported XIM styles, ordered by preferenc. */
3261 static XIMStyle supported_xim_styles[] =
3263 XIMPreeditPosition | XIMStatusArea,
3264 XIMPreeditPosition | XIMStatusNothing,
3265 XIMPreeditPosition | XIMStatusNone,
3266 XIMPreeditNothing | XIMStatusArea,
3267 XIMPreeditNothing | XIMStatusNothing,
3268 XIMPreeditNothing | XIMStatusNone,
3269 XIMPreeditNone | XIMStatusArea,
3270 XIMPreeditNone | XIMStatusNothing,
3271 XIMPreeditNone | XIMStatusNone,
3276 /* Create an X fontset on frame F with base font name
3277 BASE_FONTNAME.. */
3279 static XFontSet
3280 xic_create_xfontset (f, base_fontname)
3281 struct frame *f;
3282 char *base_fontname;
3284 XFontSet xfs;
3285 char **missing_list;
3286 int missing_count;
3287 char *def_string;
3289 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3290 base_fontname, &missing_list,
3291 &missing_count, &def_string);
3292 if (missing_list)
3293 XFreeStringList (missing_list);
3295 /* No need to free def_string. */
3296 return xfs;
3300 /* Value is the best input style, given user preferences USER (already
3301 checked to be supported by Emacs), and styles supported by the
3302 input method XIM. */
3304 static XIMStyle
3305 best_xim_style (user, xim)
3306 XIMStyles *user;
3307 XIMStyles *xim;
3309 int i, j;
3311 for (i = 0; i < user->count_styles; ++i)
3312 for (j = 0; j < xim->count_styles; ++j)
3313 if (user->supported_styles[i] == xim->supported_styles[j])
3314 return user->supported_styles[i];
3316 /* Return the default style. */
3317 return XIMPreeditNothing | XIMStatusNothing;
3320 /* Create XIC for frame F. */
3322 static XIMStyle xic_style;
3324 void
3325 create_frame_xic (f)
3326 struct frame *f;
3328 XIM xim;
3329 XIC xic = NULL;
3330 XFontSet xfs = NULL;
3332 if (FRAME_XIC (f))
3333 return;
3335 xim = FRAME_X_XIM (f);
3336 if (xim)
3338 XRectangle s_area;
3339 XPoint spot;
3340 XVaNestedList preedit_attr;
3341 XVaNestedList status_attr;
3342 char *base_fontname;
3343 int fontset;
3345 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3346 spot.x = 0; spot.y = 1;
3347 /* Create X fontset. */
3348 fontset = FRAME_FONTSET (f);
3349 if (fontset < 0)
3350 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3351 else
3353 /* Determine the base fontname from the ASCII font name of
3354 FONTSET. */
3355 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3356 char *p = ascii_font;
3357 int i;
3359 for (i = 0; *p; p++)
3360 if (*p == '-') i++;
3361 if (i != 14)
3362 /* As the font name doesn't conform to XLFD, we can't
3363 modify it to get a suitable base fontname for the
3364 frame. */
3365 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3366 else
3368 int len = strlen (ascii_font) + 1;
3369 char *p1 = NULL;
3371 for (i = 0, p = ascii_font; i < 8; p++)
3373 if (*p == '-')
3375 i++;
3376 if (i == 3)
3377 p1 = p + 1;
3380 base_fontname = (char *) alloca (len);
3381 bzero (base_fontname, len);
3382 strcpy (base_fontname, "-*-*-");
3383 bcopy (p1, base_fontname + 5, p - p1);
3384 strcat (base_fontname, "*-*-*-*-*-*-*");
3387 xfs = xic_create_xfontset (f, base_fontname);
3389 /* Determine XIC style. */
3390 if (xic_style == 0)
3392 XIMStyles supported_list;
3393 supported_list.count_styles = (sizeof supported_xim_styles
3394 / sizeof supported_xim_styles[0]);
3395 supported_list.supported_styles = supported_xim_styles;
3396 xic_style = best_xim_style (&supported_list,
3397 FRAME_X_XIM_STYLES (f));
3400 preedit_attr = XVaCreateNestedList (0,
3401 XNFontSet, xfs,
3402 XNForeground,
3403 FRAME_FOREGROUND_PIXEL (f),
3404 XNBackground,
3405 FRAME_BACKGROUND_PIXEL (f),
3406 (xic_style & XIMPreeditPosition
3407 ? XNSpotLocation
3408 : NULL),
3409 &spot,
3410 NULL);
3411 status_attr = XVaCreateNestedList (0,
3412 XNArea,
3413 &s_area,
3414 XNFontSet,
3415 xfs,
3416 XNForeground,
3417 FRAME_FOREGROUND_PIXEL (f),
3418 XNBackground,
3419 FRAME_BACKGROUND_PIXEL (f),
3420 NULL);
3422 xic = XCreateIC (xim,
3423 XNInputStyle, xic_style,
3424 XNClientWindow, FRAME_X_WINDOW(f),
3425 XNFocusWindow, FRAME_X_WINDOW(f),
3426 XNStatusAttributes, status_attr,
3427 XNPreeditAttributes, preedit_attr,
3428 NULL);
3429 XFree (preedit_attr);
3430 XFree (status_attr);
3433 FRAME_XIC (f) = xic;
3434 FRAME_XIC_STYLE (f) = xic_style;
3435 FRAME_XIC_FONTSET (f) = xfs;
3439 /* Destroy XIC and free XIC fontset of frame F, if any. */
3441 void
3442 free_frame_xic (f)
3443 struct frame *f;
3445 if (FRAME_XIC (f) == NULL)
3446 return;
3448 XDestroyIC (FRAME_XIC (f));
3449 if (FRAME_XIC_FONTSET (f))
3450 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3452 FRAME_XIC (f) = NULL;
3453 FRAME_XIC_FONTSET (f) = NULL;
3457 /* Place preedit area for XIC of window W's frame to specified
3458 pixel position X/Y. X and Y are relative to window W. */
3460 void
3461 xic_set_preeditarea (w, x, y)
3462 struct window *w;
3463 int x, y;
3465 struct frame *f = XFRAME (w->frame);
3466 XVaNestedList attr;
3467 XPoint spot;
3469 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3470 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3471 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3472 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3473 XFree (attr);
3477 /* Place status area for XIC in bottom right corner of frame F.. */
3479 void
3480 xic_set_statusarea (f)
3481 struct frame *f;
3483 XIC xic = FRAME_XIC (f);
3484 XVaNestedList attr;
3485 XRectangle area;
3486 XRectangle *needed;
3488 /* Negotiate geometry of status area. If input method has existing
3489 status area, use its current size. */
3490 area.x = area.y = area.width = area.height = 0;
3491 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3492 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3493 XFree (attr);
3495 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3496 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3497 XFree (attr);
3499 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3501 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3502 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3503 XFree (attr);
3506 area.width = needed->width;
3507 area.height = needed->height;
3508 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3509 area.y = (PIXEL_HEIGHT (f) - area.height
3510 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3511 XFree (needed);
3513 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3514 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3515 XFree (attr);
3519 /* Set X fontset for XIC of frame F, using base font name
3520 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3522 void
3523 xic_set_xfontset (f, base_fontname)
3524 struct frame *f;
3525 char *base_fontname;
3527 XVaNestedList attr;
3528 XFontSet xfs;
3530 xfs = xic_create_xfontset (f, base_fontname);
3532 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3533 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3534 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3535 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3536 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3537 XFree (attr);
3539 if (FRAME_XIC_FONTSET (f))
3540 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3541 FRAME_XIC_FONTSET (f) = xfs;
3544 #endif /* HAVE_X_I18N */
3548 #ifdef USE_X_TOOLKIT
3550 /* Create and set up the X widget for frame F. */
3552 static void
3553 x_window (f, window_prompting, minibuffer_only)
3554 struct frame *f;
3555 long window_prompting;
3556 int minibuffer_only;
3558 XClassHint class_hints;
3559 XSetWindowAttributes attributes;
3560 unsigned long attribute_mask;
3561 Widget shell_widget;
3562 Widget pane_widget;
3563 Widget frame_widget;
3564 Arg al [25];
3565 int ac;
3567 BLOCK_INPUT;
3569 /* Use the resource name as the top-level widget name
3570 for looking up resources. Make a non-Lisp copy
3571 for the window manager, so GC relocation won't bother it.
3573 Elsewhere we specify the window name for the window manager. */
3576 char *str = (char *) XSTRING (Vx_resource_name)->data;
3577 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3578 strcpy (f->namebuf, str);
3581 ac = 0;
3582 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3583 XtSetArg (al[ac], XtNinput, 1); ac++;
3584 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3585 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3586 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3587 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3588 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3589 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3590 applicationShellWidgetClass,
3591 FRAME_X_DISPLAY (f), al, ac);
3593 f->output_data.x->widget = shell_widget;
3594 /* maybe_set_screen_title_format (shell_widget); */
3596 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3597 (widget_value *) NULL,
3598 shell_widget, False,
3599 (lw_callback) NULL,
3600 (lw_callback) NULL,
3601 (lw_callback) NULL,
3602 (lw_callback) NULL);
3604 ac = 0;
3605 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3606 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3607 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3608 XtSetValues (pane_widget, al, ac);
3609 f->output_data.x->column_widget = pane_widget;
3611 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3612 the emacs screen when changing menubar. This reduces flickering. */
3614 ac = 0;
3615 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3616 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3617 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3618 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3619 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3620 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3621 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3622 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3623 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3624 al, ac);
3626 f->output_data.x->edit_widget = frame_widget;
3628 XtManageChild (frame_widget);
3630 /* Do some needed geometry management. */
3632 int len;
3633 char *tem, shell_position[32];
3634 Arg al[2];
3635 int ac = 0;
3636 int extra_borders = 0;
3637 int menubar_size
3638 = (f->output_data.x->menubar_widget
3639 ? (f->output_data.x->menubar_widget->core.height
3640 + f->output_data.x->menubar_widget->core.border_width)
3641 : 0);
3643 #if 0 /* Experimentally, we now get the right results
3644 for -geometry -0-0 without this. 24 Aug 96, rms. */
3645 if (FRAME_EXTERNAL_MENU_BAR (f))
3647 Dimension ibw = 0;
3648 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3649 menubar_size += ibw;
3651 #endif
3653 f->output_data.x->menubar_height = menubar_size;
3655 #ifndef USE_LUCID
3656 /* Motif seems to need this amount added to the sizes
3657 specified for the shell widget. The Athena/Lucid widgets don't.
3658 Both conclusions reached experimentally. -- rms. */
3659 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3660 &extra_borders, NULL);
3661 extra_borders *= 2;
3662 #endif
3664 /* Convert our geometry parameters into a geometry string
3665 and specify it.
3666 Note that we do not specify here whether the position
3667 is a user-specified or program-specified one.
3668 We pass that information later, in x_wm_set_size_hints. */
3670 int left = f->output_data.x->left_pos;
3671 int xneg = window_prompting & XNegative;
3672 int top = f->output_data.x->top_pos;
3673 int yneg = window_prompting & YNegative;
3674 if (xneg)
3675 left = -left;
3676 if (yneg)
3677 top = -top;
3679 if (window_prompting & USPosition)
3680 sprintf (shell_position, "=%dx%d%c%d%c%d",
3681 PIXEL_WIDTH (f) + extra_borders,
3682 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3683 (xneg ? '-' : '+'), left,
3684 (yneg ? '-' : '+'), top);
3685 else
3686 sprintf (shell_position, "=%dx%d",
3687 PIXEL_WIDTH (f) + extra_borders,
3688 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3691 len = strlen (shell_position) + 1;
3692 /* We don't free this because we don't know whether
3693 it is safe to free it while the frame exists.
3694 It isn't worth the trouble of arranging to free it
3695 when the frame is deleted. */
3696 tem = (char *) xmalloc (len);
3697 strncpy (tem, shell_position, len);
3698 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3699 XtSetValues (shell_widget, al, ac);
3702 XtManageChild (pane_widget);
3703 XtRealizeWidget (shell_widget);
3705 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3707 validate_x_resource_name ();
3709 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3710 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3711 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3713 #ifdef HAVE_X_I18N
3714 FRAME_XIC (f) = NULL;
3715 #ifdef USE_XIM
3716 create_frame_xic (f);
3717 #endif
3718 #endif
3720 f->output_data.x->wm_hints.input = True;
3721 f->output_data.x->wm_hints.flags |= InputHint;
3722 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3723 &f->output_data.x->wm_hints);
3725 hack_wm_protocols (f, shell_widget);
3727 #ifdef HACK_EDITRES
3728 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3729 #endif
3731 /* Do a stupid property change to force the server to generate a
3732 PropertyNotify event so that the event_stream server timestamp will
3733 be initialized to something relevant to the time we created the window.
3735 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3736 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3737 XA_ATOM, 32, PropModeAppend,
3738 (unsigned char*) NULL, 0);
3740 /* Make all the standard events reach the Emacs frame. */
3741 attributes.event_mask = STANDARD_EVENT_SET;
3743 #ifdef HAVE_X_I18N
3744 if (FRAME_XIC (f))
3746 /* XIM server might require some X events. */
3747 unsigned long fevent = NoEventMask;
3748 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3749 attributes.event_mask |= fevent;
3751 #endif /* HAVE_X_I18N */
3753 attribute_mask = CWEventMask;
3754 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3755 attribute_mask, &attributes);
3757 XtMapWidget (frame_widget);
3759 /* x_set_name normally ignores requests to set the name if the
3760 requested name is the same as the current name. This is the one
3761 place where that assumption isn't correct; f->name is set, but
3762 the X server hasn't been told. */
3764 Lisp_Object name;
3765 int explicit = f->explicit_name;
3767 f->explicit_name = 0;
3768 name = f->name;
3769 f->name = Qnil;
3770 x_set_name (f, name, explicit);
3773 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3774 f->output_data.x->text_cursor);
3776 UNBLOCK_INPUT;
3778 /* This is a no-op, except under Motif. Make sure main areas are
3779 set to something reasonable, in case we get an error later. */
3780 lw_set_main_areas (pane_widget, 0, frame_widget);
3783 #else /* not USE_X_TOOLKIT */
3785 /* Create and set up the X window for frame F. */
3787 void
3788 x_window (f)
3789 struct frame *f;
3792 XClassHint class_hints;
3793 XSetWindowAttributes attributes;
3794 unsigned long attribute_mask;
3796 attributes.background_pixel = f->output_data.x->background_pixel;
3797 attributes.border_pixel = f->output_data.x->border_pixel;
3798 attributes.bit_gravity = StaticGravity;
3799 attributes.backing_store = NotUseful;
3800 attributes.save_under = True;
3801 attributes.event_mask = STANDARD_EVENT_SET;
3802 attributes.colormap = FRAME_X_COLORMAP (f);
3803 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3804 | CWColormap);
3806 BLOCK_INPUT;
3807 FRAME_X_WINDOW (f)
3808 = XCreateWindow (FRAME_X_DISPLAY (f),
3809 f->output_data.x->parent_desc,
3810 f->output_data.x->left_pos,
3811 f->output_data.x->top_pos,
3812 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3813 f->output_data.x->border_width,
3814 CopyFromParent, /* depth */
3815 InputOutput, /* class */
3816 FRAME_X_VISUAL (f),
3817 attribute_mask, &attributes);
3819 #ifdef HAVE_X_I18N
3820 #ifdef USE_XIM
3821 create_frame_xic (f);
3822 if (FRAME_XIC (f))
3824 /* XIM server might require some X events. */
3825 unsigned long fevent = NoEventMask;
3826 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3827 attributes.event_mask |= fevent;
3828 attribute_mask = CWEventMask;
3829 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3830 attribute_mask, &attributes);
3832 #endif
3833 #endif /* HAVE_X_I18N */
3835 validate_x_resource_name ();
3837 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3838 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3839 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3841 /* The menubar is part of the ordinary display;
3842 it does not count in addition to the height of the window. */
3843 f->output_data.x->menubar_height = 0;
3845 /* This indicates that we use the "Passive Input" input model.
3846 Unless we do this, we don't get the Focus{In,Out} events that we
3847 need to draw the cursor correctly. Accursed bureaucrats.
3848 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3850 f->output_data.x->wm_hints.input = True;
3851 f->output_data.x->wm_hints.flags |= InputHint;
3852 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3853 &f->output_data.x->wm_hints);
3854 f->output_data.x->wm_hints.icon_pixmap = None;
3856 /* Request "save yourself" and "delete window" commands from wm. */
3858 Atom protocols[2];
3859 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3860 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3861 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3864 /* x_set_name normally ignores requests to set the name if the
3865 requested name is the same as the current name. This is the one
3866 place where that assumption isn't correct; f->name is set, but
3867 the X server hasn't been told. */
3869 Lisp_Object name;
3870 int explicit = f->explicit_name;
3872 f->explicit_name = 0;
3873 name = f->name;
3874 f->name = Qnil;
3875 x_set_name (f, name, explicit);
3878 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3879 f->output_data.x->text_cursor);
3881 UNBLOCK_INPUT;
3883 if (FRAME_X_WINDOW (f) == 0)
3884 error ("Unable to create window");
3887 #endif /* not USE_X_TOOLKIT */
3889 /* Handle the icon stuff for this window. Perhaps later we might
3890 want an x_set_icon_position which can be called interactively as
3891 well. */
3893 static void
3894 x_icon (f, parms)
3895 struct frame *f;
3896 Lisp_Object parms;
3898 Lisp_Object icon_x, icon_y;
3899 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3901 /* Set the position of the icon. Note that twm groups all
3902 icons in an icon window. */
3903 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3904 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3905 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3907 CHECK_NUMBER (icon_x, 0);
3908 CHECK_NUMBER (icon_y, 0);
3910 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3911 error ("Both left and top icon corners of icon must be specified");
3913 BLOCK_INPUT;
3915 if (! EQ (icon_x, Qunbound))
3916 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3918 /* Start up iconic or window? */
3919 x_wm_set_window_state
3920 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3921 Qicon)
3922 ? IconicState
3923 : NormalState));
3925 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3926 ? f->icon_name
3927 : f->name))->data);
3929 UNBLOCK_INPUT;
3932 /* Make the GCs needed for this window, setting the
3933 background, border and mouse colors; also create the
3934 mouse cursor and the gray border tile. */
3936 static char cursor_bits[] =
3938 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3939 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3944 static void
3945 x_make_gc (f)
3946 struct frame *f;
3948 XGCValues gc_values;
3950 BLOCK_INPUT;
3952 /* Create the GCs of this frame.
3953 Note that many default values are used. */
3955 /* Normal video */
3956 gc_values.font = f->output_data.x->font->fid;
3957 gc_values.foreground = f->output_data.x->foreground_pixel;
3958 gc_values.background = f->output_data.x->background_pixel;
3959 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3960 f->output_data.x->normal_gc
3961 = XCreateGC (FRAME_X_DISPLAY (f),
3962 FRAME_X_WINDOW (f),
3963 GCLineWidth | GCFont | GCForeground | GCBackground,
3964 &gc_values);
3966 /* Reverse video style. */
3967 gc_values.foreground = f->output_data.x->background_pixel;
3968 gc_values.background = f->output_data.x->foreground_pixel;
3969 f->output_data.x->reverse_gc
3970 = XCreateGC (FRAME_X_DISPLAY (f),
3971 FRAME_X_WINDOW (f),
3972 GCFont | GCForeground | GCBackground | GCLineWidth,
3973 &gc_values);
3975 /* Cursor has cursor-color background, background-color foreground. */
3976 gc_values.foreground = f->output_data.x->background_pixel;
3977 gc_values.background = f->output_data.x->cursor_pixel;
3978 gc_values.fill_style = FillOpaqueStippled;
3979 gc_values.stipple
3980 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3981 FRAME_X_DISPLAY_INFO (f)->root_window,
3982 cursor_bits, 16, 16);
3983 f->output_data.x->cursor_gc
3984 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3985 (GCFont | GCForeground | GCBackground
3986 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3987 &gc_values);
3989 /* Reliefs. */
3990 f->output_data.x->white_relief.gc = 0;
3991 f->output_data.x->black_relief.gc = 0;
3993 /* Create the gray border tile used when the pointer is not in
3994 the frame. Since this depends on the frame's pixel values,
3995 this must be done on a per-frame basis. */
3996 f->output_data.x->border_tile
3997 = (XCreatePixmapFromBitmapData
3998 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3999 gray_bits, gray_width, gray_height,
4000 f->output_data.x->foreground_pixel,
4001 f->output_data.x->background_pixel,
4002 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4004 UNBLOCK_INPUT;
4008 /* Free what was was allocated in x_make_gc. */
4010 void
4011 x_free_gcs (f)
4012 struct frame *f;
4014 Display *dpy = FRAME_X_DISPLAY (f);
4016 BLOCK_INPUT;
4018 if (f->output_data.x->normal_gc)
4020 XFreeGC (dpy, f->output_data.x->normal_gc);
4021 f->output_data.x->normal_gc = 0;
4024 if (f->output_data.x->reverse_gc)
4026 XFreeGC (dpy, f->output_data.x->reverse_gc);
4027 f->output_data.x->reverse_gc = 0;
4030 if (f->output_data.x->cursor_gc)
4032 XFreeGC (dpy, f->output_data.x->cursor_gc);
4033 f->output_data.x->cursor_gc = 0;
4036 if (f->output_data.x->border_tile)
4038 XFreePixmap (dpy, f->output_data.x->border_tile);
4039 f->output_data.x->border_tile = 0;
4042 UNBLOCK_INPUT;
4046 /* Handler for signals raised during x_create_frame and
4047 x_create_top_frame. FRAME is the frame which is partially
4048 constructed. */
4050 static Lisp_Object
4051 unwind_create_frame (frame)
4052 Lisp_Object frame;
4054 struct frame *f = XFRAME (frame);
4056 /* If frame is ``official'', nothing to do. */
4057 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4059 #if GLYPH_DEBUG
4060 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4061 #endif
4063 x_free_frame_resources (f);
4065 /* Check that reference counts are indeed correct. */
4066 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4067 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4068 return Qt;
4071 return Qnil;
4075 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4076 1, 1, 0,
4077 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
4078 Returns an Emacs frame object.\n\
4079 ALIST is an alist of frame parameters.\n\
4080 If the parameters specify that the frame should not have a minibuffer,\n\
4081 and do not specify a specific minibuffer window to use,\n\
4082 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4083 be shared by the new frame.\n\
4085 This function is an internal primitive--use `make-frame' instead.")
4086 (parms)
4087 Lisp_Object parms;
4089 struct frame *f;
4090 Lisp_Object frame, tem;
4091 Lisp_Object name;
4092 int minibuffer_only = 0;
4093 long window_prompting = 0;
4094 int width, height;
4095 int count = BINDING_STACK_SIZE ();
4096 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4097 Lisp_Object display;
4098 struct x_display_info *dpyinfo = NULL;
4099 Lisp_Object parent;
4100 struct kboard *kb;
4102 check_x ();
4104 /* Use this general default value to start with
4105 until we know if this frame has a specified name. */
4106 Vx_resource_name = Vinvocation_name;
4108 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4109 if (EQ (display, Qunbound))
4110 display = Qnil;
4111 dpyinfo = check_x_display_info (display);
4112 #ifdef MULTI_KBOARD
4113 kb = dpyinfo->kboard;
4114 #else
4115 kb = &the_only_kboard;
4116 #endif
4118 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4119 if (!STRINGP (name)
4120 && ! EQ (name, Qunbound)
4121 && ! NILP (name))
4122 error ("Invalid frame name--not a string or nil");
4124 if (STRINGP (name))
4125 Vx_resource_name = name;
4127 /* See if parent window is specified. */
4128 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4129 if (EQ (parent, Qunbound))
4130 parent = Qnil;
4131 if (! NILP (parent))
4132 CHECK_NUMBER (parent, 0);
4134 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4135 /* No need to protect DISPLAY because that's not used after passing
4136 it to make_frame_without_minibuffer. */
4137 frame = Qnil;
4138 GCPRO4 (parms, parent, name, frame);
4139 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4140 RES_TYPE_SYMBOL);
4141 if (EQ (tem, Qnone) || NILP (tem))
4142 f = make_frame_without_minibuffer (Qnil, kb, display);
4143 else if (EQ (tem, Qonly))
4145 f = make_minibuffer_frame ();
4146 minibuffer_only = 1;
4148 else if (WINDOWP (tem))
4149 f = make_frame_without_minibuffer (tem, kb, display);
4150 else
4151 f = make_frame (1);
4153 XSETFRAME (frame, f);
4155 /* Note that X Windows does support scroll bars. */
4156 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4158 f->output_method = output_x_window;
4159 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4160 bzero (f->output_data.x, sizeof (struct x_output));
4161 f->output_data.x->icon_bitmap = -1;
4162 f->output_data.x->fontset = -1;
4163 f->output_data.x->scroll_bar_foreground_pixel = -1;
4164 f->output_data.x->scroll_bar_background_pixel = -1;
4165 record_unwind_protect (unwind_create_frame, frame);
4167 f->icon_name
4168 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4169 RES_TYPE_STRING);
4170 if (! STRINGP (f->icon_name))
4171 f->icon_name = Qnil;
4173 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4174 #if GLYPH_DEBUG
4175 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4176 dpyinfo_refcount = dpyinfo->reference_count;
4177 #endif /* GLYPH_DEBUG */
4178 #ifdef MULTI_KBOARD
4179 FRAME_KBOARD (f) = kb;
4180 #endif
4182 /* These colors will be set anyway later, but it's important
4183 to get the color reference counts right, so initialize them! */
4185 Lisp_Object black;
4186 struct gcpro gcpro1;
4188 /* Function x_decode_color can signal an error. Make
4189 sure to initialize color slots so that we won't try
4190 to free colors we haven't allocated. */
4191 f->output_data.x->foreground_pixel = -1;
4192 f->output_data.x->background_pixel = -1;
4193 f->output_data.x->cursor_pixel = -1;
4194 f->output_data.x->cursor_foreground_pixel = -1;
4195 f->output_data.x->border_pixel = -1;
4196 f->output_data.x->mouse_pixel = -1;
4198 black = build_string ("black");
4199 GCPRO1 (black);
4200 f->output_data.x->foreground_pixel
4201 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4202 f->output_data.x->background_pixel
4203 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4204 f->output_data.x->cursor_pixel
4205 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4206 f->output_data.x->cursor_foreground_pixel
4207 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4208 f->output_data.x->border_pixel
4209 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4210 f->output_data.x->mouse_pixel
4211 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4212 UNGCPRO;
4215 /* Specify the parent under which to make this X window. */
4217 if (!NILP (parent))
4219 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4220 f->output_data.x->explicit_parent = 1;
4222 else
4224 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4225 f->output_data.x->explicit_parent = 0;
4228 /* Set the name; the functions to which we pass f expect the name to
4229 be set. */
4230 if (EQ (name, Qunbound) || NILP (name))
4232 f->name = build_string (dpyinfo->x_id_name);
4233 f->explicit_name = 0;
4235 else
4237 f->name = name;
4238 f->explicit_name = 1;
4239 /* use the frame's title when getting resources for this frame. */
4240 specbind (Qx_resource_name, name);
4243 /* Extract the window parameters from the supplied values
4244 that are needed to determine window geometry. */
4246 Lisp_Object font;
4248 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4250 BLOCK_INPUT;
4251 /* First, try whatever font the caller has specified. */
4252 if (STRINGP (font))
4254 tem = Fquery_fontset (font, Qnil);
4255 if (STRINGP (tem))
4256 font = x_new_fontset (f, XSTRING (tem)->data);
4257 else
4258 font = x_new_font (f, XSTRING (font)->data);
4261 /* Try out a font which we hope has bold and italic variations. */
4262 if (!STRINGP (font))
4263 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4264 if (!STRINGP (font))
4265 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4266 if (! STRINGP (font))
4267 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4268 if (! STRINGP (font))
4269 /* This was formerly the first thing tried, but it finds too many fonts
4270 and takes too long. */
4271 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4272 /* If those didn't work, look for something which will at least work. */
4273 if (! STRINGP (font))
4274 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4275 UNBLOCK_INPUT;
4276 if (! STRINGP (font))
4277 font = build_string ("fixed");
4279 x_default_parameter (f, parms, Qfont, font,
4280 "font", "Font", RES_TYPE_STRING);
4283 #ifdef USE_LUCID
4284 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4285 whereby it fails to get any font. */
4286 xlwmenu_default_font = f->output_data.x->font;
4287 #endif
4289 x_default_parameter (f, parms, Qborder_width, make_number (2),
4290 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4292 /* This defaults to 2 in order to match xterm. We recognize either
4293 internalBorderWidth or internalBorder (which is what xterm calls
4294 it). */
4295 if (NILP (Fassq (Qinternal_border_width, parms)))
4297 Lisp_Object value;
4299 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4300 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4301 if (! EQ (value, Qunbound))
4302 parms = Fcons (Fcons (Qinternal_border_width, value),
4303 parms);
4305 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4306 "internalBorderWidth", "internalBorderWidth",
4307 RES_TYPE_NUMBER);
4308 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4309 "verticalScrollBars", "ScrollBars",
4310 RES_TYPE_SYMBOL);
4312 /* Also do the stuff which must be set before the window exists. */
4313 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4314 "foreground", "Foreground", RES_TYPE_STRING);
4315 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4316 "background", "Background", RES_TYPE_STRING);
4317 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4318 "pointerColor", "Foreground", RES_TYPE_STRING);
4319 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4320 "cursorColor", "Foreground", RES_TYPE_STRING);
4321 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4322 "borderColor", "BorderColor", RES_TYPE_STRING);
4323 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4324 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4325 x_default_parameter (f, parms, Qline_spacing, Qnil,
4326 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4328 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4329 "scrollBarForeground",
4330 "ScrollBarForeground", 1);
4331 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4332 "scrollBarBackground",
4333 "ScrollBarBackground", 0);
4335 /* Init faces before x_default_parameter is called for scroll-bar
4336 parameters because that function calls x_set_scroll_bar_width,
4337 which calls change_frame_size, which calls Fset_window_buffer,
4338 which runs hooks, which call Fvertical_motion. At the end, we
4339 end up in init_iterator with a null face cache, which should not
4340 happen. */
4341 init_frame_faces (f);
4343 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4344 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4345 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4346 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4347 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4348 "bufferPredicate", "BufferPredicate",
4349 RES_TYPE_SYMBOL);
4350 x_default_parameter (f, parms, Qtitle, Qnil,
4351 "title", "Title", RES_TYPE_STRING);
4352 x_default_parameter (f, parms, Qwait_for_wm, Qt,
4353 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4355 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4357 /* Add the tool-bar height to the initial frame height so that the
4358 user gets a text display area of the size he specified with -g or
4359 via .Xdefaults. Later changes of the tool-bar height don't
4360 change the frame size. This is done so that users can create
4361 tall Emacs frames without having to guess how tall the tool-bar
4362 will get. */
4363 if (FRAME_TOOL_BAR_LINES (f))
4365 int margin, relief, bar_height;
4367 relief = (tool_bar_button_relief > 0
4368 ? tool_bar_button_relief
4369 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4371 if (INTEGERP (Vtool_bar_button_margin)
4372 && XINT (Vtool_bar_button_margin) > 0)
4373 margin = XFASTINT (Vtool_bar_button_margin);
4374 else if (CONSP (Vtool_bar_button_margin)
4375 && INTEGERP (XCDR (Vtool_bar_button_margin))
4376 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4377 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4378 else
4379 margin = 0;
4381 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4382 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4385 /* Compute the size of the X window. */
4386 window_prompting = x_figure_window_size (f, parms);
4388 if (window_prompting & XNegative)
4390 if (window_prompting & YNegative)
4391 f->output_data.x->win_gravity = SouthEastGravity;
4392 else
4393 f->output_data.x->win_gravity = NorthEastGravity;
4395 else
4397 if (window_prompting & YNegative)
4398 f->output_data.x->win_gravity = SouthWestGravity;
4399 else
4400 f->output_data.x->win_gravity = NorthWestGravity;
4403 f->output_data.x->size_hint_flags = window_prompting;
4405 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4406 f->no_split = minibuffer_only || EQ (tem, Qt);
4408 /* Create the X widget or window. */
4409 #ifdef USE_X_TOOLKIT
4410 x_window (f, window_prompting, minibuffer_only);
4411 #else
4412 x_window (f);
4413 #endif
4415 x_icon (f, parms);
4416 x_make_gc (f);
4418 /* Now consider the frame official. */
4419 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4420 Vframe_list = Fcons (frame, Vframe_list);
4422 /* We need to do this after creating the X window, so that the
4423 icon-creation functions can say whose icon they're describing. */
4424 x_default_parameter (f, parms, Qicon_type, Qnil,
4425 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4427 x_default_parameter (f, parms, Qauto_raise, Qnil,
4428 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4429 x_default_parameter (f, parms, Qauto_lower, Qnil,
4430 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4431 x_default_parameter (f, parms, Qcursor_type, Qbox,
4432 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4433 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4434 "scrollBarWidth", "ScrollBarWidth",
4435 RES_TYPE_NUMBER);
4437 /* Dimensions, especially f->height, must be done via change_frame_size.
4438 Change will not be effected unless different from the current
4439 f->height. */
4440 width = f->width;
4441 height = f->height;
4443 f->height = 0;
4444 SET_FRAME_WIDTH (f, 0);
4445 change_frame_size (f, height, width, 1, 0, 0);
4447 /* Set up faces after all frame parameters are known. This call
4448 also merges in face attributes specified for new frames. If we
4449 don't do this, the `menu' face for instance won't have the right
4450 colors, and the menu bar won't appear in the specified colors for
4451 new frames. */
4452 call1 (Qface_set_after_frame_default, frame);
4454 #ifdef USE_X_TOOLKIT
4455 /* Create the menu bar. */
4456 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4458 /* If this signals an error, we haven't set size hints for the
4459 frame and we didn't make it visible. */
4460 initialize_frame_menubar (f);
4462 /* This is a no-op, except under Motif where it arranges the
4463 main window for the widgets on it. */
4464 lw_set_main_areas (f->output_data.x->column_widget,
4465 f->output_data.x->menubar_widget,
4466 f->output_data.x->edit_widget);
4468 #endif /* USE_X_TOOLKIT */
4470 /* Tell the server what size and position, etc, we want, and how
4471 badly we want them. This should be done after we have the menu
4472 bar so that its size can be taken into account. */
4473 BLOCK_INPUT;
4474 x_wm_set_size_hint (f, window_prompting, 0);
4475 UNBLOCK_INPUT;
4477 /* Make the window appear on the frame and enable display, unless
4478 the caller says not to. However, with explicit parent, Emacs
4479 cannot control visibility, so don't try. */
4480 if (! f->output_data.x->explicit_parent)
4482 Lisp_Object visibility;
4484 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4485 RES_TYPE_SYMBOL);
4486 if (EQ (visibility, Qunbound))
4487 visibility = Qt;
4489 if (EQ (visibility, Qicon))
4490 x_iconify_frame (f);
4491 else if (! NILP (visibility))
4492 x_make_frame_visible (f);
4493 else
4494 /* Must have been Qnil. */
4498 UNGCPRO;
4500 /* Make sure windows on this frame appear in calls to next-window
4501 and similar functions. */
4502 Vwindow_list = Qnil;
4504 return unbind_to (count, frame);
4508 /* FRAME is used only to get a handle on the X display. We don't pass the
4509 display info directly because we're called from frame.c, which doesn't
4510 know about that structure. */
4512 Lisp_Object
4513 x_get_focus_frame (frame)
4514 struct frame *frame;
4516 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4517 Lisp_Object xfocus;
4518 if (! dpyinfo->x_focus_frame)
4519 return Qnil;
4521 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4522 return xfocus;
4526 /* In certain situations, when the window manager follows a
4527 click-to-focus policy, there seems to be no way around calling
4528 XSetInputFocus to give another frame the input focus .
4530 In an ideal world, XSetInputFocus should generally be avoided so
4531 that applications don't interfere with the window manager's focus
4532 policy. But I think it's okay to use when it's clearly done
4533 following a user-command. */
4535 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4536 "Set the input focus to FRAME.\n\
4537 FRAME nil means use the selected frame.")
4538 (frame)
4539 Lisp_Object frame;
4541 struct frame *f = check_x_frame (frame);
4542 Display *dpy = FRAME_X_DISPLAY (f);
4543 int count;
4545 BLOCK_INPUT;
4546 count = x_catch_errors (dpy);
4547 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4548 RevertToParent, CurrentTime);
4549 x_uncatch_errors (dpy, count);
4550 UNBLOCK_INPUT;
4552 return Qnil;
4556 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4557 "Internal function called by `color-defined-p', which see.")
4558 (color, frame)
4559 Lisp_Object color, frame;
4561 XColor foo;
4562 FRAME_PTR f = check_x_frame (frame);
4564 CHECK_STRING (color, 1);
4566 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4567 return Qt;
4568 else
4569 return Qnil;
4572 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4573 "Internal function called by `color-values', which see.")
4574 (color, frame)
4575 Lisp_Object color, frame;
4577 XColor foo;
4578 FRAME_PTR f = check_x_frame (frame);
4580 CHECK_STRING (color, 1);
4582 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4584 Lisp_Object rgb[3];
4586 rgb[0] = make_number (foo.red);
4587 rgb[1] = make_number (foo.green);
4588 rgb[2] = make_number (foo.blue);
4589 return Flist (3, rgb);
4591 else
4592 return Qnil;
4595 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4596 "Internal function called by `display-color-p', which see.")
4597 (display)
4598 Lisp_Object display;
4600 struct x_display_info *dpyinfo = check_x_display_info (display);
4602 if (dpyinfo->n_planes <= 2)
4603 return Qnil;
4605 switch (dpyinfo->visual->class)
4607 case StaticColor:
4608 case PseudoColor:
4609 case TrueColor:
4610 case DirectColor:
4611 return Qt;
4613 default:
4614 return Qnil;
4618 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4619 0, 1, 0,
4620 "Return t if the X display supports shades of gray.\n\
4621 Note that color displays do support shades of gray.\n\
4622 The optional argument DISPLAY specifies which display to ask about.\n\
4623 DISPLAY should be either a frame or a display name (a string).\n\
4624 If omitted or nil, that stands for the selected frame's display.")
4625 (display)
4626 Lisp_Object display;
4628 struct x_display_info *dpyinfo = check_x_display_info (display);
4630 if (dpyinfo->n_planes <= 1)
4631 return Qnil;
4633 switch (dpyinfo->visual->class)
4635 case StaticColor:
4636 case PseudoColor:
4637 case TrueColor:
4638 case DirectColor:
4639 case StaticGray:
4640 case GrayScale:
4641 return Qt;
4643 default:
4644 return Qnil;
4648 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4649 0, 1, 0,
4650 "Returns the width in pixels of the X display DISPLAY.\n\
4651 The optional argument DISPLAY specifies which display to ask about.\n\
4652 DISPLAY should be either a frame or a display name (a string).\n\
4653 If omitted or nil, that stands for the selected frame's display.")
4654 (display)
4655 Lisp_Object display;
4657 struct x_display_info *dpyinfo = check_x_display_info (display);
4659 return make_number (dpyinfo->width);
4662 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4663 Sx_display_pixel_height, 0, 1, 0,
4664 "Returns the height in pixels of the X display DISPLAY.\n\
4665 The optional argument DISPLAY specifies which display to ask about.\n\
4666 DISPLAY should be either a frame or a display name (a string).\n\
4667 If omitted or nil, that stands for the selected frame's display.")
4668 (display)
4669 Lisp_Object display;
4671 struct x_display_info *dpyinfo = check_x_display_info (display);
4673 return make_number (dpyinfo->height);
4676 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4677 0, 1, 0,
4678 "Returns the number of bitplanes of the X display DISPLAY.\n\
4679 The optional argument DISPLAY specifies which display to ask about.\n\
4680 DISPLAY should be either a frame or a display name (a string).\n\
4681 If omitted or nil, that stands for the selected frame's display.")
4682 (display)
4683 Lisp_Object display;
4685 struct x_display_info *dpyinfo = check_x_display_info (display);
4687 return make_number (dpyinfo->n_planes);
4690 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4691 0, 1, 0,
4692 "Returns the number of color cells of the X display DISPLAY.\n\
4693 The optional argument DISPLAY specifies which display to ask about.\n\
4694 DISPLAY should be either a frame or a display name (a string).\n\
4695 If omitted or nil, that stands for the selected frame's display.")
4696 (display)
4697 Lisp_Object display;
4699 struct x_display_info *dpyinfo = check_x_display_info (display);
4701 return make_number (DisplayCells (dpyinfo->display,
4702 XScreenNumberOfScreen (dpyinfo->screen)));
4705 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4706 Sx_server_max_request_size,
4707 0, 1, 0,
4708 "Returns the maximum request size of the X server of display DISPLAY.\n\
4709 The optional argument DISPLAY specifies which display to ask about.\n\
4710 DISPLAY should be either a frame or a display name (a string).\n\
4711 If omitted or nil, that stands for the selected frame's display.")
4712 (display)
4713 Lisp_Object display;
4715 struct x_display_info *dpyinfo = check_x_display_info (display);
4717 return make_number (MAXREQUEST (dpyinfo->display));
4720 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4721 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4722 The optional argument DISPLAY specifies which display to ask about.\n\
4723 DISPLAY should be either a frame or a display name (a string).\n\
4724 If omitted or nil, that stands for the selected frame's display.")
4725 (display)
4726 Lisp_Object display;
4728 struct x_display_info *dpyinfo = check_x_display_info (display);
4729 char *vendor = ServerVendor (dpyinfo->display);
4731 if (! vendor) vendor = "";
4732 return build_string (vendor);
4735 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4736 "Returns the version numbers of the X server of display DISPLAY.\n\
4737 The value is a list of three integers: the major and minor\n\
4738 version numbers of the X Protocol in use, and the vendor-specific release\n\
4739 number. See also the function `x-server-vendor'.\n\n\
4740 The optional argument DISPLAY specifies which display to ask about.\n\
4741 DISPLAY should be either a frame or a display name (a string).\n\
4742 If omitted or nil, that stands for the selected frame's display.")
4743 (display)
4744 Lisp_Object display;
4746 struct x_display_info *dpyinfo = check_x_display_info (display);
4747 Display *dpy = dpyinfo->display;
4749 return Fcons (make_number (ProtocolVersion (dpy)),
4750 Fcons (make_number (ProtocolRevision (dpy)),
4751 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4754 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4755 "Returns the number of screens on the X server of display DISPLAY.\n\
4756 The optional argument DISPLAY specifies which display to ask about.\n\
4757 DISPLAY should be either a frame or a display name (a string).\n\
4758 If omitted or nil, that stands for the selected frame's display.")
4759 (display)
4760 Lisp_Object display;
4762 struct x_display_info *dpyinfo = check_x_display_info (display);
4764 return make_number (ScreenCount (dpyinfo->display));
4767 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4768 "Returns the height in millimeters of the X display DISPLAY.\n\
4769 The optional argument DISPLAY specifies which display to ask about.\n\
4770 DISPLAY should be either a frame or a display name (a string).\n\
4771 If omitted or nil, that stands for the selected frame's display.")
4772 (display)
4773 Lisp_Object display;
4775 struct x_display_info *dpyinfo = check_x_display_info (display);
4777 return make_number (HeightMMOfScreen (dpyinfo->screen));
4780 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4781 "Returns the width in millimeters of the X display DISPLAY.\n\
4782 The optional argument DISPLAY specifies which display to ask about.\n\
4783 DISPLAY should be either a frame or a display name (a string).\n\
4784 If omitted or nil, that stands for the selected frame's display.")
4785 (display)
4786 Lisp_Object display;
4788 struct x_display_info *dpyinfo = check_x_display_info (display);
4790 return make_number (WidthMMOfScreen (dpyinfo->screen));
4793 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4794 Sx_display_backing_store, 0, 1, 0,
4795 "Returns an indication of whether X display DISPLAY does backing store.\n\
4796 The value may be `always', `when-mapped', or `not-useful'.\n\
4797 The optional argument DISPLAY specifies which display to ask about.\n\
4798 DISPLAY should be either a frame or a display name (a string).\n\
4799 If omitted or nil, that stands for the selected frame's display.")
4800 (display)
4801 Lisp_Object display;
4803 struct x_display_info *dpyinfo = check_x_display_info (display);
4804 Lisp_Object result;
4806 switch (DoesBackingStore (dpyinfo->screen))
4808 case Always:
4809 result = intern ("always");
4810 break;
4812 case WhenMapped:
4813 result = intern ("when-mapped");
4814 break;
4816 case NotUseful:
4817 result = intern ("not-useful");
4818 break;
4820 default:
4821 error ("Strange value for BackingStore parameter of screen");
4822 result = Qnil;
4825 return result;
4828 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4829 Sx_display_visual_class, 0, 1, 0,
4830 "Returns the visual class of the X display DISPLAY.\n\
4831 The value is one of the symbols `static-gray', `gray-scale',\n\
4832 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4833 The optional argument DISPLAY specifies which display to ask about.\n\
4834 DISPLAY should be either a frame or a display name (a string).\n\
4835 If omitted or nil, that stands for the selected frame's display.")
4836 (display)
4837 Lisp_Object display;
4839 struct x_display_info *dpyinfo = check_x_display_info (display);
4840 Lisp_Object result;
4842 switch (dpyinfo->visual->class)
4844 case StaticGray:
4845 result = intern ("static-gray");
4846 break;
4847 case GrayScale:
4848 result = intern ("gray-scale");
4849 break;
4850 case StaticColor:
4851 result = intern ("static-color");
4852 break;
4853 case PseudoColor:
4854 result = intern ("pseudo-color");
4855 break;
4856 case TrueColor:
4857 result = intern ("true-color");
4858 break;
4859 case DirectColor:
4860 result = intern ("direct-color");
4861 break;
4862 default:
4863 error ("Display has an unknown visual class");
4864 result = Qnil;
4867 return result;
4870 DEFUN ("x-display-save-under", Fx_display_save_under,
4871 Sx_display_save_under, 0, 1, 0,
4872 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4873 The optional argument DISPLAY specifies which display to ask about.\n\
4874 DISPLAY should be either a frame or a display name (a string).\n\
4875 If omitted or nil, that stands for the selected frame's display.")
4876 (display)
4877 Lisp_Object display;
4879 struct x_display_info *dpyinfo = check_x_display_info (display);
4881 if (DoesSaveUnders (dpyinfo->screen) == True)
4882 return Qt;
4883 else
4884 return Qnil;
4888 x_pixel_width (f)
4889 register struct frame *f;
4891 return PIXEL_WIDTH (f);
4895 x_pixel_height (f)
4896 register struct frame *f;
4898 return PIXEL_HEIGHT (f);
4902 x_char_width (f)
4903 register struct frame *f;
4905 return FONT_WIDTH (f->output_data.x->font);
4909 x_char_height (f)
4910 register struct frame *f;
4912 return f->output_data.x->line_height;
4916 x_screen_planes (f)
4917 register struct frame *f;
4919 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4924 /************************************************************************
4925 X Displays
4926 ************************************************************************/
4929 /* Mapping visual names to visuals. */
4931 static struct visual_class
4933 char *name;
4934 int class;
4936 visual_classes[] =
4938 {"StaticGray", StaticGray},
4939 {"GrayScale", GrayScale},
4940 {"StaticColor", StaticColor},
4941 {"PseudoColor", PseudoColor},
4942 {"TrueColor", TrueColor},
4943 {"DirectColor", DirectColor},
4944 NULL
4948 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4950 /* Value is the screen number of screen SCR. This is a substitute for
4951 the X function with the same name when that doesn't exist. */
4954 XScreenNumberOfScreen (scr)
4955 register Screen *scr;
4957 Display *dpy = scr->display;
4958 int i;
4960 for (i = 0; i < dpy->nscreens; ++i)
4961 if (scr == dpy->screens[i])
4962 break;
4964 return i;
4967 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4970 /* Select the visual that should be used on display DPYINFO. Set
4971 members of DPYINFO appropriately. Called from x_term_init. */
4973 void
4974 select_visual (dpyinfo)
4975 struct x_display_info *dpyinfo;
4977 Display *dpy = dpyinfo->display;
4978 Screen *screen = dpyinfo->screen;
4979 Lisp_Object value;
4981 /* See if a visual is specified. */
4982 value = display_x_get_resource (dpyinfo,
4983 build_string ("visualClass"),
4984 build_string ("VisualClass"),
4985 Qnil, Qnil);
4986 if (STRINGP (value))
4988 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4989 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4990 depth, a decimal number. NAME is compared with case ignored. */
4991 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4992 char *dash;
4993 int i, class = -1;
4994 XVisualInfo vinfo;
4996 strcpy (s, XSTRING (value)->data);
4997 dash = index (s, '-');
4998 if (dash)
5000 dpyinfo->n_planes = atoi (dash + 1);
5001 *dash = '\0';
5003 else
5004 /* We won't find a matching visual with depth 0, so that
5005 an error will be printed below. */
5006 dpyinfo->n_planes = 0;
5008 /* Determine the visual class. */
5009 for (i = 0; visual_classes[i].name; ++i)
5010 if (xstricmp (s, visual_classes[i].name) == 0)
5012 class = visual_classes[i].class;
5013 break;
5016 /* Look up a matching visual for the specified class. */
5017 if (class == -1
5018 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5019 dpyinfo->n_planes, class, &vinfo))
5020 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
5022 dpyinfo->visual = vinfo.visual;
5024 else
5026 int n_visuals;
5027 XVisualInfo *vinfo, vinfo_template;
5029 dpyinfo->visual = DefaultVisualOfScreen (screen);
5031 #ifdef HAVE_X11R4
5032 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5033 #else
5034 vinfo_template.visualid = dpyinfo->visual->visualid;
5035 #endif
5036 vinfo_template.screen = XScreenNumberOfScreen (screen);
5037 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5038 &vinfo_template, &n_visuals);
5039 if (n_visuals != 1)
5040 fatal ("Can't get proper X visual info");
5042 dpyinfo->n_planes = vinfo->depth;
5043 XFree ((char *) vinfo);
5048 /* Return the X display structure for the display named NAME.
5049 Open a new connection if necessary. */
5051 struct x_display_info *
5052 x_display_info_for_name (name)
5053 Lisp_Object name;
5055 Lisp_Object names;
5056 struct x_display_info *dpyinfo;
5058 CHECK_STRING (name, 0);
5060 if (! EQ (Vwindow_system, intern ("x")))
5061 error ("Not using X Windows");
5063 for (dpyinfo = x_display_list, names = x_display_name_list;
5064 dpyinfo;
5065 dpyinfo = dpyinfo->next, names = XCDR (names))
5067 Lisp_Object tem;
5068 tem = Fstring_equal (XCAR (XCAR (names)), name);
5069 if (!NILP (tem))
5070 return dpyinfo;
5073 /* Use this general default value to start with. */
5074 Vx_resource_name = Vinvocation_name;
5076 validate_x_resource_name ();
5078 dpyinfo = x_term_init (name, (char *)0,
5079 (char *) XSTRING (Vx_resource_name)->data);
5081 if (dpyinfo == 0)
5082 error ("Cannot connect to X server %s", XSTRING (name)->data);
5084 x_in_use = 1;
5085 XSETFASTINT (Vwindow_system_version, 11);
5087 return dpyinfo;
5091 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5092 1, 3, 0, "Open a connection to an X server.\n\
5093 DISPLAY is the name of the display to connect to.\n\
5094 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5095 If the optional third arg MUST-SUCCEED is non-nil,\n\
5096 terminate Emacs if we can't open the connection.")
5097 (display, xrm_string, must_succeed)
5098 Lisp_Object display, xrm_string, must_succeed;
5100 unsigned char *xrm_option;
5101 struct x_display_info *dpyinfo;
5103 CHECK_STRING (display, 0);
5104 if (! NILP (xrm_string))
5105 CHECK_STRING (xrm_string, 1);
5107 if (! EQ (Vwindow_system, intern ("x")))
5108 error ("Not using X Windows");
5110 if (! NILP (xrm_string))
5111 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5112 else
5113 xrm_option = (unsigned char *) 0;
5115 validate_x_resource_name ();
5117 /* This is what opens the connection and sets x_current_display.
5118 This also initializes many symbols, such as those used for input. */
5119 dpyinfo = x_term_init (display, xrm_option,
5120 (char *) XSTRING (Vx_resource_name)->data);
5122 if (dpyinfo == 0)
5124 if (!NILP (must_succeed))
5125 fatal ("Cannot connect to X server %s.\n\
5126 Check the DISPLAY environment variable or use `-d'.\n\
5127 Also use the `xhost' program to verify that it is set to permit\n\
5128 connections from your machine.\n",
5129 XSTRING (display)->data);
5130 else
5131 error ("Cannot connect to X server %s", XSTRING (display)->data);
5134 x_in_use = 1;
5136 XSETFASTINT (Vwindow_system_version, 11);
5137 return Qnil;
5140 DEFUN ("x-close-connection", Fx_close_connection,
5141 Sx_close_connection, 1, 1, 0,
5142 "Close the connection to DISPLAY's X server.\n\
5143 For DISPLAY, specify either a frame or a display name (a string).\n\
5144 If DISPLAY is nil, that stands for the selected frame's display.")
5145 (display)
5146 Lisp_Object display;
5148 struct x_display_info *dpyinfo = check_x_display_info (display);
5149 int i;
5151 if (dpyinfo->reference_count > 0)
5152 error ("Display still has frames on it");
5154 BLOCK_INPUT;
5155 /* Free the fonts in the font table. */
5156 for (i = 0; i < dpyinfo->n_fonts; i++)
5157 if (dpyinfo->font_table[i].name)
5159 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5160 xfree (dpyinfo->font_table[i].full_name);
5161 xfree (dpyinfo->font_table[i].name);
5162 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5165 x_destroy_all_bitmaps (dpyinfo);
5166 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5168 #ifdef USE_X_TOOLKIT
5169 XtCloseDisplay (dpyinfo->display);
5170 #else
5171 XCloseDisplay (dpyinfo->display);
5172 #endif
5174 x_delete_display (dpyinfo);
5175 UNBLOCK_INPUT;
5177 return Qnil;
5180 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5181 "Return the list of display names that Emacs has connections to.")
5184 Lisp_Object tail, result;
5186 result = Qnil;
5187 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5188 result = Fcons (XCAR (XCAR (tail)), result);
5190 return result;
5193 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5194 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5195 If ON is nil, allow buffering of requests.\n\
5196 Turning on synchronization prohibits the Xlib routines from buffering\n\
5197 requests and seriously degrades performance, but makes debugging much\n\
5198 easier.\n\
5199 The optional second argument DISPLAY specifies which display to act on.\n\
5200 DISPLAY should be either a frame or a display name (a string).\n\
5201 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5202 (on, display)
5203 Lisp_Object display, on;
5205 struct x_display_info *dpyinfo = check_x_display_info (display);
5207 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5209 return Qnil;
5212 /* Wait for responses to all X commands issued so far for frame F. */
5214 void
5215 x_sync (f)
5216 FRAME_PTR f;
5218 BLOCK_INPUT;
5219 XSync (FRAME_X_DISPLAY (f), False);
5220 UNBLOCK_INPUT;
5224 /***********************************************************************
5225 Image types
5226 ***********************************************************************/
5228 /* Value is the number of elements of vector VECTOR. */
5230 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5232 /* List of supported image types. Use define_image_type to add new
5233 types. Use lookup_image_type to find a type for a given symbol. */
5235 static struct image_type *image_types;
5237 /* The symbol `image' which is the car of the lists used to represent
5238 images in Lisp. */
5240 extern Lisp_Object Qimage;
5242 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5244 Lisp_Object Qxbm;
5246 /* Keywords. */
5248 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5249 extern Lisp_Object QCdata;
5250 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5251 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5252 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5254 /* Other symbols. */
5256 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5258 /* Time in seconds after which images should be removed from the cache
5259 if not displayed. */
5261 Lisp_Object Vimage_cache_eviction_delay;
5263 /* Function prototypes. */
5265 static void define_image_type P_ ((struct image_type *type));
5266 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5267 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5268 static void x_laplace P_ ((struct frame *, struct image *));
5269 static void x_emboss P_ ((struct frame *, struct image *));
5270 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5271 Lisp_Object));
5274 /* Define a new image type from TYPE. This adds a copy of TYPE to
5275 image_types and adds the symbol *TYPE->type to Vimage_types. */
5277 static void
5278 define_image_type (type)
5279 struct image_type *type;
5281 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5282 The initialized data segment is read-only. */
5283 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5284 bcopy (type, p, sizeof *p);
5285 p->next = image_types;
5286 image_types = p;
5287 Vimage_types = Fcons (*p->type, Vimage_types);
5291 /* Look up image type SYMBOL, and return a pointer to its image_type
5292 structure. Value is null if SYMBOL is not a known image type. */
5294 static INLINE struct image_type *
5295 lookup_image_type (symbol)
5296 Lisp_Object symbol;
5298 struct image_type *type;
5300 for (type = image_types; type; type = type->next)
5301 if (EQ (symbol, *type->type))
5302 break;
5304 return type;
5308 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5309 valid image specification is a list whose car is the symbol
5310 `image', and whose rest is a property list. The property list must
5311 contain a value for key `:type'. That value must be the name of a
5312 supported image type. The rest of the property list depends on the
5313 image type. */
5316 valid_image_p (object)
5317 Lisp_Object object;
5319 int valid_p = 0;
5321 if (CONSP (object) && EQ (XCAR (object), Qimage))
5323 Lisp_Object tem;
5325 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5326 if (EQ (XCAR (tem), QCtype))
5328 tem = XCDR (tem);
5329 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5331 struct image_type *type;
5332 type = lookup_image_type (XCAR (tem));
5333 if (type)
5334 valid_p = type->valid_p (object);
5337 break;
5341 return valid_p;
5345 /* Log error message with format string FORMAT and argument ARG.
5346 Signaling an error, e.g. when an image cannot be loaded, is not a
5347 good idea because this would interrupt redisplay, and the error
5348 message display would lead to another redisplay. This function
5349 therefore simply displays a message. */
5351 static void
5352 image_error (format, arg1, arg2)
5353 char *format;
5354 Lisp_Object arg1, arg2;
5356 add_to_log (format, arg1, arg2);
5361 /***********************************************************************
5362 Image specifications
5363 ***********************************************************************/
5365 enum image_value_type
5367 IMAGE_DONT_CHECK_VALUE_TYPE,
5368 IMAGE_STRING_VALUE,
5369 IMAGE_STRING_OR_NIL_VALUE,
5370 IMAGE_SYMBOL_VALUE,
5371 IMAGE_POSITIVE_INTEGER_VALUE,
5372 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5373 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5374 IMAGE_ASCENT_VALUE,
5375 IMAGE_INTEGER_VALUE,
5376 IMAGE_FUNCTION_VALUE,
5377 IMAGE_NUMBER_VALUE,
5378 IMAGE_BOOL_VALUE
5381 /* Structure used when parsing image specifications. */
5383 struct image_keyword
5385 /* Name of keyword. */
5386 char *name;
5388 /* The type of value allowed. */
5389 enum image_value_type type;
5391 /* Non-zero means key must be present. */
5392 int mandatory_p;
5394 /* Used to recognize duplicate keywords in a property list. */
5395 int count;
5397 /* The value that was found. */
5398 Lisp_Object value;
5402 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5403 int, Lisp_Object));
5404 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5407 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5408 has the format (image KEYWORD VALUE ...). One of the keyword/
5409 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5410 image_keywords structures of size NKEYWORDS describing other
5411 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5413 static int
5414 parse_image_spec (spec, keywords, nkeywords, type)
5415 Lisp_Object spec;
5416 struct image_keyword *keywords;
5417 int nkeywords;
5418 Lisp_Object type;
5420 int i;
5421 Lisp_Object plist;
5423 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5424 return 0;
5426 plist = XCDR (spec);
5427 while (CONSP (plist))
5429 Lisp_Object key, value;
5431 /* First element of a pair must be a symbol. */
5432 key = XCAR (plist);
5433 plist = XCDR (plist);
5434 if (!SYMBOLP (key))
5435 return 0;
5437 /* There must follow a value. */
5438 if (!CONSP (plist))
5439 return 0;
5440 value = XCAR (plist);
5441 plist = XCDR (plist);
5443 /* Find key in KEYWORDS. Error if not found. */
5444 for (i = 0; i < nkeywords; ++i)
5445 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5446 break;
5448 if (i == nkeywords)
5449 continue;
5451 /* Record that we recognized the keyword. If a keywords
5452 was found more than once, it's an error. */
5453 keywords[i].value = value;
5454 ++keywords[i].count;
5456 if (keywords[i].count > 1)
5457 return 0;
5459 /* Check type of value against allowed type. */
5460 switch (keywords[i].type)
5462 case IMAGE_STRING_VALUE:
5463 if (!STRINGP (value))
5464 return 0;
5465 break;
5467 case IMAGE_STRING_OR_NIL_VALUE:
5468 if (!STRINGP (value) && !NILP (value))
5469 return 0;
5470 break;
5472 case IMAGE_SYMBOL_VALUE:
5473 if (!SYMBOLP (value))
5474 return 0;
5475 break;
5477 case IMAGE_POSITIVE_INTEGER_VALUE:
5478 if (!INTEGERP (value) || XINT (value) <= 0)
5479 return 0;
5480 break;
5482 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5483 if (INTEGERP (value) && XINT (value) >= 0)
5484 break;
5485 if (CONSP (value)
5486 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5487 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5488 break;
5489 return 0;
5491 case IMAGE_ASCENT_VALUE:
5492 if (SYMBOLP (value) && EQ (value, Qcenter))
5493 break;
5494 else if (INTEGERP (value)
5495 && XINT (value) >= 0
5496 && XINT (value) <= 100)
5497 break;
5498 return 0;
5500 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5501 if (!INTEGERP (value) || XINT (value) < 0)
5502 return 0;
5503 break;
5505 case IMAGE_DONT_CHECK_VALUE_TYPE:
5506 break;
5508 case IMAGE_FUNCTION_VALUE:
5509 value = indirect_function (value);
5510 if (SUBRP (value)
5511 || COMPILEDP (value)
5512 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5513 break;
5514 return 0;
5516 case IMAGE_NUMBER_VALUE:
5517 if (!INTEGERP (value) && !FLOATP (value))
5518 return 0;
5519 break;
5521 case IMAGE_INTEGER_VALUE:
5522 if (!INTEGERP (value))
5523 return 0;
5524 break;
5526 case IMAGE_BOOL_VALUE:
5527 if (!NILP (value) && !EQ (value, Qt))
5528 return 0;
5529 break;
5531 default:
5532 abort ();
5533 break;
5536 if (EQ (key, QCtype) && !EQ (type, value))
5537 return 0;
5540 /* Check that all mandatory fields are present. */
5541 for (i = 0; i < nkeywords; ++i)
5542 if (keywords[i].mandatory_p && keywords[i].count == 0)
5543 return 0;
5545 return NILP (plist);
5549 /* Return the value of KEY in image specification SPEC. Value is nil
5550 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5551 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5553 static Lisp_Object
5554 image_spec_value (spec, key, found)
5555 Lisp_Object spec, key;
5556 int *found;
5558 Lisp_Object tail;
5560 xassert (valid_image_p (spec));
5562 for (tail = XCDR (spec);
5563 CONSP (tail) && CONSP (XCDR (tail));
5564 tail = XCDR (XCDR (tail)))
5566 if (EQ (XCAR (tail), key))
5568 if (found)
5569 *found = 1;
5570 return XCAR (XCDR (tail));
5574 if (found)
5575 *found = 0;
5576 return Qnil;
5580 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5581 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5582 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5583 size in canonical character units.\n\
5584 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5585 or omitted means use the selected frame.")
5586 (spec, pixels, frame)
5587 Lisp_Object spec, pixels, frame;
5589 Lisp_Object size;
5591 size = Qnil;
5592 if (valid_image_p (spec))
5594 struct frame *f = check_x_frame (frame);
5595 int id = lookup_image (f, spec);
5596 struct image *img = IMAGE_FROM_ID (f, id);
5597 int width = img->width + 2 * img->hmargin;
5598 int height = img->height + 2 * img->vmargin;
5600 if (NILP (pixels))
5601 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5602 make_float ((double) height / CANON_Y_UNIT (f)));
5603 else
5604 size = Fcons (make_number (width), make_number (height));
5606 else
5607 error ("Invalid image specification");
5609 return size;
5613 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5614 "Return t if image SPEC has a mask bitmap.\n\
5615 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5616 or omitted means use the selected frame.")
5617 (spec, frame)
5618 Lisp_Object spec, frame;
5620 Lisp_Object mask;
5622 mask = Qnil;
5623 if (valid_image_p (spec))
5625 struct frame *f = check_x_frame (frame);
5626 int id = lookup_image (f, spec);
5627 struct image *img = IMAGE_FROM_ID (f, id);
5628 if (img->mask)
5629 mask = Qt;
5631 else
5632 error ("Invalid image specification");
5634 return mask;
5639 /***********************************************************************
5640 Image type independent image structures
5641 ***********************************************************************/
5643 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5644 static void free_image P_ ((struct frame *f, struct image *img));
5647 /* Allocate and return a new image structure for image specification
5648 SPEC. SPEC has a hash value of HASH. */
5650 static struct image *
5651 make_image (spec, hash)
5652 Lisp_Object spec;
5653 unsigned hash;
5655 struct image *img = (struct image *) xmalloc (sizeof *img);
5657 xassert (valid_image_p (spec));
5658 bzero (img, sizeof *img);
5659 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5660 xassert (img->type != NULL);
5661 img->spec = spec;
5662 img->data.lisp_val = Qnil;
5663 img->ascent = DEFAULT_IMAGE_ASCENT;
5664 img->hash = hash;
5665 return img;
5669 /* Free image IMG which was used on frame F, including its resources. */
5671 static void
5672 free_image (f, img)
5673 struct frame *f;
5674 struct image *img;
5676 if (img)
5678 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5680 /* Remove IMG from the hash table of its cache. */
5681 if (img->prev)
5682 img->prev->next = img->next;
5683 else
5684 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5686 if (img->next)
5687 img->next->prev = img->prev;
5689 c->images[img->id] = NULL;
5691 /* Free resources, then free IMG. */
5692 img->type->free (f, img);
5693 xfree (img);
5698 /* Prepare image IMG for display on frame F. Must be called before
5699 drawing an image. */
5701 void
5702 prepare_image_for_display (f, img)
5703 struct frame *f;
5704 struct image *img;
5706 EMACS_TIME t;
5708 /* We're about to display IMG, so set its timestamp to `now'. */
5709 EMACS_GET_TIME (t);
5710 img->timestamp = EMACS_SECS (t);
5712 /* If IMG doesn't have a pixmap yet, load it now, using the image
5713 type dependent loader function. */
5714 if (img->pixmap == None && !img->load_failed_p)
5715 img->load_failed_p = img->type->load (f, img) == 0;
5719 /* Value is the number of pixels for the ascent of image IMG when
5720 drawn in face FACE. */
5723 image_ascent (img, face)
5724 struct image *img;
5725 struct face *face;
5727 int height = img->height + img->vmargin;
5728 int ascent;
5730 if (img->ascent == CENTERED_IMAGE_ASCENT)
5732 if (face->font)
5733 /* This expression is arranged so that if the image can't be
5734 exactly centered, it will be moved slightly up. This is
5735 because a typical font is `top-heavy' (due to the presence
5736 uppercase letters), so the image placement should err towards
5737 being top-heavy too. It also just generally looks better. */
5738 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5739 else
5740 ascent = height / 2;
5742 else
5743 ascent = height * img->ascent / 100.0;
5745 return ascent;
5750 /***********************************************************************
5751 Helper functions for X image types
5752 ***********************************************************************/
5754 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5755 int, int));
5756 static void x_clear_image P_ ((struct frame *f, struct image *img));
5757 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5758 struct image *img,
5759 Lisp_Object color_name,
5760 unsigned long dflt));
5763 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5764 free the pixmap if any. MASK_P non-zero means clear the mask
5765 pixmap if any. COLORS_P non-zero means free colors allocated for
5766 the image, if any. */
5768 static void
5769 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5770 struct frame *f;
5771 struct image *img;
5772 int pixmap_p, mask_p, colors_p;
5774 if (pixmap_p && img->pixmap)
5776 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5777 img->pixmap = None;
5780 if (mask_p && img->mask)
5782 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5783 img->mask = None;
5786 if (colors_p && img->ncolors)
5788 x_free_colors (f, img->colors, img->ncolors);
5789 xfree (img->colors);
5790 img->colors = NULL;
5791 img->ncolors = 0;
5795 /* Free X resources of image IMG which is used on frame F. */
5797 static void
5798 x_clear_image (f, img)
5799 struct frame *f;
5800 struct image *img;
5802 BLOCK_INPUT;
5803 x_clear_image_1 (f, img, 1, 1, 1);
5804 UNBLOCK_INPUT;
5808 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5809 cannot be allocated, use DFLT. Add a newly allocated color to
5810 IMG->colors, so that it can be freed again. Value is the pixel
5811 color. */
5813 static unsigned long
5814 x_alloc_image_color (f, img, color_name, dflt)
5815 struct frame *f;
5816 struct image *img;
5817 Lisp_Object color_name;
5818 unsigned long dflt;
5820 XColor color;
5821 unsigned long result;
5823 xassert (STRINGP (color_name));
5825 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5827 /* This isn't called frequently so we get away with simply
5828 reallocating the color vector to the needed size, here. */
5829 ++img->ncolors;
5830 img->colors =
5831 (unsigned long *) xrealloc (img->colors,
5832 img->ncolors * sizeof *img->colors);
5833 img->colors[img->ncolors - 1] = color.pixel;
5834 result = color.pixel;
5836 else
5837 result = dflt;
5839 return result;
5844 /***********************************************************************
5845 Image Cache
5846 ***********************************************************************/
5848 static void cache_image P_ ((struct frame *f, struct image *img));
5849 static void postprocess_image P_ ((struct frame *, struct image *));
5852 /* Return a new, initialized image cache that is allocated from the
5853 heap. Call free_image_cache to free an image cache. */
5855 struct image_cache *
5856 make_image_cache ()
5858 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5859 int size;
5861 bzero (c, sizeof *c);
5862 c->size = 50;
5863 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5864 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5865 c->buckets = (struct image **) xmalloc (size);
5866 bzero (c->buckets, size);
5867 return c;
5871 /* Free image cache of frame F. Be aware that X frames share images
5872 caches. */
5874 void
5875 free_image_cache (f)
5876 struct frame *f;
5878 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5879 if (c)
5881 int i;
5883 /* Cache should not be referenced by any frame when freed. */
5884 xassert (c->refcount == 0);
5886 for (i = 0; i < c->used; ++i)
5887 free_image (f, c->images[i]);
5888 xfree (c->images);
5889 xfree (c->buckets);
5890 xfree (c);
5891 FRAME_X_IMAGE_CACHE (f) = NULL;
5896 /* Clear image cache of frame F. FORCE_P non-zero means free all
5897 images. FORCE_P zero means clear only images that haven't been
5898 displayed for some time. Should be called from time to time to
5899 reduce the number of loaded images. If image-eviction-seconds is
5900 non-nil, this frees images in the cache which weren't displayed for
5901 at least that many seconds. */
5903 void
5904 clear_image_cache (f, force_p)
5905 struct frame *f;
5906 int force_p;
5908 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5910 if (c && INTEGERP (Vimage_cache_eviction_delay))
5912 EMACS_TIME t;
5913 unsigned long old;
5914 int i, nfreed;
5916 EMACS_GET_TIME (t);
5917 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5919 /* Block input so that we won't be interrupted by a SIGIO
5920 while being in an inconsistent state. */
5921 BLOCK_INPUT;
5923 for (i = nfreed = 0; i < c->used; ++i)
5925 struct image *img = c->images[i];
5926 if (img != NULL
5927 && (force_p || img->timestamp < old))
5929 free_image (f, img);
5930 ++nfreed;
5934 /* We may be clearing the image cache because, for example,
5935 Emacs was iconified for a longer period of time. In that
5936 case, current matrices may still contain references to
5937 images freed above. So, clear these matrices. */
5938 if (nfreed)
5940 Lisp_Object tail, frame;
5942 FOR_EACH_FRAME (tail, frame)
5944 struct frame *f = XFRAME (frame);
5945 if (FRAME_X_P (f)
5946 && FRAME_X_IMAGE_CACHE (f) == c)
5947 clear_current_matrices (f);
5950 ++windows_or_buffers_changed;
5953 UNBLOCK_INPUT;
5958 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5959 0, 1, 0,
5960 "Clear the image cache of FRAME.\n\
5961 FRAME nil or omitted means use the selected frame.\n\
5962 FRAME t means clear the image caches of all frames.")
5963 (frame)
5964 Lisp_Object frame;
5966 if (EQ (frame, Qt))
5968 Lisp_Object tail;
5970 FOR_EACH_FRAME (tail, frame)
5971 if (FRAME_X_P (XFRAME (frame)))
5972 clear_image_cache (XFRAME (frame), 1);
5974 else
5975 clear_image_cache (check_x_frame (frame), 1);
5977 return Qnil;
5981 /* Compute masks and transform image IMG on frame F, as specified
5982 by the image's specification, */
5984 static void
5985 postprocess_image (f, img)
5986 struct frame *f;
5987 struct image *img;
5989 /* Manipulation of the image's mask. */
5990 if (img->pixmap)
5992 Lisp_Object conversion, spec;
5993 Lisp_Object mask;
5995 spec = img->spec;
5997 /* `:heuristic-mask t'
5998 `:mask heuristic'
5999 means build a mask heuristically.
6000 `:heuristic-mask (R G B)'
6001 `:mask (heuristic (R G B))'
6002 means build a mask from color (R G B) in the
6003 image.
6004 `:mask nil'
6005 means remove a mask, if any. */
6007 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6008 if (!NILP (mask))
6009 x_build_heuristic_mask (f, img, mask);
6010 else
6012 int found_p;
6014 mask = image_spec_value (spec, QCmask, &found_p);
6016 if (EQ (mask, Qheuristic))
6017 x_build_heuristic_mask (f, img, Qt);
6018 else if (CONSP (mask)
6019 && EQ (XCAR (mask), Qheuristic))
6021 if (CONSP (XCDR (mask)))
6022 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6023 else
6024 x_build_heuristic_mask (f, img, XCDR (mask));
6026 else if (NILP (mask) && found_p && img->mask)
6028 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6029 img->mask = None;
6034 /* Should we apply an image transformation algorithm? */
6035 conversion = image_spec_value (spec, QCconversion, NULL);
6036 if (EQ (conversion, Qdisabled))
6037 x_disable_image (f, img);
6038 else if (EQ (conversion, Qlaplace))
6039 x_laplace (f, img);
6040 else if (EQ (conversion, Qemboss))
6041 x_emboss (f, img);
6042 else if (CONSP (conversion)
6043 && EQ (XCAR (conversion), Qedge_detection))
6045 Lisp_Object tem;
6046 tem = XCDR (conversion);
6047 if (CONSP (tem))
6048 x_edge_detection (f, img,
6049 Fplist_get (tem, QCmatrix),
6050 Fplist_get (tem, QCcolor_adjustment));
6056 /* Return the id of image with Lisp specification SPEC on frame F.
6057 SPEC must be a valid Lisp image specification (see valid_image_p). */
6060 lookup_image (f, spec)
6061 struct frame *f;
6062 Lisp_Object spec;
6064 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6065 struct image *img;
6066 int i;
6067 unsigned hash;
6068 struct gcpro gcpro1;
6069 EMACS_TIME now;
6071 /* F must be a window-system frame, and SPEC must be a valid image
6072 specification. */
6073 xassert (FRAME_WINDOW_P (f));
6074 xassert (valid_image_p (spec));
6076 GCPRO1 (spec);
6078 /* Look up SPEC in the hash table of the image cache. */
6079 hash = sxhash (spec, 0);
6080 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6082 for (img = c->buckets[i]; img; img = img->next)
6083 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6084 break;
6086 /* If not found, create a new image and cache it. */
6087 if (img == NULL)
6089 extern Lisp_Object Qpostscript;
6091 BLOCK_INPUT;
6092 img = make_image (spec, hash);
6093 cache_image (f, img);
6094 img->load_failed_p = img->type->load (f, img) == 0;
6096 /* If we can't load the image, and we don't have a width and
6097 height, use some arbitrary width and height so that we can
6098 draw a rectangle for it. */
6099 if (img->load_failed_p)
6101 Lisp_Object value;
6103 value = image_spec_value (spec, QCwidth, NULL);
6104 img->width = (INTEGERP (value)
6105 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6106 value = image_spec_value (spec, QCheight, NULL);
6107 img->height = (INTEGERP (value)
6108 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6110 else
6112 /* Handle image type independent image attributes
6113 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
6114 Lisp_Object ascent, margin, relief;
6116 ascent = image_spec_value (spec, QCascent, NULL);
6117 if (INTEGERP (ascent))
6118 img->ascent = XFASTINT (ascent);
6119 else if (EQ (ascent, Qcenter))
6120 img->ascent = CENTERED_IMAGE_ASCENT;
6122 margin = image_spec_value (spec, QCmargin, NULL);
6123 if (INTEGERP (margin) && XINT (margin) >= 0)
6124 img->vmargin = img->hmargin = XFASTINT (margin);
6125 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6126 && INTEGERP (XCDR (margin)))
6128 if (XINT (XCAR (margin)) > 0)
6129 img->hmargin = XFASTINT (XCAR (margin));
6130 if (XINT (XCDR (margin)) > 0)
6131 img->vmargin = XFASTINT (XCDR (margin));
6134 relief = image_spec_value (spec, QCrelief, NULL);
6135 if (INTEGERP (relief))
6137 img->relief = XINT (relief);
6138 img->hmargin += abs (img->relief);
6139 img->vmargin += abs (img->relief);
6142 /* Do image transformations and compute masks, unless we
6143 don't have the image yet. */
6144 if (!EQ (*img->type->type, Qpostscript))
6145 postprocess_image (f, img);
6148 UNBLOCK_INPUT;
6149 xassert (!interrupt_input_blocked);
6152 /* We're using IMG, so set its timestamp to `now'. */
6153 EMACS_GET_TIME (now);
6154 img->timestamp = EMACS_SECS (now);
6156 UNGCPRO;
6158 /* Value is the image id. */
6159 return img->id;
6163 /* Cache image IMG in the image cache of frame F. */
6165 static void
6166 cache_image (f, img)
6167 struct frame *f;
6168 struct image *img;
6170 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6171 int i;
6173 /* Find a free slot in c->images. */
6174 for (i = 0; i < c->used; ++i)
6175 if (c->images[i] == NULL)
6176 break;
6178 /* If no free slot found, maybe enlarge c->images. */
6179 if (i == c->used && c->used == c->size)
6181 c->size *= 2;
6182 c->images = (struct image **) xrealloc (c->images,
6183 c->size * sizeof *c->images);
6186 /* Add IMG to c->images, and assign IMG an id. */
6187 c->images[i] = img;
6188 img->id = i;
6189 if (i == c->used)
6190 ++c->used;
6192 /* Add IMG to the cache's hash table. */
6193 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6194 img->next = c->buckets[i];
6195 if (img->next)
6196 img->next->prev = img;
6197 img->prev = NULL;
6198 c->buckets[i] = img;
6202 /* Call FN on every image in the image cache of frame F. Used to mark
6203 Lisp Objects in the image cache. */
6205 void
6206 forall_images_in_image_cache (f, fn)
6207 struct frame *f;
6208 void (*fn) P_ ((struct image *img));
6210 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6212 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6213 if (c)
6215 int i;
6216 for (i = 0; i < c->used; ++i)
6217 if (c->images[i])
6218 fn (c->images[i]);
6225 /***********************************************************************
6226 X support code
6227 ***********************************************************************/
6229 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6230 XImage **, Pixmap *));
6231 static void x_destroy_x_image P_ ((XImage *));
6232 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6235 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6236 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6237 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6238 via xmalloc. Print error messages via image_error if an error
6239 occurs. Value is non-zero if successful. */
6241 static int
6242 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6243 struct frame *f;
6244 int width, height, depth;
6245 XImage **ximg;
6246 Pixmap *pixmap;
6248 Display *display = FRAME_X_DISPLAY (f);
6249 Screen *screen = FRAME_X_SCREEN (f);
6250 Window window = FRAME_X_WINDOW (f);
6252 xassert (interrupt_input_blocked);
6254 if (depth <= 0)
6255 depth = DefaultDepthOfScreen (screen);
6256 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6257 depth, ZPixmap, 0, NULL, width, height,
6258 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6259 if (*ximg == NULL)
6261 image_error ("Unable to allocate X image", Qnil, Qnil);
6262 return 0;
6265 /* Allocate image raster. */
6266 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6268 /* Allocate a pixmap of the same size. */
6269 *pixmap = XCreatePixmap (display, window, width, height, depth);
6270 if (*pixmap == None)
6272 x_destroy_x_image (*ximg);
6273 *ximg = NULL;
6274 image_error ("Unable to create X pixmap", Qnil, Qnil);
6275 return 0;
6278 return 1;
6282 /* Destroy XImage XIMG. Free XIMG->data. */
6284 static void
6285 x_destroy_x_image (ximg)
6286 XImage *ximg;
6288 xassert (interrupt_input_blocked);
6289 if (ximg)
6291 xfree (ximg->data);
6292 ximg->data = NULL;
6293 XDestroyImage (ximg);
6298 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6299 are width and height of both the image and pixmap. */
6301 static void
6302 x_put_x_image (f, ximg, pixmap, width, height)
6303 struct frame *f;
6304 XImage *ximg;
6305 Pixmap pixmap;
6307 GC gc;
6309 xassert (interrupt_input_blocked);
6310 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6311 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6312 XFreeGC (FRAME_X_DISPLAY (f), gc);
6317 /***********************************************************************
6318 File Handling
6319 ***********************************************************************/
6321 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6322 static char *slurp_file P_ ((char *, int *));
6325 /* Find image file FILE. Look in data-directory, then
6326 x-bitmap-file-path. Value is the full name of the file found, or
6327 nil if not found. */
6329 static Lisp_Object
6330 x_find_image_file (file)
6331 Lisp_Object file;
6333 Lisp_Object file_found, search_path;
6334 struct gcpro gcpro1, gcpro2;
6335 int fd;
6337 file_found = Qnil;
6338 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6339 GCPRO2 (file_found, search_path);
6341 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6342 fd = openp (search_path, file, "", &file_found, 0);
6344 if (fd == -1)
6345 file_found = Qnil;
6346 else
6347 close (fd);
6349 UNGCPRO;
6350 return file_found;
6354 /* Read FILE into memory. Value is a pointer to a buffer allocated
6355 with xmalloc holding FILE's contents. Value is null if an error
6356 occurred. *SIZE is set to the size of the file. */
6358 static char *
6359 slurp_file (file, size)
6360 char *file;
6361 int *size;
6363 FILE *fp = NULL;
6364 char *buf = NULL;
6365 struct stat st;
6367 if (stat (file, &st) == 0
6368 && (fp = fopen (file, "r")) != NULL
6369 && (buf = (char *) xmalloc (st.st_size),
6370 fread (buf, 1, st.st_size, fp) == st.st_size))
6372 *size = st.st_size;
6373 fclose (fp);
6375 else
6377 if (fp)
6378 fclose (fp);
6379 if (buf)
6381 xfree (buf);
6382 buf = NULL;
6386 return buf;
6391 /***********************************************************************
6392 XBM images
6393 ***********************************************************************/
6395 static int xbm_scan P_ ((char **, char *, char *, int *));
6396 static int xbm_load P_ ((struct frame *f, struct image *img));
6397 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6398 char *, char *));
6399 static int xbm_image_p P_ ((Lisp_Object object));
6400 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6401 unsigned char **));
6402 static int xbm_file_p P_ ((Lisp_Object));
6405 /* Indices of image specification fields in xbm_format, below. */
6407 enum xbm_keyword_index
6409 XBM_TYPE,
6410 XBM_FILE,
6411 XBM_WIDTH,
6412 XBM_HEIGHT,
6413 XBM_DATA,
6414 XBM_FOREGROUND,
6415 XBM_BACKGROUND,
6416 XBM_ASCENT,
6417 XBM_MARGIN,
6418 XBM_RELIEF,
6419 XBM_ALGORITHM,
6420 XBM_HEURISTIC_MASK,
6421 XBM_MASK,
6422 XBM_LAST
6425 /* Vector of image_keyword structures describing the format
6426 of valid XBM image specifications. */
6428 static struct image_keyword xbm_format[XBM_LAST] =
6430 {":type", IMAGE_SYMBOL_VALUE, 1},
6431 {":file", IMAGE_STRING_VALUE, 0},
6432 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6433 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6434 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6435 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6436 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6437 {":ascent", IMAGE_ASCENT_VALUE, 0},
6438 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6439 {":relief", IMAGE_INTEGER_VALUE, 0},
6440 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6441 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6442 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6445 /* Structure describing the image type XBM. */
6447 static struct image_type xbm_type =
6449 &Qxbm,
6450 xbm_image_p,
6451 xbm_load,
6452 x_clear_image,
6453 NULL
6456 /* Tokens returned from xbm_scan. */
6458 enum xbm_token
6460 XBM_TK_IDENT = 256,
6461 XBM_TK_NUMBER
6465 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6466 A valid specification is a list starting with the symbol `image'
6467 The rest of the list is a property list which must contain an
6468 entry `:type xbm..
6470 If the specification specifies a file to load, it must contain
6471 an entry `:file FILENAME' where FILENAME is a string.
6473 If the specification is for a bitmap loaded from memory it must
6474 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6475 WIDTH and HEIGHT are integers > 0. DATA may be:
6477 1. a string large enough to hold the bitmap data, i.e. it must
6478 have a size >= (WIDTH + 7) / 8 * HEIGHT
6480 2. a bool-vector of size >= WIDTH * HEIGHT
6482 3. a vector of strings or bool-vectors, one for each line of the
6483 bitmap.
6485 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6486 may not be specified in this case because they are defined in the
6487 XBM file.
6489 Both the file and data forms may contain the additional entries
6490 `:background COLOR' and `:foreground COLOR'. If not present,
6491 foreground and background of the frame on which the image is
6492 displayed is used. */
6494 static int
6495 xbm_image_p (object)
6496 Lisp_Object object;
6498 struct image_keyword kw[XBM_LAST];
6500 bcopy (xbm_format, kw, sizeof kw);
6501 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6502 return 0;
6504 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6506 if (kw[XBM_FILE].count)
6508 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6509 return 0;
6511 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6513 /* In-memory XBM file. */
6514 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6515 return 0;
6517 else
6519 Lisp_Object data;
6520 int width, height;
6522 /* Entries for `:width', `:height' and `:data' must be present. */
6523 if (!kw[XBM_WIDTH].count
6524 || !kw[XBM_HEIGHT].count
6525 || !kw[XBM_DATA].count)
6526 return 0;
6528 data = kw[XBM_DATA].value;
6529 width = XFASTINT (kw[XBM_WIDTH].value);
6530 height = XFASTINT (kw[XBM_HEIGHT].value);
6532 /* Check type of data, and width and height against contents of
6533 data. */
6534 if (VECTORP (data))
6536 int i;
6538 /* Number of elements of the vector must be >= height. */
6539 if (XVECTOR (data)->size < height)
6540 return 0;
6542 /* Each string or bool-vector in data must be large enough
6543 for one line of the image. */
6544 for (i = 0; i < height; ++i)
6546 Lisp_Object elt = XVECTOR (data)->contents[i];
6548 if (STRINGP (elt))
6550 if (XSTRING (elt)->size
6551 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6552 return 0;
6554 else if (BOOL_VECTOR_P (elt))
6556 if (XBOOL_VECTOR (elt)->size < width)
6557 return 0;
6559 else
6560 return 0;
6563 else if (STRINGP (data))
6565 if (XSTRING (data)->size
6566 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6567 return 0;
6569 else if (BOOL_VECTOR_P (data))
6571 if (XBOOL_VECTOR (data)->size < width * height)
6572 return 0;
6574 else
6575 return 0;
6578 return 1;
6582 /* Scan a bitmap file. FP is the stream to read from. Value is
6583 either an enumerator from enum xbm_token, or a character for a
6584 single-character token, or 0 at end of file. If scanning an
6585 identifier, store the lexeme of the identifier in SVAL. If
6586 scanning a number, store its value in *IVAL. */
6588 static int
6589 xbm_scan (s, end, sval, ival)
6590 char **s, *end;
6591 char *sval;
6592 int *ival;
6594 int c;
6596 loop:
6598 /* Skip white space. */
6599 while (*s < end && (c = *(*s)++, isspace (c)))
6602 if (*s >= end)
6603 c = 0;
6604 else if (isdigit (c))
6606 int value = 0, digit;
6608 if (c == '0' && *s < end)
6610 c = *(*s)++;
6611 if (c == 'x' || c == 'X')
6613 while (*s < end)
6615 c = *(*s)++;
6616 if (isdigit (c))
6617 digit = c - '0';
6618 else if (c >= 'a' && c <= 'f')
6619 digit = c - 'a' + 10;
6620 else if (c >= 'A' && c <= 'F')
6621 digit = c - 'A' + 10;
6622 else
6623 break;
6624 value = 16 * value + digit;
6627 else if (isdigit (c))
6629 value = c - '0';
6630 while (*s < end
6631 && (c = *(*s)++, isdigit (c)))
6632 value = 8 * value + c - '0';
6635 else
6637 value = c - '0';
6638 while (*s < end
6639 && (c = *(*s)++, isdigit (c)))
6640 value = 10 * value + c - '0';
6643 if (*s < end)
6644 *s = *s - 1;
6645 *ival = value;
6646 c = XBM_TK_NUMBER;
6648 else if (isalpha (c) || c == '_')
6650 *sval++ = c;
6651 while (*s < end
6652 && (c = *(*s)++, (isalnum (c) || c == '_')))
6653 *sval++ = c;
6654 *sval = 0;
6655 if (*s < end)
6656 *s = *s - 1;
6657 c = XBM_TK_IDENT;
6659 else if (c == '/' && **s == '*')
6661 /* C-style comment. */
6662 ++*s;
6663 while (**s && (**s != '*' || *(*s + 1) != '/'))
6664 ++*s;
6665 if (**s)
6667 *s += 2;
6668 goto loop;
6672 return c;
6676 /* Replacement for XReadBitmapFileData which isn't available under old
6677 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6678 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6679 the image. Return in *DATA the bitmap data allocated with xmalloc.
6680 Value is non-zero if successful. DATA null means just test if
6681 CONTENTS looks like an in-memory XBM file. */
6683 static int
6684 xbm_read_bitmap_data (contents, end, width, height, data)
6685 char *contents, *end;
6686 int *width, *height;
6687 unsigned char **data;
6689 char *s = contents;
6690 char buffer[BUFSIZ];
6691 int padding_p = 0;
6692 int v10 = 0;
6693 int bytes_per_line, i, nbytes;
6694 unsigned char *p;
6695 int value;
6696 int LA1;
6698 #define match() \
6699 LA1 = xbm_scan (&s, end, buffer, &value)
6701 #define expect(TOKEN) \
6702 if (LA1 != (TOKEN)) \
6703 goto failure; \
6704 else \
6705 match ()
6707 #define expect_ident(IDENT) \
6708 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6709 match (); \
6710 else \
6711 goto failure
6713 *width = *height = -1;
6714 if (data)
6715 *data = NULL;
6716 LA1 = xbm_scan (&s, end, buffer, &value);
6718 /* Parse defines for width, height and hot-spots. */
6719 while (LA1 == '#')
6721 match ();
6722 expect_ident ("define");
6723 expect (XBM_TK_IDENT);
6725 if (LA1 == XBM_TK_NUMBER);
6727 char *p = strrchr (buffer, '_');
6728 p = p ? p + 1 : buffer;
6729 if (strcmp (p, "width") == 0)
6730 *width = value;
6731 else if (strcmp (p, "height") == 0)
6732 *height = value;
6734 expect (XBM_TK_NUMBER);
6737 if (*width < 0 || *height < 0)
6738 goto failure;
6739 else if (data == NULL)
6740 goto success;
6742 /* Parse bits. Must start with `static'. */
6743 expect_ident ("static");
6744 if (LA1 == XBM_TK_IDENT)
6746 if (strcmp (buffer, "unsigned") == 0)
6748 match ();
6749 expect_ident ("char");
6751 else if (strcmp (buffer, "short") == 0)
6753 match ();
6754 v10 = 1;
6755 if (*width % 16 && *width % 16 < 9)
6756 padding_p = 1;
6758 else if (strcmp (buffer, "char") == 0)
6759 match ();
6760 else
6761 goto failure;
6763 else
6764 goto failure;
6766 expect (XBM_TK_IDENT);
6767 expect ('[');
6768 expect (']');
6769 expect ('=');
6770 expect ('{');
6772 bytes_per_line = (*width + 7) / 8 + padding_p;
6773 nbytes = bytes_per_line * *height;
6774 p = *data = (char *) xmalloc (nbytes);
6776 if (v10)
6778 for (i = 0; i < nbytes; i += 2)
6780 int val = value;
6781 expect (XBM_TK_NUMBER);
6783 *p++ = val;
6784 if (!padding_p || ((i + 2) % bytes_per_line))
6785 *p++ = value >> 8;
6787 if (LA1 == ',' || LA1 == '}')
6788 match ();
6789 else
6790 goto failure;
6793 else
6795 for (i = 0; i < nbytes; ++i)
6797 int val = value;
6798 expect (XBM_TK_NUMBER);
6800 *p++ = val;
6802 if (LA1 == ',' || LA1 == '}')
6803 match ();
6804 else
6805 goto failure;
6809 success:
6810 return 1;
6812 failure:
6814 if (data && *data)
6816 xfree (*data);
6817 *data = NULL;
6819 return 0;
6821 #undef match
6822 #undef expect
6823 #undef expect_ident
6827 /* Load XBM image IMG which will be displayed on frame F from buffer
6828 CONTENTS. END is the end of the buffer. Value is non-zero if
6829 successful. */
6831 static int
6832 xbm_load_image (f, img, contents, end)
6833 struct frame *f;
6834 struct image *img;
6835 char *contents, *end;
6837 int rc;
6838 unsigned char *data;
6839 int success_p = 0;
6841 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6842 if (rc)
6844 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6845 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6846 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6847 Lisp_Object value;
6849 xassert (img->width > 0 && img->height > 0);
6851 /* Get foreground and background colors, maybe allocate colors. */
6852 value = image_spec_value (img->spec, QCforeground, NULL);
6853 if (!NILP (value))
6854 foreground = x_alloc_image_color (f, img, value, foreground);
6856 value = image_spec_value (img->spec, QCbackground, NULL);
6857 if (!NILP (value))
6858 background = x_alloc_image_color (f, img, value, background);
6860 img->pixmap
6861 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6862 FRAME_X_WINDOW (f),
6863 data,
6864 img->width, img->height,
6865 foreground, background,
6866 depth);
6867 xfree (data);
6869 if (img->pixmap == None)
6871 x_clear_image (f, img);
6872 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6874 else
6875 success_p = 1;
6877 else
6878 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6880 return success_p;
6884 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6886 static int
6887 xbm_file_p (data)
6888 Lisp_Object data;
6890 int w, h;
6891 return (STRINGP (data)
6892 && xbm_read_bitmap_data (XSTRING (data)->data,
6893 (XSTRING (data)->data
6894 + STRING_BYTES (XSTRING (data))),
6895 &w, &h, NULL));
6899 /* Fill image IMG which is used on frame F with pixmap data. Value is
6900 non-zero if successful. */
6902 static int
6903 xbm_load (f, img)
6904 struct frame *f;
6905 struct image *img;
6907 int success_p = 0;
6908 Lisp_Object file_name;
6910 xassert (xbm_image_p (img->spec));
6912 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6913 file_name = image_spec_value (img->spec, QCfile, NULL);
6914 if (STRINGP (file_name))
6916 Lisp_Object file;
6917 char *contents;
6918 int size;
6919 struct gcpro gcpro1;
6921 file = x_find_image_file (file_name);
6922 GCPRO1 (file);
6923 if (!STRINGP (file))
6925 image_error ("Cannot find image file `%s'", file_name, Qnil);
6926 UNGCPRO;
6927 return 0;
6930 contents = slurp_file (XSTRING (file)->data, &size);
6931 if (contents == NULL)
6933 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6934 UNGCPRO;
6935 return 0;
6938 success_p = xbm_load_image (f, img, contents, contents + size);
6939 UNGCPRO;
6941 else
6943 struct image_keyword fmt[XBM_LAST];
6944 Lisp_Object data;
6945 int depth;
6946 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6947 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6948 char *bits;
6949 int parsed_p;
6950 int in_memory_file_p = 0;
6952 /* See if data looks like an in-memory XBM file. */
6953 data = image_spec_value (img->spec, QCdata, NULL);
6954 in_memory_file_p = xbm_file_p (data);
6956 /* Parse the image specification. */
6957 bcopy (xbm_format, fmt, sizeof fmt);
6958 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6959 xassert (parsed_p);
6961 /* Get specified width, and height. */
6962 if (!in_memory_file_p)
6964 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6965 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6966 xassert (img->width > 0 && img->height > 0);
6969 /* Get foreground and background colors, maybe allocate colors. */
6970 if (fmt[XBM_FOREGROUND].count
6971 && STRINGP (fmt[XBM_FOREGROUND].value))
6972 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6973 foreground);
6974 if (fmt[XBM_BACKGROUND].count
6975 && STRINGP (fmt[XBM_BACKGROUND].value))
6976 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6977 background);
6979 if (in_memory_file_p)
6980 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6981 (XSTRING (data)->data
6982 + STRING_BYTES (XSTRING (data))));
6983 else
6985 if (VECTORP (data))
6987 int i;
6988 char *p;
6989 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6991 p = bits = (char *) alloca (nbytes * img->height);
6992 for (i = 0; i < img->height; ++i, p += nbytes)
6994 Lisp_Object line = XVECTOR (data)->contents[i];
6995 if (STRINGP (line))
6996 bcopy (XSTRING (line)->data, p, nbytes);
6997 else
6998 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7001 else if (STRINGP (data))
7002 bits = XSTRING (data)->data;
7003 else
7004 bits = XBOOL_VECTOR (data)->data;
7006 /* Create the pixmap. */
7007 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7008 img->pixmap
7009 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7010 FRAME_X_WINDOW (f),
7011 bits,
7012 img->width, img->height,
7013 foreground, background,
7014 depth);
7015 if (img->pixmap)
7016 success_p = 1;
7017 else
7019 image_error ("Unable to create pixmap for XBM image `%s'",
7020 img->spec, Qnil);
7021 x_clear_image (f, img);
7026 return success_p;
7031 /***********************************************************************
7032 XPM images
7033 ***********************************************************************/
7035 #if HAVE_XPM
7037 static int xpm_image_p P_ ((Lisp_Object object));
7038 static int xpm_load P_ ((struct frame *f, struct image *img));
7039 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7041 #include "X11/xpm.h"
7043 /* The symbol `xpm' identifying XPM-format images. */
7045 Lisp_Object Qxpm;
7047 /* Indices of image specification fields in xpm_format, below. */
7049 enum xpm_keyword_index
7051 XPM_TYPE,
7052 XPM_FILE,
7053 XPM_DATA,
7054 XPM_ASCENT,
7055 XPM_MARGIN,
7056 XPM_RELIEF,
7057 XPM_ALGORITHM,
7058 XPM_HEURISTIC_MASK,
7059 XPM_MASK,
7060 XPM_COLOR_SYMBOLS,
7061 XPM_LAST
7064 /* Vector of image_keyword structures describing the format
7065 of valid XPM image specifications. */
7067 static struct image_keyword xpm_format[XPM_LAST] =
7069 {":type", IMAGE_SYMBOL_VALUE, 1},
7070 {":file", IMAGE_STRING_VALUE, 0},
7071 {":data", IMAGE_STRING_VALUE, 0},
7072 {":ascent", IMAGE_ASCENT_VALUE, 0},
7073 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7074 {":relief", IMAGE_INTEGER_VALUE, 0},
7075 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7076 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7077 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7078 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7081 /* Structure describing the image type XBM. */
7083 static struct image_type xpm_type =
7085 &Qxpm,
7086 xpm_image_p,
7087 xpm_load,
7088 x_clear_image,
7089 NULL
7093 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7094 functions for allocating image colors. Our own functions handle
7095 color allocation failures more gracefully than the ones on the XPM
7096 lib. */
7098 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7099 #define ALLOC_XPM_COLORS
7100 #endif
7102 #ifdef ALLOC_XPM_COLORS
7104 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7105 static void xpm_free_color_cache P_ ((void));
7106 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7107 static int xpm_color_bucket P_ ((char *));
7108 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7109 XColor *, int));
7111 /* An entry in a hash table used to cache color definitions of named
7112 colors. This cache is necessary to speed up XPM image loading in
7113 case we do color allocations ourselves. Without it, we would need
7114 a call to XParseColor per pixel in the image. */
7116 struct xpm_cached_color
7118 /* Next in collision chain. */
7119 struct xpm_cached_color *next;
7121 /* Color definition (RGB and pixel color). */
7122 XColor color;
7124 /* Color name. */
7125 char name[1];
7128 /* The hash table used for the color cache, and its bucket vector
7129 size. */
7131 #define XPM_COLOR_CACHE_BUCKETS 1001
7132 struct xpm_cached_color **xpm_color_cache;
7134 /* Initialize the color cache. */
7136 static void
7137 xpm_init_color_cache (f, attrs)
7138 struct frame *f;
7139 XpmAttributes *attrs;
7141 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7142 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7143 memset (xpm_color_cache, 0, nbytes);
7144 init_color_table ();
7146 if (attrs->valuemask & XpmColorSymbols)
7148 int i;
7149 XColor color;
7151 for (i = 0; i < attrs->numsymbols; ++i)
7152 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7153 attrs->colorsymbols[i].value, &color))
7155 color.pixel = lookup_rgb_color (f, color.red, color.green,
7156 color.blue);
7157 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7163 /* Free the color cache. */
7165 static void
7166 xpm_free_color_cache ()
7168 struct xpm_cached_color *p, *next;
7169 int i;
7171 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7172 for (p = xpm_color_cache[i]; p; p = next)
7174 next = p->next;
7175 xfree (p);
7178 xfree (xpm_color_cache);
7179 xpm_color_cache = NULL;
7180 free_color_table ();
7184 /* Return the bucket index for color named COLOR_NAME in the color
7185 cache. */
7187 static int
7188 xpm_color_bucket (color_name)
7189 char *color_name;
7191 unsigned h = 0;
7192 char *s;
7194 for (s = color_name; *s; ++s)
7195 h = (h << 2) ^ *s;
7196 return h %= XPM_COLOR_CACHE_BUCKETS;
7200 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7201 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7202 entry added. */
7204 static struct xpm_cached_color *
7205 xpm_cache_color (f, color_name, color, bucket)
7206 struct frame *f;
7207 char *color_name;
7208 XColor *color;
7209 int bucket;
7211 size_t nbytes;
7212 struct xpm_cached_color *p;
7214 if (bucket < 0)
7215 bucket = xpm_color_bucket (color_name);
7217 nbytes = sizeof *p + strlen (color_name);
7218 p = (struct xpm_cached_color *) xmalloc (nbytes);
7219 strcpy (p->name, color_name);
7220 p->color = *color;
7221 p->next = xpm_color_cache[bucket];
7222 xpm_color_cache[bucket] = p;
7223 return p;
7227 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7228 return the cached definition in *COLOR. Otherwise, make a new
7229 entry in the cache and allocate the color. Value is zero if color
7230 allocation failed. */
7232 static int
7233 xpm_lookup_color (f, color_name, color)
7234 struct frame *f;
7235 char *color_name;
7236 XColor *color;
7238 struct xpm_cached_color *p;
7239 int h = xpm_color_bucket (color_name);
7241 for (p = xpm_color_cache[h]; p; p = p->next)
7242 if (strcmp (p->name, color_name) == 0)
7243 break;
7245 if (p != NULL)
7246 *color = p->color;
7247 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7248 color_name, color))
7250 color->pixel = lookup_rgb_color (f, color->red, color->green,
7251 color->blue);
7252 p = xpm_cache_color (f, color_name, color, h);
7255 return p != NULL;
7259 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7260 CLOSURE is a pointer to the frame on which we allocate the
7261 color. Return in *COLOR the allocated color. Value is non-zero
7262 if successful. */
7264 static int
7265 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7266 Display *dpy;
7267 Colormap cmap;
7268 char *color_name;
7269 XColor *color;
7270 void *closure;
7272 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7276 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7277 is a pointer to the frame on which we allocate the color. Value is
7278 non-zero if successful. */
7280 static int
7281 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7282 Display *dpy;
7283 Colormap cmap;
7284 Pixel *pixels;
7285 int npixels;
7286 void *closure;
7288 return 1;
7291 #endif /* ALLOC_XPM_COLORS */
7294 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7295 for XPM images. Such a list must consist of conses whose car and
7296 cdr are strings. */
7298 static int
7299 xpm_valid_color_symbols_p (color_symbols)
7300 Lisp_Object color_symbols;
7302 while (CONSP (color_symbols))
7304 Lisp_Object sym = XCAR (color_symbols);
7305 if (!CONSP (sym)
7306 || !STRINGP (XCAR (sym))
7307 || !STRINGP (XCDR (sym)))
7308 break;
7309 color_symbols = XCDR (color_symbols);
7312 return NILP (color_symbols);
7316 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7318 static int
7319 xpm_image_p (object)
7320 Lisp_Object object;
7322 struct image_keyword fmt[XPM_LAST];
7323 bcopy (xpm_format, fmt, sizeof fmt);
7324 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7325 /* Either `:file' or `:data' must be present. */
7326 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7327 /* Either no `:color-symbols' or it's a list of conses
7328 whose car and cdr are strings. */
7329 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7330 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7334 /* Load image IMG which will be displayed on frame F. Value is
7335 non-zero if successful. */
7337 static int
7338 xpm_load (f, img)
7339 struct frame *f;
7340 struct image *img;
7342 int rc;
7343 XpmAttributes attrs;
7344 Lisp_Object specified_file, color_symbols;
7346 /* Configure the XPM lib. Use the visual of frame F. Allocate
7347 close colors. Return colors allocated. */
7348 bzero (&attrs, sizeof attrs);
7349 attrs.visual = FRAME_X_VISUAL (f);
7350 attrs.colormap = FRAME_X_COLORMAP (f);
7351 attrs.valuemask |= XpmVisual;
7352 attrs.valuemask |= XpmColormap;
7354 #ifdef ALLOC_XPM_COLORS
7355 /* Allocate colors with our own functions which handle
7356 failing color allocation more gracefully. */
7357 attrs.color_closure = f;
7358 attrs.alloc_color = xpm_alloc_color;
7359 attrs.free_colors = xpm_free_colors;
7360 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7361 #else /* not ALLOC_XPM_COLORS */
7362 /* Let the XPM lib allocate colors. */
7363 attrs.valuemask |= XpmReturnAllocPixels;
7364 #ifdef XpmAllocCloseColors
7365 attrs.alloc_close_colors = 1;
7366 attrs.valuemask |= XpmAllocCloseColors;
7367 #else /* not XpmAllocCloseColors */
7368 attrs.closeness = 600;
7369 attrs.valuemask |= XpmCloseness;
7370 #endif /* not XpmAllocCloseColors */
7371 #endif /* ALLOC_XPM_COLORS */
7373 /* If image specification contains symbolic color definitions, add
7374 these to `attrs'. */
7375 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7376 if (CONSP (color_symbols))
7378 Lisp_Object tail;
7379 XpmColorSymbol *xpm_syms;
7380 int i, size;
7382 attrs.valuemask |= XpmColorSymbols;
7384 /* Count number of symbols. */
7385 attrs.numsymbols = 0;
7386 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7387 ++attrs.numsymbols;
7389 /* Allocate an XpmColorSymbol array. */
7390 size = attrs.numsymbols * sizeof *xpm_syms;
7391 xpm_syms = (XpmColorSymbol *) alloca (size);
7392 bzero (xpm_syms, size);
7393 attrs.colorsymbols = xpm_syms;
7395 /* Fill the color symbol array. */
7396 for (tail = color_symbols, i = 0;
7397 CONSP (tail);
7398 ++i, tail = XCDR (tail))
7400 Lisp_Object name = XCAR (XCAR (tail));
7401 Lisp_Object color = XCDR (XCAR (tail));
7402 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7403 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7404 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7405 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7409 /* Create a pixmap for the image, either from a file, or from a
7410 string buffer containing data in the same format as an XPM file. */
7411 #ifdef ALLOC_XPM_COLORS
7412 xpm_init_color_cache (f, &attrs);
7413 #endif
7415 specified_file = image_spec_value (img->spec, QCfile, NULL);
7416 if (STRINGP (specified_file))
7418 Lisp_Object file = x_find_image_file (specified_file);
7419 if (!STRINGP (file))
7421 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7422 return 0;
7425 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7426 XSTRING (file)->data, &img->pixmap, &img->mask,
7427 &attrs);
7429 else
7431 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7432 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7433 XSTRING (buffer)->data,
7434 &img->pixmap, &img->mask,
7435 &attrs);
7438 if (rc == XpmSuccess)
7440 #ifdef ALLOC_XPM_COLORS
7441 img->colors = colors_in_color_table (&img->ncolors);
7442 #else /* not ALLOC_XPM_COLORS */
7443 int i;
7445 img->ncolors = attrs.nalloc_pixels;
7446 img->colors = (unsigned long *) xmalloc (img->ncolors
7447 * sizeof *img->colors);
7448 for (i = 0; i < attrs.nalloc_pixels; ++i)
7450 img->colors[i] = attrs.alloc_pixels[i];
7451 #ifdef DEBUG_X_COLORS
7452 register_color (img->colors[i]);
7453 #endif
7455 #endif /* not ALLOC_XPM_COLORS */
7457 img->width = attrs.width;
7458 img->height = attrs.height;
7459 xassert (img->width > 0 && img->height > 0);
7461 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7462 XpmFreeAttributes (&attrs);
7464 else
7466 switch (rc)
7468 case XpmOpenFailed:
7469 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7470 break;
7472 case XpmFileInvalid:
7473 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7474 break;
7476 case XpmNoMemory:
7477 image_error ("Out of memory (%s)", img->spec, Qnil);
7478 break;
7480 case XpmColorFailed:
7481 image_error ("Color allocation error (%s)", img->spec, Qnil);
7482 break;
7484 default:
7485 image_error ("Unknown error (%s)", img->spec, Qnil);
7486 break;
7490 #ifdef ALLOC_XPM_COLORS
7491 xpm_free_color_cache ();
7492 #endif
7493 return rc == XpmSuccess;
7496 #endif /* HAVE_XPM != 0 */
7499 /***********************************************************************
7500 Color table
7501 ***********************************************************************/
7503 /* An entry in the color table mapping an RGB color to a pixel color. */
7505 struct ct_color
7507 int r, g, b;
7508 unsigned long pixel;
7510 /* Next in color table collision list. */
7511 struct ct_color *next;
7514 /* The bucket vector size to use. Must be prime. */
7516 #define CT_SIZE 101
7518 /* Value is a hash of the RGB color given by R, G, and B. */
7520 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7522 /* The color hash table. */
7524 struct ct_color **ct_table;
7526 /* Number of entries in the color table. */
7528 int ct_colors_allocated;
7530 /* Initialize the color table. */
7532 static void
7533 init_color_table ()
7535 int size = CT_SIZE * sizeof (*ct_table);
7536 ct_table = (struct ct_color **) xmalloc (size);
7537 bzero (ct_table, size);
7538 ct_colors_allocated = 0;
7542 /* Free memory associated with the color table. */
7544 static void
7545 free_color_table ()
7547 int i;
7548 struct ct_color *p, *next;
7550 for (i = 0; i < CT_SIZE; ++i)
7551 for (p = ct_table[i]; p; p = next)
7553 next = p->next;
7554 xfree (p);
7557 xfree (ct_table);
7558 ct_table = NULL;
7562 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7563 entry for that color already is in the color table, return the
7564 pixel color of that entry. Otherwise, allocate a new color for R,
7565 G, B, and make an entry in the color table. */
7567 static unsigned long
7568 lookup_rgb_color (f, r, g, b)
7569 struct frame *f;
7570 int r, g, b;
7572 unsigned hash = CT_HASH_RGB (r, g, b);
7573 int i = hash % CT_SIZE;
7574 struct ct_color *p;
7576 for (p = ct_table[i]; p; p = p->next)
7577 if (p->r == r && p->g == g && p->b == b)
7578 break;
7580 if (p == NULL)
7582 XColor color;
7583 Colormap cmap;
7584 int rc;
7586 color.red = r;
7587 color.green = g;
7588 color.blue = b;
7590 cmap = FRAME_X_COLORMAP (f);
7591 rc = x_alloc_nearest_color (f, cmap, &color);
7593 if (rc)
7595 ++ct_colors_allocated;
7597 p = (struct ct_color *) xmalloc (sizeof *p);
7598 p->r = r;
7599 p->g = g;
7600 p->b = b;
7601 p->pixel = color.pixel;
7602 p->next = ct_table[i];
7603 ct_table[i] = p;
7605 else
7606 return FRAME_FOREGROUND_PIXEL (f);
7609 return p->pixel;
7613 /* Look up pixel color PIXEL which is used on frame F in the color
7614 table. If not already present, allocate it. Value is PIXEL. */
7616 static unsigned long
7617 lookup_pixel_color (f, pixel)
7618 struct frame *f;
7619 unsigned long pixel;
7621 int i = pixel % CT_SIZE;
7622 struct ct_color *p;
7624 for (p = ct_table[i]; p; p = p->next)
7625 if (p->pixel == pixel)
7626 break;
7628 if (p == NULL)
7630 XColor color;
7631 Colormap cmap;
7632 int rc;
7634 cmap = FRAME_X_COLORMAP (f);
7635 color.pixel = pixel;
7636 x_query_color (f, &color);
7637 rc = x_alloc_nearest_color (f, cmap, &color);
7639 if (rc)
7641 ++ct_colors_allocated;
7643 p = (struct ct_color *) xmalloc (sizeof *p);
7644 p->r = color.red;
7645 p->g = color.green;
7646 p->b = color.blue;
7647 p->pixel = pixel;
7648 p->next = ct_table[i];
7649 ct_table[i] = p;
7651 else
7652 return FRAME_FOREGROUND_PIXEL (f);
7655 return p->pixel;
7659 /* Value is a vector of all pixel colors contained in the color table,
7660 allocated via xmalloc. Set *N to the number of colors. */
7662 static unsigned long *
7663 colors_in_color_table (n)
7664 int *n;
7666 int i, j;
7667 struct ct_color *p;
7668 unsigned long *colors;
7670 if (ct_colors_allocated == 0)
7672 *n = 0;
7673 colors = NULL;
7675 else
7677 colors = (unsigned long *) xmalloc (ct_colors_allocated
7678 * sizeof *colors);
7679 *n = ct_colors_allocated;
7681 for (i = j = 0; i < CT_SIZE; ++i)
7682 for (p = ct_table[i]; p; p = p->next)
7683 colors[j++] = p->pixel;
7686 return colors;
7691 /***********************************************************************
7692 Algorithms
7693 ***********************************************************************/
7695 static void x_laplace_write_row P_ ((struct frame *, long *,
7696 int, XImage *, int));
7697 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7698 XColor *, int, XImage *, int));
7699 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7700 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7701 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7703 /* Non-zero means draw a cross on images having `:conversion
7704 disabled'. */
7706 int cross_disabled_images;
7708 /* Edge detection matrices for different edge-detection
7709 strategies. */
7711 static int emboss_matrix[9] = {
7712 /* x - 1 x x + 1 */
7713 2, -1, 0, /* y - 1 */
7714 -1, 0, 1, /* y */
7715 0, 1, -2 /* y + 1 */
7718 static int laplace_matrix[9] = {
7719 /* x - 1 x x + 1 */
7720 1, 0, 0, /* y - 1 */
7721 0, 0, 0, /* y */
7722 0, 0, -1 /* y + 1 */
7725 /* Value is the intensity of the color whose red/green/blue values
7726 are R, G, and B. */
7728 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7731 /* On frame F, return an array of XColor structures describing image
7732 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7733 non-zero means also fill the red/green/blue members of the XColor
7734 structures. Value is a pointer to the array of XColors structures,
7735 allocated with xmalloc; it must be freed by the caller. */
7737 static XColor *
7738 x_to_xcolors (f, img, rgb_p)
7739 struct frame *f;
7740 struct image *img;
7741 int rgb_p;
7743 int x, y;
7744 XColor *colors, *p;
7745 XImage *ximg;
7747 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7749 /* Get the X image IMG->pixmap. */
7750 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7751 0, 0, img->width, img->height, ~0, ZPixmap);
7753 /* Fill the `pixel' members of the XColor array. I wished there
7754 were an easy and portable way to circumvent XGetPixel. */
7755 p = colors;
7756 for (y = 0; y < img->height; ++y)
7758 XColor *row = p;
7760 for (x = 0; x < img->width; ++x, ++p)
7761 p->pixel = XGetPixel (ximg, x, y);
7763 if (rgb_p)
7764 x_query_colors (f, row, img->width);
7767 XDestroyImage (ximg);
7768 return colors;
7772 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7773 RGB members are set. F is the frame on which this all happens.
7774 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7776 static void
7777 x_from_xcolors (f, img, colors)
7778 struct frame *f;
7779 struct image *img;
7780 XColor *colors;
7782 int x, y;
7783 XImage *oimg;
7784 Pixmap pixmap;
7785 XColor *p;
7787 init_color_table ();
7789 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7790 &oimg, &pixmap);
7791 p = colors;
7792 for (y = 0; y < img->height; ++y)
7793 for (x = 0; x < img->width; ++x, ++p)
7795 unsigned long pixel;
7796 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7797 XPutPixel (oimg, x, y, pixel);
7800 xfree (colors);
7801 x_clear_image_1 (f, img, 1, 0, 1);
7803 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7804 x_destroy_x_image (oimg);
7805 img->pixmap = pixmap;
7806 img->colors = colors_in_color_table (&img->ncolors);
7807 free_color_table ();
7811 /* On frame F, perform edge-detection on image IMG.
7813 MATRIX is a nine-element array specifying the transformation
7814 matrix. See emboss_matrix for an example.
7816 COLOR_ADJUST is a color adjustment added to each pixel of the
7817 outgoing image. */
7819 static void
7820 x_detect_edges (f, img, matrix, color_adjust)
7821 struct frame *f;
7822 struct image *img;
7823 int matrix[9], color_adjust;
7825 XColor *colors = x_to_xcolors (f, img, 1);
7826 XColor *new, *p;
7827 int x, y, i, sum;
7829 for (i = sum = 0; i < 9; ++i)
7830 sum += abs (matrix[i]);
7832 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7834 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
7836 for (y = 0; y < img->height; ++y)
7838 p = COLOR (new, 0, y);
7839 p->red = p->green = p->blue = 0xffff/2;
7840 p = COLOR (new, img->width - 1, y);
7841 p->red = p->green = p->blue = 0xffff/2;
7844 for (x = 1; x < img->width - 1; ++x)
7846 p = COLOR (new, x, 0);
7847 p->red = p->green = p->blue = 0xffff/2;
7848 p = COLOR (new, x, img->height - 1);
7849 p->red = p->green = p->blue = 0xffff/2;
7852 for (y = 1; y < img->height - 1; ++y)
7854 p = COLOR (new, 1, y);
7856 for (x = 1; x < img->width - 1; ++x, ++p)
7858 int r, g, b, y1, x1;
7860 r = g = b = i = 0;
7861 for (y1 = y - 1; y1 < y + 2; ++y1)
7862 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7863 if (matrix[i])
7865 XColor *t = COLOR (colors, x1, y1);
7866 r += matrix[i] * t->red;
7867 g += matrix[i] * t->green;
7868 b += matrix[i] * t->blue;
7871 r = (r / sum + color_adjust) & 0xffff;
7872 g = (g / sum + color_adjust) & 0xffff;
7873 b = (b / sum + color_adjust) & 0xffff;
7874 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7878 xfree (colors);
7879 x_from_xcolors (f, img, new);
7881 #undef COLOR
7885 /* Perform the pre-defined `emboss' edge-detection on image IMG
7886 on frame F. */
7888 static void
7889 x_emboss (f, img)
7890 struct frame *f;
7891 struct image *img;
7893 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7897 /* Perform the pre-defined `laplace' edge-detection on image IMG
7898 on frame F. */
7900 static void
7901 x_laplace (f, img)
7902 struct frame *f;
7903 struct image *img;
7905 x_detect_edges (f, img, laplace_matrix, 45000);
7909 /* Perform edge-detection on image IMG on frame F, with specified
7910 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7912 MATRIX must be either
7914 - a list of at least 9 numbers in row-major form
7915 - a vector of at least 9 numbers
7917 COLOR_ADJUST nil means use a default; otherwise it must be a
7918 number. */
7920 static void
7921 x_edge_detection (f, img, matrix, color_adjust)
7922 struct frame *f;
7923 struct image *img;
7924 Lisp_Object matrix, color_adjust;
7926 int i = 0;
7927 int trans[9];
7929 if (CONSP (matrix))
7931 for (i = 0;
7932 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7933 ++i, matrix = XCDR (matrix))
7934 trans[i] = XFLOATINT (XCAR (matrix));
7936 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7938 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7939 trans[i] = XFLOATINT (AREF (matrix, i));
7942 if (NILP (color_adjust))
7943 color_adjust = make_number (0xffff / 2);
7945 if (i == 9 && NUMBERP (color_adjust))
7946 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7950 /* Transform image IMG on frame F so that it looks disabled. */
7952 static void
7953 x_disable_image (f, img)
7954 struct frame *f;
7955 struct image *img;
7957 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7959 if (dpyinfo->n_planes >= 2)
7961 /* Color (or grayscale). Convert to gray, and equalize. Just
7962 drawing such images with a stipple can look very odd, so
7963 we're using this method instead. */
7964 XColor *colors = x_to_xcolors (f, img, 1);
7965 XColor *p, *end;
7966 const int h = 15000;
7967 const int l = 30000;
7969 for (p = colors, end = colors + img->width * img->height;
7970 p < end;
7971 ++p)
7973 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7974 int i2 = (0xffff - h - l) * i / 0xffff + l;
7975 p->red = p->green = p->blue = i2;
7978 x_from_xcolors (f, img, colors);
7981 /* Draw a cross over the disabled image, if we must or if we
7982 should. */
7983 if (dpyinfo->n_planes < 2 || cross_disabled_images)
7985 Display *dpy = FRAME_X_DISPLAY (f);
7986 GC gc;
7988 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
7989 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
7990 XDrawLine (dpy, img->pixmap, gc, 0, 0,
7991 img->width - 1, img->height - 1);
7992 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
7993 img->width - 1, 0);
7994 XFreeGC (dpy, gc);
7996 if (img->mask)
7998 gc = XCreateGC (dpy, img->mask, 0, NULL);
7999 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8000 XDrawLine (dpy, img->mask, gc, 0, 0,
8001 img->width - 1, img->height - 1);
8002 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8003 img->width - 1, 0);
8004 XFreeGC (dpy, gc);
8010 /* Build a mask for image IMG which is used on frame F. FILE is the
8011 name of an image file, for error messages. HOW determines how to
8012 determine the background color of IMG. If it is a list '(R G B)',
8013 with R, G, and B being integers >= 0, take that as the color of the
8014 background. Otherwise, determine the background color of IMG
8015 heuristically. Value is non-zero if successful. */
8017 static int
8018 x_build_heuristic_mask (f, img, how)
8019 struct frame *f;
8020 struct image *img;
8021 Lisp_Object how;
8023 Display *dpy = FRAME_X_DISPLAY (f);
8024 XImage *ximg, *mask_img;
8025 int x, y, rc, look_at_corners_p;
8026 unsigned long bg = 0;
8028 if (img->mask)
8030 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8031 img->mask = None;
8034 /* Create an image and pixmap serving as mask. */
8035 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8036 &mask_img, &img->mask);
8037 if (!rc)
8038 return 0;
8040 /* Get the X image of IMG->pixmap. */
8041 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8042 ~0, ZPixmap);
8044 /* Determine the background color of ximg. If HOW is `(R G B)'
8045 take that as color. Otherwise, try to determine the color
8046 heuristically. */
8047 look_at_corners_p = 1;
8049 if (CONSP (how))
8051 int rgb[3], i = 0;
8053 while (i < 3
8054 && CONSP (how)
8055 && NATNUMP (XCAR (how)))
8057 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8058 how = XCDR (how);
8061 if (i == 3 && NILP (how))
8063 char color_name[30];
8064 XColor exact, color;
8065 Colormap cmap;
8067 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8069 cmap = FRAME_X_COLORMAP (f);
8070 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
8072 bg = color.pixel;
8073 look_at_corners_p = 0;
8078 if (look_at_corners_p)
8080 unsigned long corners[4];
8081 int i, best_count;
8083 /* Get the colors at the corners of ximg. */
8084 corners[0] = XGetPixel (ximg, 0, 0);
8085 corners[1] = XGetPixel (ximg, img->width - 1, 0);
8086 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
8087 corners[3] = XGetPixel (ximg, 0, img->height - 1);
8089 /* Choose the most frequently found color as background. */
8090 for (i = best_count = 0; i < 4; ++i)
8092 int j, n;
8094 for (j = n = 0; j < 4; ++j)
8095 if (corners[i] == corners[j])
8096 ++n;
8098 if (n > best_count)
8099 bg = corners[i], best_count = n;
8103 /* Set all bits in mask_img to 1 whose color in ximg is different
8104 from the background color bg. */
8105 for (y = 0; y < img->height; ++y)
8106 for (x = 0; x < img->width; ++x)
8107 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8109 /* Put mask_img into img->mask. */
8110 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8111 x_destroy_x_image (mask_img);
8112 XDestroyImage (ximg);
8114 return 1;
8119 /***********************************************************************
8120 PBM (mono, gray, color)
8121 ***********************************************************************/
8123 static int pbm_image_p P_ ((Lisp_Object object));
8124 static int pbm_load P_ ((struct frame *f, struct image *img));
8125 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8127 /* The symbol `pbm' identifying images of this type. */
8129 Lisp_Object Qpbm;
8131 /* Indices of image specification fields in gs_format, below. */
8133 enum pbm_keyword_index
8135 PBM_TYPE,
8136 PBM_FILE,
8137 PBM_DATA,
8138 PBM_ASCENT,
8139 PBM_MARGIN,
8140 PBM_RELIEF,
8141 PBM_ALGORITHM,
8142 PBM_HEURISTIC_MASK,
8143 PBM_MASK,
8144 PBM_FOREGROUND,
8145 PBM_BACKGROUND,
8146 PBM_LAST
8149 /* Vector of image_keyword structures describing the format
8150 of valid user-defined image specifications. */
8152 static struct image_keyword pbm_format[PBM_LAST] =
8154 {":type", IMAGE_SYMBOL_VALUE, 1},
8155 {":file", IMAGE_STRING_VALUE, 0},
8156 {":data", IMAGE_STRING_VALUE, 0},
8157 {":ascent", IMAGE_ASCENT_VALUE, 0},
8158 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8159 {":relief", IMAGE_INTEGER_VALUE, 0},
8160 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8161 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8162 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8163 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8164 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8167 /* Structure describing the image type `pbm'. */
8169 static struct image_type pbm_type =
8171 &Qpbm,
8172 pbm_image_p,
8173 pbm_load,
8174 x_clear_image,
8175 NULL
8179 /* Return non-zero if OBJECT is a valid PBM image specification. */
8181 static int
8182 pbm_image_p (object)
8183 Lisp_Object object;
8185 struct image_keyword fmt[PBM_LAST];
8187 bcopy (pbm_format, fmt, sizeof fmt);
8189 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8190 return 0;
8192 /* Must specify either :data or :file. */
8193 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8197 /* Scan a decimal number from *S and return it. Advance *S while
8198 reading the number. END is the end of the string. Value is -1 at
8199 end of input. */
8201 static int
8202 pbm_scan_number (s, end)
8203 unsigned char **s, *end;
8205 int c = 0, val = -1;
8207 while (*s < end)
8209 /* Skip white-space. */
8210 while (*s < end && (c = *(*s)++, isspace (c)))
8213 if (c == '#')
8215 /* Skip comment to end of line. */
8216 while (*s < end && (c = *(*s)++, c != '\n'))
8219 else if (isdigit (c))
8221 /* Read decimal number. */
8222 val = c - '0';
8223 while (*s < end && (c = *(*s)++, isdigit (c)))
8224 val = 10 * val + c - '0';
8225 break;
8227 else
8228 break;
8231 return val;
8235 /* Load PBM image IMG for use on frame F. */
8237 static int
8238 pbm_load (f, img)
8239 struct frame *f;
8240 struct image *img;
8242 int raw_p, x, y;
8243 int width, height, max_color_idx = 0;
8244 XImage *ximg;
8245 Lisp_Object file, specified_file;
8246 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8247 struct gcpro gcpro1;
8248 unsigned char *contents = NULL;
8249 unsigned char *end, *p;
8250 int size;
8252 specified_file = image_spec_value (img->spec, QCfile, NULL);
8253 file = Qnil;
8254 GCPRO1 (file);
8256 if (STRINGP (specified_file))
8258 file = x_find_image_file (specified_file);
8259 if (!STRINGP (file))
8261 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8262 UNGCPRO;
8263 return 0;
8266 contents = slurp_file (XSTRING (file)->data, &size);
8267 if (contents == NULL)
8269 image_error ("Error reading `%s'", file, Qnil);
8270 UNGCPRO;
8271 return 0;
8274 p = contents;
8275 end = contents + size;
8277 else
8279 Lisp_Object data;
8280 data = image_spec_value (img->spec, QCdata, NULL);
8281 p = XSTRING (data)->data;
8282 end = p + STRING_BYTES (XSTRING (data));
8285 /* Check magic number. */
8286 if (end - p < 2 || *p++ != 'P')
8288 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8289 error:
8290 xfree (contents);
8291 UNGCPRO;
8292 return 0;
8295 switch (*p++)
8297 case '1':
8298 raw_p = 0, type = PBM_MONO;
8299 break;
8301 case '2':
8302 raw_p = 0, type = PBM_GRAY;
8303 break;
8305 case '3':
8306 raw_p = 0, type = PBM_COLOR;
8307 break;
8309 case '4':
8310 raw_p = 1, type = PBM_MONO;
8311 break;
8313 case '5':
8314 raw_p = 1, type = PBM_GRAY;
8315 break;
8317 case '6':
8318 raw_p = 1, type = PBM_COLOR;
8319 break;
8321 default:
8322 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8323 goto error;
8326 /* Read width, height, maximum color-component. Characters
8327 starting with `#' up to the end of a line are ignored. */
8328 width = pbm_scan_number (&p, end);
8329 height = pbm_scan_number (&p, end);
8331 if (type != PBM_MONO)
8333 max_color_idx = pbm_scan_number (&p, end);
8334 if (raw_p && max_color_idx > 255)
8335 max_color_idx = 255;
8338 if (width < 0
8339 || height < 0
8340 || (type != PBM_MONO && max_color_idx < 0))
8341 goto error;
8343 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8344 &ximg, &img->pixmap))
8345 goto error;
8347 /* Initialize the color hash table. */
8348 init_color_table ();
8350 if (type == PBM_MONO)
8352 int c = 0, g;
8353 struct image_keyword fmt[PBM_LAST];
8354 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8355 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8357 /* Parse the image specification. */
8358 bcopy (pbm_format, fmt, sizeof fmt);
8359 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8361 /* Get foreground and background colors, maybe allocate colors. */
8362 if (fmt[PBM_FOREGROUND].count
8363 && STRINGP (fmt[PBM_FOREGROUND].value))
8364 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8365 if (fmt[PBM_BACKGROUND].count
8366 && STRINGP (fmt[PBM_BACKGROUND].value))
8367 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8369 for (y = 0; y < height; ++y)
8370 for (x = 0; x < width; ++x)
8372 if (raw_p)
8374 if ((x & 7) == 0)
8375 c = *p++;
8376 g = c & 0x80;
8377 c <<= 1;
8379 else
8380 g = pbm_scan_number (&p, end);
8382 XPutPixel (ximg, x, y, g ? fg : bg);
8385 else
8387 for (y = 0; y < height; ++y)
8388 for (x = 0; x < width; ++x)
8390 int r, g, b;
8392 if (type == PBM_GRAY)
8393 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8394 else if (raw_p)
8396 r = *p++;
8397 g = *p++;
8398 b = *p++;
8400 else
8402 r = pbm_scan_number (&p, end);
8403 g = pbm_scan_number (&p, end);
8404 b = pbm_scan_number (&p, end);
8407 if (r < 0 || g < 0 || b < 0)
8409 xfree (ximg->data);
8410 ximg->data = NULL;
8411 XDestroyImage (ximg);
8412 image_error ("Invalid pixel value in image `%s'",
8413 img->spec, Qnil);
8414 goto error;
8417 /* RGB values are now in the range 0..max_color_idx.
8418 Scale this to the range 0..0xffff supported by X. */
8419 r = (double) r * 65535 / max_color_idx;
8420 g = (double) g * 65535 / max_color_idx;
8421 b = (double) b * 65535 / max_color_idx;
8422 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8426 /* Store in IMG->colors the colors allocated for the image, and
8427 free the color table. */
8428 img->colors = colors_in_color_table (&img->ncolors);
8429 free_color_table ();
8431 /* Put the image into a pixmap. */
8432 x_put_x_image (f, ximg, img->pixmap, width, height);
8433 x_destroy_x_image (ximg);
8435 img->width = width;
8436 img->height = height;
8438 UNGCPRO;
8439 xfree (contents);
8440 return 1;
8445 /***********************************************************************
8447 ***********************************************************************/
8449 #if HAVE_PNG
8451 #include <png.h>
8453 /* Function prototypes. */
8455 static int png_image_p P_ ((Lisp_Object object));
8456 static int png_load P_ ((struct frame *f, struct image *img));
8458 /* The symbol `png' identifying images of this type. */
8460 Lisp_Object Qpng;
8462 /* Indices of image specification fields in png_format, below. */
8464 enum png_keyword_index
8466 PNG_TYPE,
8467 PNG_DATA,
8468 PNG_FILE,
8469 PNG_ASCENT,
8470 PNG_MARGIN,
8471 PNG_RELIEF,
8472 PNG_ALGORITHM,
8473 PNG_HEURISTIC_MASK,
8474 PNG_MASK,
8475 PNG_LAST
8478 /* Vector of image_keyword structures describing the format
8479 of valid user-defined image specifications. */
8481 static struct image_keyword png_format[PNG_LAST] =
8483 {":type", IMAGE_SYMBOL_VALUE, 1},
8484 {":data", IMAGE_STRING_VALUE, 0},
8485 {":file", IMAGE_STRING_VALUE, 0},
8486 {":ascent", IMAGE_ASCENT_VALUE, 0},
8487 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8488 {":relief", IMAGE_INTEGER_VALUE, 0},
8489 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8490 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8491 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8494 /* Structure describing the image type `png'. */
8496 static struct image_type png_type =
8498 &Qpng,
8499 png_image_p,
8500 png_load,
8501 x_clear_image,
8502 NULL
8506 /* Return non-zero if OBJECT is a valid PNG image specification. */
8508 static int
8509 png_image_p (object)
8510 Lisp_Object object;
8512 struct image_keyword fmt[PNG_LAST];
8513 bcopy (png_format, fmt, sizeof fmt);
8515 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8516 return 0;
8518 /* Must specify either the :data or :file keyword. */
8519 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8523 /* Error and warning handlers installed when the PNG library
8524 is initialized. */
8526 static void
8527 my_png_error (png_ptr, msg)
8528 png_struct *png_ptr;
8529 char *msg;
8531 xassert (png_ptr != NULL);
8532 image_error ("PNG error: %s", build_string (msg), Qnil);
8533 longjmp (png_ptr->jmpbuf, 1);
8537 static void
8538 my_png_warning (png_ptr, msg)
8539 png_struct *png_ptr;
8540 char *msg;
8542 xassert (png_ptr != NULL);
8543 image_error ("PNG warning: %s", build_string (msg), Qnil);
8546 /* Memory source for PNG decoding. */
8548 struct png_memory_storage
8550 unsigned char *bytes; /* The data */
8551 size_t len; /* How big is it? */
8552 int index; /* Where are we? */
8556 /* Function set as reader function when reading PNG image from memory.
8557 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8558 bytes from the input to DATA. */
8560 static void
8561 png_read_from_memory (png_ptr, data, length)
8562 png_structp png_ptr;
8563 png_bytep data;
8564 png_size_t length;
8566 struct png_memory_storage *tbr
8567 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8569 if (length > tbr->len - tbr->index)
8570 png_error (png_ptr, "Read error");
8572 bcopy (tbr->bytes + tbr->index, data, length);
8573 tbr->index = tbr->index + length;
8576 /* Load PNG image IMG for use on frame F. Value is non-zero if
8577 successful. */
8579 static int
8580 png_load (f, img)
8581 struct frame *f;
8582 struct image *img;
8584 Lisp_Object file, specified_file;
8585 Lisp_Object specified_data;
8586 int x, y, i;
8587 XImage *ximg, *mask_img = NULL;
8588 struct gcpro gcpro1;
8589 png_struct *png_ptr = NULL;
8590 png_info *info_ptr = NULL, *end_info = NULL;
8591 FILE *volatile fp = NULL;
8592 png_byte sig[8];
8593 png_byte * volatile pixels = NULL;
8594 png_byte ** volatile rows = NULL;
8595 png_uint_32 width, height;
8596 int bit_depth, color_type, interlace_type;
8597 png_byte channels;
8598 png_uint_32 row_bytes;
8599 int transparent_p;
8600 char *gamma_str;
8601 double screen_gamma, image_gamma;
8602 int intent;
8603 struct png_memory_storage tbr; /* Data to be read */
8605 /* Find out what file to load. */
8606 specified_file = image_spec_value (img->spec, QCfile, NULL);
8607 specified_data = image_spec_value (img->spec, QCdata, NULL);
8608 file = Qnil;
8609 GCPRO1 (file);
8611 if (NILP (specified_data))
8613 file = x_find_image_file (specified_file);
8614 if (!STRINGP (file))
8616 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8617 UNGCPRO;
8618 return 0;
8621 /* Open the image file. */
8622 fp = fopen (XSTRING (file)->data, "rb");
8623 if (!fp)
8625 image_error ("Cannot open image file `%s'", file, Qnil);
8626 UNGCPRO;
8627 fclose (fp);
8628 return 0;
8631 /* Check PNG signature. */
8632 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8633 || !png_check_sig (sig, sizeof sig))
8635 image_error ("Not a PNG file: `%s'", file, Qnil);
8636 UNGCPRO;
8637 fclose (fp);
8638 return 0;
8641 else
8643 /* Read from memory. */
8644 tbr.bytes = XSTRING (specified_data)->data;
8645 tbr.len = STRING_BYTES (XSTRING (specified_data));
8646 tbr.index = 0;
8648 /* Check PNG signature. */
8649 if (tbr.len < sizeof sig
8650 || !png_check_sig (tbr.bytes, sizeof sig))
8652 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8653 UNGCPRO;
8654 return 0;
8657 /* Need to skip past the signature. */
8658 tbr.bytes += sizeof (sig);
8661 /* Initialize read and info structs for PNG lib. */
8662 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8663 my_png_error, my_png_warning);
8664 if (!png_ptr)
8666 if (fp) fclose (fp);
8667 UNGCPRO;
8668 return 0;
8671 info_ptr = png_create_info_struct (png_ptr);
8672 if (!info_ptr)
8674 png_destroy_read_struct (&png_ptr, NULL, NULL);
8675 if (fp) fclose (fp);
8676 UNGCPRO;
8677 return 0;
8680 end_info = png_create_info_struct (png_ptr);
8681 if (!end_info)
8683 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8684 if (fp) fclose (fp);
8685 UNGCPRO;
8686 return 0;
8689 /* Set error jump-back. We come back here when the PNG library
8690 detects an error. */
8691 if (setjmp (png_ptr->jmpbuf))
8693 error:
8694 if (png_ptr)
8695 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8696 xfree (pixels);
8697 xfree (rows);
8698 if (fp) fclose (fp);
8699 UNGCPRO;
8700 return 0;
8703 /* Read image info. */
8704 if (!NILP (specified_data))
8705 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8706 else
8707 png_init_io (png_ptr, fp);
8709 png_set_sig_bytes (png_ptr, sizeof sig);
8710 png_read_info (png_ptr, info_ptr);
8711 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8712 &interlace_type, NULL, NULL);
8714 /* If image contains simply transparency data, we prefer to
8715 construct a clipping mask. */
8716 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8717 transparent_p = 1;
8718 else
8719 transparent_p = 0;
8721 /* This function is easier to write if we only have to handle
8722 one data format: RGB or RGBA with 8 bits per channel. Let's
8723 transform other formats into that format. */
8725 /* Strip more than 8 bits per channel. */
8726 if (bit_depth == 16)
8727 png_set_strip_16 (png_ptr);
8729 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8730 if available. */
8731 png_set_expand (png_ptr);
8733 /* Convert grayscale images to RGB. */
8734 if (color_type == PNG_COLOR_TYPE_GRAY
8735 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8736 png_set_gray_to_rgb (png_ptr);
8738 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8739 gamma_str = getenv ("SCREEN_GAMMA");
8740 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8742 /* Tell the PNG lib to handle gamma correction for us. */
8744 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8745 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8746 /* There is a special chunk in the image specifying the gamma. */
8747 png_set_sRGB (png_ptr, info_ptr, intent);
8748 else
8749 #endif
8750 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8751 /* Image contains gamma information. */
8752 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8753 else
8754 /* Use a default of 0.5 for the image gamma. */
8755 png_set_gamma (png_ptr, screen_gamma, 0.5);
8757 /* Handle alpha channel by combining the image with a background
8758 color. Do this only if a real alpha channel is supplied. For
8759 simple transparency, we prefer a clipping mask. */
8760 if (!transparent_p)
8762 png_color_16 *image_background;
8764 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8765 /* Image contains a background color with which to
8766 combine the image. */
8767 png_set_background (png_ptr, image_background,
8768 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8769 else
8771 /* Image does not contain a background color with which
8772 to combine the image data via an alpha channel. Use
8773 the frame's background instead. */
8774 XColor color;
8775 Colormap cmap;
8776 png_color_16 frame_background;
8778 cmap = FRAME_X_COLORMAP (f);
8779 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8780 x_query_color (f, &color);
8782 bzero (&frame_background, sizeof frame_background);
8783 frame_background.red = color.red;
8784 frame_background.green = color.green;
8785 frame_background.blue = color.blue;
8787 png_set_background (png_ptr, &frame_background,
8788 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8792 /* Update info structure. */
8793 png_read_update_info (png_ptr, info_ptr);
8795 /* Get number of channels. Valid values are 1 for grayscale images
8796 and images with a palette, 2 for grayscale images with transparency
8797 information (alpha channel), 3 for RGB images, and 4 for RGB
8798 images with alpha channel, i.e. RGBA. If conversions above were
8799 sufficient we should only have 3 or 4 channels here. */
8800 channels = png_get_channels (png_ptr, info_ptr);
8801 xassert (channels == 3 || channels == 4);
8803 /* Number of bytes needed for one row of the image. */
8804 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8806 /* Allocate memory for the image. */
8807 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8808 rows = (png_byte **) xmalloc (height * sizeof *rows);
8809 for (i = 0; i < height; ++i)
8810 rows[i] = pixels + i * row_bytes;
8812 /* Read the entire image. */
8813 png_read_image (png_ptr, rows);
8814 png_read_end (png_ptr, info_ptr);
8815 if (fp)
8817 fclose (fp);
8818 fp = NULL;
8821 /* Create the X image and pixmap. */
8822 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8823 &img->pixmap))
8824 goto error;
8826 /* Create an image and pixmap serving as mask if the PNG image
8827 contains an alpha channel. */
8828 if (channels == 4
8829 && !transparent_p
8830 && !x_create_x_image_and_pixmap (f, width, height, 1,
8831 &mask_img, &img->mask))
8833 x_destroy_x_image (ximg);
8834 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8835 img->pixmap = None;
8836 goto error;
8839 /* Fill the X image and mask from PNG data. */
8840 init_color_table ();
8842 for (y = 0; y < height; ++y)
8844 png_byte *p = rows[y];
8846 for (x = 0; x < width; ++x)
8848 unsigned r, g, b;
8850 r = *p++ << 8;
8851 g = *p++ << 8;
8852 b = *p++ << 8;
8853 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8855 /* An alpha channel, aka mask channel, associates variable
8856 transparency with an image. Where other image formats
8857 support binary transparency---fully transparent or fully
8858 opaque---PNG allows up to 254 levels of partial transparency.
8859 The PNG library implements partial transparency by combining
8860 the image with a specified background color.
8862 I'm not sure how to handle this here nicely: because the
8863 background on which the image is displayed may change, for
8864 real alpha channel support, it would be necessary to create
8865 a new image for each possible background.
8867 What I'm doing now is that a mask is created if we have
8868 boolean transparency information. Otherwise I'm using
8869 the frame's background color to combine the image with. */
8871 if (channels == 4)
8873 if (mask_img)
8874 XPutPixel (mask_img, x, y, *p > 0);
8875 ++p;
8880 /* Remember colors allocated for this image. */
8881 img->colors = colors_in_color_table (&img->ncolors);
8882 free_color_table ();
8884 /* Clean up. */
8885 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8886 xfree (rows);
8887 xfree (pixels);
8889 img->width = width;
8890 img->height = height;
8892 /* Put the image into the pixmap, then free the X image and its buffer. */
8893 x_put_x_image (f, ximg, img->pixmap, width, height);
8894 x_destroy_x_image (ximg);
8896 /* Same for the mask. */
8897 if (mask_img)
8899 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8900 x_destroy_x_image (mask_img);
8903 UNGCPRO;
8904 return 1;
8907 #endif /* HAVE_PNG != 0 */
8911 /***********************************************************************
8912 JPEG
8913 ***********************************************************************/
8915 #if HAVE_JPEG
8917 /* Work around a warning about HAVE_STDLIB_H being redefined in
8918 jconfig.h. */
8919 #ifdef HAVE_STDLIB_H
8920 #define HAVE_STDLIB_H_1
8921 #undef HAVE_STDLIB_H
8922 #endif /* HAVE_STLIB_H */
8924 #include <jpeglib.h>
8925 #include <jerror.h>
8926 #include <setjmp.h>
8928 #ifdef HAVE_STLIB_H_1
8929 #define HAVE_STDLIB_H 1
8930 #endif
8932 static int jpeg_image_p P_ ((Lisp_Object object));
8933 static int jpeg_load P_ ((struct frame *f, struct image *img));
8935 /* The symbol `jpeg' identifying images of this type. */
8937 Lisp_Object Qjpeg;
8939 /* Indices of image specification fields in gs_format, below. */
8941 enum jpeg_keyword_index
8943 JPEG_TYPE,
8944 JPEG_DATA,
8945 JPEG_FILE,
8946 JPEG_ASCENT,
8947 JPEG_MARGIN,
8948 JPEG_RELIEF,
8949 JPEG_ALGORITHM,
8950 JPEG_HEURISTIC_MASK,
8951 JPEG_MASK,
8952 JPEG_LAST
8955 /* Vector of image_keyword structures describing the format
8956 of valid user-defined image specifications. */
8958 static struct image_keyword jpeg_format[JPEG_LAST] =
8960 {":type", IMAGE_SYMBOL_VALUE, 1},
8961 {":data", IMAGE_STRING_VALUE, 0},
8962 {":file", IMAGE_STRING_VALUE, 0},
8963 {":ascent", IMAGE_ASCENT_VALUE, 0},
8964 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8965 {":relief", IMAGE_INTEGER_VALUE, 0},
8966 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8967 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8968 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8971 /* Structure describing the image type `jpeg'. */
8973 static struct image_type jpeg_type =
8975 &Qjpeg,
8976 jpeg_image_p,
8977 jpeg_load,
8978 x_clear_image,
8979 NULL
8983 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8985 static int
8986 jpeg_image_p (object)
8987 Lisp_Object object;
8989 struct image_keyword fmt[JPEG_LAST];
8991 bcopy (jpeg_format, fmt, sizeof fmt);
8993 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8994 return 0;
8996 /* Must specify either the :data or :file keyword. */
8997 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9001 struct my_jpeg_error_mgr
9003 struct jpeg_error_mgr pub;
9004 jmp_buf setjmp_buffer;
9008 static void
9009 my_error_exit (cinfo)
9010 j_common_ptr cinfo;
9012 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9013 longjmp (mgr->setjmp_buffer, 1);
9017 /* Init source method for JPEG data source manager. Called by
9018 jpeg_read_header() before any data is actually read. See
9019 libjpeg.doc from the JPEG lib distribution. */
9021 static void
9022 our_init_source (cinfo)
9023 j_decompress_ptr cinfo;
9028 /* Fill input buffer method for JPEG data source manager. Called
9029 whenever more data is needed. We read the whole image in one step,
9030 so this only adds a fake end of input marker at the end. */
9032 static boolean
9033 our_fill_input_buffer (cinfo)
9034 j_decompress_ptr cinfo;
9036 /* Insert a fake EOI marker. */
9037 struct jpeg_source_mgr *src = cinfo->src;
9038 static JOCTET buffer[2];
9040 buffer[0] = (JOCTET) 0xFF;
9041 buffer[1] = (JOCTET) JPEG_EOI;
9043 src->next_input_byte = buffer;
9044 src->bytes_in_buffer = 2;
9045 return TRUE;
9049 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9050 is the JPEG data source manager. */
9052 static void
9053 our_skip_input_data (cinfo, num_bytes)
9054 j_decompress_ptr cinfo;
9055 long num_bytes;
9057 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9059 if (src)
9061 if (num_bytes > src->bytes_in_buffer)
9062 ERREXIT (cinfo, JERR_INPUT_EOF);
9064 src->bytes_in_buffer -= num_bytes;
9065 src->next_input_byte += num_bytes;
9070 /* Method to terminate data source. Called by
9071 jpeg_finish_decompress() after all data has been processed. */
9073 static void
9074 our_term_source (cinfo)
9075 j_decompress_ptr cinfo;
9080 /* Set up the JPEG lib for reading an image from DATA which contains
9081 LEN bytes. CINFO is the decompression info structure created for
9082 reading the image. */
9084 static void
9085 jpeg_memory_src (cinfo, data, len)
9086 j_decompress_ptr cinfo;
9087 JOCTET *data;
9088 unsigned int len;
9090 struct jpeg_source_mgr *src;
9092 if (cinfo->src == NULL)
9094 /* First time for this JPEG object? */
9095 cinfo->src = (struct jpeg_source_mgr *)
9096 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9097 sizeof (struct jpeg_source_mgr));
9098 src = (struct jpeg_source_mgr *) cinfo->src;
9099 src->next_input_byte = data;
9102 src = (struct jpeg_source_mgr *) cinfo->src;
9103 src->init_source = our_init_source;
9104 src->fill_input_buffer = our_fill_input_buffer;
9105 src->skip_input_data = our_skip_input_data;
9106 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9107 src->term_source = our_term_source;
9108 src->bytes_in_buffer = len;
9109 src->next_input_byte = data;
9113 /* Load image IMG for use on frame F. Patterned after example.c
9114 from the JPEG lib. */
9116 static int
9117 jpeg_load (f, img)
9118 struct frame *f;
9119 struct image *img;
9121 struct jpeg_decompress_struct cinfo;
9122 struct my_jpeg_error_mgr mgr;
9123 Lisp_Object file, specified_file;
9124 Lisp_Object specified_data;
9125 FILE * volatile fp = NULL;
9126 JSAMPARRAY buffer;
9127 int row_stride, x, y;
9128 XImage *ximg = NULL;
9129 int rc;
9130 unsigned long *colors;
9131 int width, height;
9132 struct gcpro gcpro1;
9134 /* Open the JPEG file. */
9135 specified_file = image_spec_value (img->spec, QCfile, NULL);
9136 specified_data = image_spec_value (img->spec, QCdata, NULL);
9137 file = Qnil;
9138 GCPRO1 (file);
9140 if (NILP (specified_data))
9142 file = x_find_image_file (specified_file);
9143 if (!STRINGP (file))
9145 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9146 UNGCPRO;
9147 return 0;
9150 fp = fopen (XSTRING (file)->data, "r");
9151 if (fp == NULL)
9153 image_error ("Cannot open `%s'", file, Qnil);
9154 UNGCPRO;
9155 return 0;
9159 /* Customize libjpeg's error handling to call my_error_exit when an
9160 error is detected. This function will perform a longjmp. */
9161 cinfo.err = jpeg_std_error (&mgr.pub);
9162 mgr.pub.error_exit = my_error_exit;
9164 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9166 if (rc == 1)
9168 /* Called from my_error_exit. Display a JPEG error. */
9169 char buffer[JMSG_LENGTH_MAX];
9170 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9171 image_error ("Error reading JPEG image `%s': %s", img->spec,
9172 build_string (buffer));
9175 /* Close the input file and destroy the JPEG object. */
9176 if (fp)
9177 fclose ((FILE *) fp);
9178 jpeg_destroy_decompress (&cinfo);
9180 /* If we already have an XImage, free that. */
9181 x_destroy_x_image (ximg);
9183 /* Free pixmap and colors. */
9184 x_clear_image (f, img);
9186 UNGCPRO;
9187 return 0;
9190 /* Create the JPEG decompression object. Let it read from fp.
9191 Read the JPEG image header. */
9192 jpeg_create_decompress (&cinfo);
9194 if (NILP (specified_data))
9195 jpeg_stdio_src (&cinfo, (FILE *) fp);
9196 else
9197 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
9198 STRING_BYTES (XSTRING (specified_data)));
9200 jpeg_read_header (&cinfo, TRUE);
9202 /* Customize decompression so that color quantization will be used.
9203 Start decompression. */
9204 cinfo.quantize_colors = TRUE;
9205 jpeg_start_decompress (&cinfo);
9206 width = img->width = cinfo.output_width;
9207 height = img->height = cinfo.output_height;
9209 /* Create X image and pixmap. */
9210 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9211 longjmp (mgr.setjmp_buffer, 2);
9213 /* Allocate colors. When color quantization is used,
9214 cinfo.actual_number_of_colors has been set with the number of
9215 colors generated, and cinfo.colormap is a two-dimensional array
9216 of color indices in the range 0..cinfo.actual_number_of_colors.
9217 No more than 255 colors will be generated. */
9219 int i, ir, ig, ib;
9221 if (cinfo.out_color_components > 2)
9222 ir = 0, ig = 1, ib = 2;
9223 else if (cinfo.out_color_components > 1)
9224 ir = 0, ig = 1, ib = 0;
9225 else
9226 ir = 0, ig = 0, ib = 0;
9228 /* Use the color table mechanism because it handles colors that
9229 cannot be allocated nicely. Such colors will be replaced with
9230 a default color, and we don't have to care about which colors
9231 can be freed safely, and which can't. */
9232 init_color_table ();
9233 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9234 * sizeof *colors);
9236 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9238 /* Multiply RGB values with 255 because X expects RGB values
9239 in the range 0..0xffff. */
9240 int r = cinfo.colormap[ir][i] << 8;
9241 int g = cinfo.colormap[ig][i] << 8;
9242 int b = cinfo.colormap[ib][i] << 8;
9243 colors[i] = lookup_rgb_color (f, r, g, b);
9246 /* Remember those colors actually allocated. */
9247 img->colors = colors_in_color_table (&img->ncolors);
9248 free_color_table ();
9251 /* Read pixels. */
9252 row_stride = width * cinfo.output_components;
9253 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9254 row_stride, 1);
9255 for (y = 0; y < height; ++y)
9257 jpeg_read_scanlines (&cinfo, buffer, 1);
9258 for (x = 0; x < cinfo.output_width; ++x)
9259 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9262 /* Clean up. */
9263 jpeg_finish_decompress (&cinfo);
9264 jpeg_destroy_decompress (&cinfo);
9265 if (fp)
9266 fclose ((FILE *) fp);
9268 /* Put the image into the pixmap. */
9269 x_put_x_image (f, ximg, img->pixmap, width, height);
9270 x_destroy_x_image (ximg);
9271 UNGCPRO;
9272 return 1;
9275 #endif /* HAVE_JPEG */
9279 /***********************************************************************
9280 TIFF
9281 ***********************************************************************/
9283 #if HAVE_TIFF
9285 #include <tiffio.h>
9287 static int tiff_image_p P_ ((Lisp_Object object));
9288 static int tiff_load P_ ((struct frame *f, struct image *img));
9290 /* The symbol `tiff' identifying images of this type. */
9292 Lisp_Object Qtiff;
9294 /* Indices of image specification fields in tiff_format, below. */
9296 enum tiff_keyword_index
9298 TIFF_TYPE,
9299 TIFF_DATA,
9300 TIFF_FILE,
9301 TIFF_ASCENT,
9302 TIFF_MARGIN,
9303 TIFF_RELIEF,
9304 TIFF_ALGORITHM,
9305 TIFF_HEURISTIC_MASK,
9306 TIFF_MASK,
9307 TIFF_LAST
9310 /* Vector of image_keyword structures describing the format
9311 of valid user-defined image specifications. */
9313 static struct image_keyword tiff_format[TIFF_LAST] =
9315 {":type", IMAGE_SYMBOL_VALUE, 1},
9316 {":data", IMAGE_STRING_VALUE, 0},
9317 {":file", IMAGE_STRING_VALUE, 0},
9318 {":ascent", IMAGE_ASCENT_VALUE, 0},
9319 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9320 {":relief", IMAGE_INTEGER_VALUE, 0},
9321 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9322 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9323 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9326 /* Structure describing the image type `tiff'. */
9328 static struct image_type tiff_type =
9330 &Qtiff,
9331 tiff_image_p,
9332 tiff_load,
9333 x_clear_image,
9334 NULL
9338 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9340 static int
9341 tiff_image_p (object)
9342 Lisp_Object object;
9344 struct image_keyword fmt[TIFF_LAST];
9345 bcopy (tiff_format, fmt, sizeof fmt);
9347 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9348 return 0;
9350 /* Must specify either the :data or :file keyword. */
9351 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9355 /* Reading from a memory buffer for TIFF images Based on the PNG
9356 memory source, but we have to provide a lot of extra functions.
9357 Blah.
9359 We really only need to implement read and seek, but I am not
9360 convinced that the TIFF library is smart enough not to destroy
9361 itself if we only hand it the function pointers we need to
9362 override. */
9364 typedef struct
9366 unsigned char *bytes;
9367 size_t len;
9368 int index;
9370 tiff_memory_source;
9373 static size_t
9374 tiff_read_from_memory (data, buf, size)
9375 thandle_t data;
9376 tdata_t buf;
9377 tsize_t size;
9379 tiff_memory_source *src = (tiff_memory_source *) data;
9381 if (size > src->len - src->index)
9382 return (size_t) -1;
9383 bcopy (src->bytes + src->index, buf, size);
9384 src->index += size;
9385 return size;
9389 static size_t
9390 tiff_write_from_memory (data, buf, size)
9391 thandle_t data;
9392 tdata_t buf;
9393 tsize_t size;
9395 return (size_t) -1;
9399 static toff_t
9400 tiff_seek_in_memory (data, off, whence)
9401 thandle_t data;
9402 toff_t off;
9403 int whence;
9405 tiff_memory_source *src = (tiff_memory_source *) data;
9406 int idx;
9408 switch (whence)
9410 case SEEK_SET: /* Go from beginning of source. */
9411 idx = off;
9412 break;
9414 case SEEK_END: /* Go from end of source. */
9415 idx = src->len + off;
9416 break;
9418 case SEEK_CUR: /* Go from current position. */
9419 idx = src->index + off;
9420 break;
9422 default: /* Invalid `whence'. */
9423 return -1;
9426 if (idx > src->len || idx < 0)
9427 return -1;
9429 src->index = idx;
9430 return src->index;
9434 static int
9435 tiff_close_memory (data)
9436 thandle_t data;
9438 /* NOOP */
9439 return 0;
9443 static int
9444 tiff_mmap_memory (data, pbase, psize)
9445 thandle_t data;
9446 tdata_t *pbase;
9447 toff_t *psize;
9449 /* It is already _IN_ memory. */
9450 return 0;
9454 static void
9455 tiff_unmap_memory (data, base, size)
9456 thandle_t data;
9457 tdata_t base;
9458 toff_t size;
9460 /* We don't need to do this. */
9464 static toff_t
9465 tiff_size_of_memory (data)
9466 thandle_t data;
9468 return ((tiff_memory_source *) data)->len;
9472 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9473 successful. */
9475 static int
9476 tiff_load (f, img)
9477 struct frame *f;
9478 struct image *img;
9480 Lisp_Object file, specified_file;
9481 Lisp_Object specified_data;
9482 TIFF *tiff;
9483 int width, height, x, y;
9484 uint32 *buf;
9485 int rc;
9486 XImage *ximg;
9487 struct gcpro gcpro1;
9488 tiff_memory_source memsrc;
9490 specified_file = image_spec_value (img->spec, QCfile, NULL);
9491 specified_data = image_spec_value (img->spec, QCdata, NULL);
9492 file = Qnil;
9493 GCPRO1 (file);
9495 if (NILP (specified_data))
9497 /* Read from a file */
9498 file = x_find_image_file (specified_file);
9499 if (!STRINGP (file))
9501 image_error ("Cannot find image file `%s'", file, Qnil);
9502 UNGCPRO;
9503 return 0;
9506 /* Try to open the image file. */
9507 tiff = TIFFOpen (XSTRING (file)->data, "r");
9508 if (tiff == NULL)
9510 image_error ("Cannot open `%s'", file, Qnil);
9511 UNGCPRO;
9512 return 0;
9515 else
9517 /* Memory source! */
9518 memsrc.bytes = XSTRING (specified_data)->data;
9519 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9520 memsrc.index = 0;
9522 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9523 (TIFFReadWriteProc) tiff_read_from_memory,
9524 (TIFFReadWriteProc) tiff_write_from_memory,
9525 tiff_seek_in_memory,
9526 tiff_close_memory,
9527 tiff_size_of_memory,
9528 tiff_mmap_memory,
9529 tiff_unmap_memory);
9531 if (!tiff)
9533 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9534 UNGCPRO;
9535 return 0;
9539 /* Get width and height of the image, and allocate a raster buffer
9540 of width x height 32-bit values. */
9541 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9542 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9543 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9545 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9546 TIFFClose (tiff);
9547 if (!rc)
9549 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9550 xfree (buf);
9551 UNGCPRO;
9552 return 0;
9555 /* Create the X image and pixmap. */
9556 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9558 xfree (buf);
9559 UNGCPRO;
9560 return 0;
9563 /* Initialize the color table. */
9564 init_color_table ();
9566 /* Process the pixel raster. Origin is in the lower-left corner. */
9567 for (y = 0; y < height; ++y)
9569 uint32 *row = buf + y * width;
9571 for (x = 0; x < width; ++x)
9573 uint32 abgr = row[x];
9574 int r = TIFFGetR (abgr) << 8;
9575 int g = TIFFGetG (abgr) << 8;
9576 int b = TIFFGetB (abgr) << 8;
9577 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9581 /* Remember the colors allocated for the image. Free the color table. */
9582 img->colors = colors_in_color_table (&img->ncolors);
9583 free_color_table ();
9585 /* Put the image into the pixmap, then free the X image and its buffer. */
9586 x_put_x_image (f, ximg, img->pixmap, width, height);
9587 x_destroy_x_image (ximg);
9588 xfree (buf);
9590 img->width = width;
9591 img->height = height;
9593 UNGCPRO;
9594 return 1;
9597 #endif /* HAVE_TIFF != 0 */
9601 /***********************************************************************
9603 ***********************************************************************/
9605 #if HAVE_GIF
9607 #include <gif_lib.h>
9609 static int gif_image_p P_ ((Lisp_Object object));
9610 static int gif_load P_ ((struct frame *f, struct image *img));
9612 /* The symbol `gif' identifying images of this type. */
9614 Lisp_Object Qgif;
9616 /* Indices of image specification fields in gif_format, below. */
9618 enum gif_keyword_index
9620 GIF_TYPE,
9621 GIF_DATA,
9622 GIF_FILE,
9623 GIF_ASCENT,
9624 GIF_MARGIN,
9625 GIF_RELIEF,
9626 GIF_ALGORITHM,
9627 GIF_HEURISTIC_MASK,
9628 GIF_MASK,
9629 GIF_IMAGE,
9630 GIF_LAST
9633 /* Vector of image_keyword structures describing the format
9634 of valid user-defined image specifications. */
9636 static struct image_keyword gif_format[GIF_LAST] =
9638 {":type", IMAGE_SYMBOL_VALUE, 1},
9639 {":data", IMAGE_STRING_VALUE, 0},
9640 {":file", IMAGE_STRING_VALUE, 0},
9641 {":ascent", IMAGE_ASCENT_VALUE, 0},
9642 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9643 {":relief", IMAGE_INTEGER_VALUE, 0},
9644 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9645 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9646 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9647 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9650 /* Structure describing the image type `gif'. */
9652 static struct image_type gif_type =
9654 &Qgif,
9655 gif_image_p,
9656 gif_load,
9657 x_clear_image,
9658 NULL
9662 /* Return non-zero if OBJECT is a valid GIF image specification. */
9664 static int
9665 gif_image_p (object)
9666 Lisp_Object object;
9668 struct image_keyword fmt[GIF_LAST];
9669 bcopy (gif_format, fmt, sizeof fmt);
9671 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9672 return 0;
9674 /* Must specify either the :data or :file keyword. */
9675 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9679 /* Reading a GIF image from memory
9680 Based on the PNG memory stuff to a certain extent. */
9682 typedef struct
9684 unsigned char *bytes;
9685 size_t len;
9686 int index;
9688 gif_memory_source;
9691 /* Make the current memory source available to gif_read_from_memory.
9692 It's done this way because not all versions of libungif support
9693 a UserData field in the GifFileType structure. */
9694 static gif_memory_source *current_gif_memory_src;
9696 static int
9697 gif_read_from_memory (file, buf, len)
9698 GifFileType *file;
9699 GifByteType *buf;
9700 int len;
9702 gif_memory_source *src = current_gif_memory_src;
9704 if (len > src->len - src->index)
9705 return -1;
9707 bcopy (src->bytes + src->index, buf, len);
9708 src->index += len;
9709 return len;
9713 /* Load GIF image IMG for use on frame F. Value is non-zero if
9714 successful. */
9716 static int
9717 gif_load (f, img)
9718 struct frame *f;
9719 struct image *img;
9721 Lisp_Object file, specified_file;
9722 Lisp_Object specified_data;
9723 int rc, width, height, x, y, i;
9724 XImage *ximg;
9725 ColorMapObject *gif_color_map;
9726 unsigned long pixel_colors[256];
9727 GifFileType *gif;
9728 struct gcpro gcpro1;
9729 Lisp_Object image;
9730 int ino, image_left, image_top, image_width, image_height;
9731 gif_memory_source memsrc;
9732 unsigned char *raster;
9734 specified_file = image_spec_value (img->spec, QCfile, NULL);
9735 specified_data = image_spec_value (img->spec, QCdata, NULL);
9736 file = Qnil;
9737 GCPRO1 (file);
9739 if (NILP (specified_data))
9741 file = x_find_image_file (specified_file);
9742 if (!STRINGP (file))
9744 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9745 UNGCPRO;
9746 return 0;
9749 /* Open the GIF file. */
9750 gif = DGifOpenFileName (XSTRING (file)->data);
9751 if (gif == NULL)
9753 image_error ("Cannot open `%s'", file, Qnil);
9754 UNGCPRO;
9755 return 0;
9758 else
9760 /* Read from memory! */
9761 current_gif_memory_src = &memsrc;
9762 memsrc.bytes = XSTRING (specified_data)->data;
9763 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9764 memsrc.index = 0;
9766 gif = DGifOpen(&memsrc, gif_read_from_memory);
9767 if (!gif)
9769 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9770 UNGCPRO;
9771 return 0;
9775 /* Read entire contents. */
9776 rc = DGifSlurp (gif);
9777 if (rc == GIF_ERROR)
9779 image_error ("Error reading `%s'", img->spec, Qnil);
9780 DGifCloseFile (gif);
9781 UNGCPRO;
9782 return 0;
9785 image = image_spec_value (img->spec, QCindex, NULL);
9786 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9787 if (ino >= gif->ImageCount)
9789 image_error ("Invalid image number `%s' in image `%s'",
9790 image, img->spec);
9791 DGifCloseFile (gif);
9792 UNGCPRO;
9793 return 0;
9796 width = img->width = gif->SWidth;
9797 height = img->height = gif->SHeight;
9799 /* Create the X image and pixmap. */
9800 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9802 DGifCloseFile (gif);
9803 UNGCPRO;
9804 return 0;
9807 /* Allocate colors. */
9808 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9809 if (!gif_color_map)
9810 gif_color_map = gif->SColorMap;
9811 init_color_table ();
9812 bzero (pixel_colors, sizeof pixel_colors);
9814 for (i = 0; i < gif_color_map->ColorCount; ++i)
9816 int r = gif_color_map->Colors[i].Red << 8;
9817 int g = gif_color_map->Colors[i].Green << 8;
9818 int b = gif_color_map->Colors[i].Blue << 8;
9819 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9822 img->colors = colors_in_color_table (&img->ncolors);
9823 free_color_table ();
9825 /* Clear the part of the screen image that are not covered by
9826 the image from the GIF file. Full animated GIF support
9827 requires more than can be done here (see the gif89 spec,
9828 disposal methods). Let's simply assume that the part
9829 not covered by a sub-image is in the frame's background color. */
9830 image_top = gif->SavedImages[ino].ImageDesc.Top;
9831 image_left = gif->SavedImages[ino].ImageDesc.Left;
9832 image_width = gif->SavedImages[ino].ImageDesc.Width;
9833 image_height = gif->SavedImages[ino].ImageDesc.Height;
9835 for (y = 0; y < image_top; ++y)
9836 for (x = 0; x < width; ++x)
9837 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9839 for (y = image_top + image_height; y < height; ++y)
9840 for (x = 0; x < width; ++x)
9841 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9843 for (y = image_top; y < image_top + image_height; ++y)
9845 for (x = 0; x < image_left; ++x)
9846 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9847 for (x = image_left + image_width; x < width; ++x)
9848 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9851 /* Read the GIF image into the X image. We use a local variable
9852 `raster' here because RasterBits below is a char *, and invites
9853 problems with bytes >= 0x80. */
9854 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9856 if (gif->SavedImages[ino].ImageDesc.Interlace)
9858 static int interlace_start[] = {0, 4, 2, 1};
9859 static int interlace_increment[] = {8, 8, 4, 2};
9860 int pass;
9861 int row = interlace_start[0];
9863 pass = 0;
9865 for (y = 0; y < image_height; y++)
9867 if (row >= image_height)
9869 row = interlace_start[++pass];
9870 while (row >= image_height)
9871 row = interlace_start[++pass];
9874 for (x = 0; x < image_width; x++)
9876 int i = raster[(y * image_width) + x];
9877 XPutPixel (ximg, x + image_left, row + image_top,
9878 pixel_colors[i]);
9881 row += interlace_increment[pass];
9884 else
9886 for (y = 0; y < image_height; ++y)
9887 for (x = 0; x < image_width; ++x)
9889 int i = raster[y * image_width + x];
9890 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9894 DGifCloseFile (gif);
9896 /* Put the image into the pixmap, then free the X image and its buffer. */
9897 x_put_x_image (f, ximg, img->pixmap, width, height);
9898 x_destroy_x_image (ximg);
9900 UNGCPRO;
9901 return 1;
9904 #endif /* HAVE_GIF != 0 */
9908 /***********************************************************************
9909 Ghostscript
9910 ***********************************************************************/
9912 static int gs_image_p P_ ((Lisp_Object object));
9913 static int gs_load P_ ((struct frame *f, struct image *img));
9914 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9916 /* The symbol `postscript' identifying images of this type. */
9918 Lisp_Object Qpostscript;
9920 /* Keyword symbols. */
9922 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9924 /* Indices of image specification fields in gs_format, below. */
9926 enum gs_keyword_index
9928 GS_TYPE,
9929 GS_PT_WIDTH,
9930 GS_PT_HEIGHT,
9931 GS_FILE,
9932 GS_LOADER,
9933 GS_BOUNDING_BOX,
9934 GS_ASCENT,
9935 GS_MARGIN,
9936 GS_RELIEF,
9937 GS_ALGORITHM,
9938 GS_HEURISTIC_MASK,
9939 GS_MASK,
9940 GS_LAST
9943 /* Vector of image_keyword structures describing the format
9944 of valid user-defined image specifications. */
9946 static struct image_keyword gs_format[GS_LAST] =
9948 {":type", IMAGE_SYMBOL_VALUE, 1},
9949 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9950 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9951 {":file", IMAGE_STRING_VALUE, 1},
9952 {":loader", IMAGE_FUNCTION_VALUE, 0},
9953 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9954 {":ascent", IMAGE_ASCENT_VALUE, 0},
9955 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9956 {":relief", IMAGE_INTEGER_VALUE, 0},
9957 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9958 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9959 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9962 /* Structure describing the image type `ghostscript'. */
9964 static struct image_type gs_type =
9966 &Qpostscript,
9967 gs_image_p,
9968 gs_load,
9969 gs_clear_image,
9970 NULL
9974 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9976 static void
9977 gs_clear_image (f, img)
9978 struct frame *f;
9979 struct image *img;
9981 /* IMG->data.ptr_val may contain a recorded colormap. */
9982 xfree (img->data.ptr_val);
9983 x_clear_image (f, img);
9987 /* Return non-zero if OBJECT is a valid Ghostscript image
9988 specification. */
9990 static int
9991 gs_image_p (object)
9992 Lisp_Object object;
9994 struct image_keyword fmt[GS_LAST];
9995 Lisp_Object tem;
9996 int i;
9998 bcopy (gs_format, fmt, sizeof fmt);
10000 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10001 return 0;
10003 /* Bounding box must be a list or vector containing 4 integers. */
10004 tem = fmt[GS_BOUNDING_BOX].value;
10005 if (CONSP (tem))
10007 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10008 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10009 return 0;
10010 if (!NILP (tem))
10011 return 0;
10013 else if (VECTORP (tem))
10015 if (XVECTOR (tem)->size != 4)
10016 return 0;
10017 for (i = 0; i < 4; ++i)
10018 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10019 return 0;
10021 else
10022 return 0;
10024 return 1;
10028 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10029 if successful. */
10031 static int
10032 gs_load (f, img)
10033 struct frame *f;
10034 struct image *img;
10036 char buffer[100];
10037 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10038 struct gcpro gcpro1, gcpro2;
10039 Lisp_Object frame;
10040 double in_width, in_height;
10041 Lisp_Object pixel_colors = Qnil;
10043 /* Compute pixel size of pixmap needed from the given size in the
10044 image specification. Sizes in the specification are in pt. 1 pt
10045 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10046 info. */
10047 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10048 in_width = XFASTINT (pt_width) / 72.0;
10049 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10050 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10051 in_height = XFASTINT (pt_height) / 72.0;
10052 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10054 /* Create the pixmap. */
10055 xassert (img->pixmap == None);
10056 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10057 img->width, img->height,
10058 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10060 if (!img->pixmap)
10062 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10063 return 0;
10066 /* Call the loader to fill the pixmap. It returns a process object
10067 if successful. We do not record_unwind_protect here because
10068 other places in redisplay like calling window scroll functions
10069 don't either. Let the Lisp loader use `unwind-protect' instead. */
10070 GCPRO2 (window_and_pixmap_id, pixel_colors);
10072 sprintf (buffer, "%lu %lu",
10073 (unsigned long) FRAME_X_WINDOW (f),
10074 (unsigned long) img->pixmap);
10075 window_and_pixmap_id = build_string (buffer);
10077 sprintf (buffer, "%lu %lu",
10078 FRAME_FOREGROUND_PIXEL (f),
10079 FRAME_BACKGROUND_PIXEL (f));
10080 pixel_colors = build_string (buffer);
10082 XSETFRAME (frame, f);
10083 loader = image_spec_value (img->spec, QCloader, NULL);
10084 if (NILP (loader))
10085 loader = intern ("gs-load-image");
10087 img->data.lisp_val = call6 (loader, frame, img->spec,
10088 make_number (img->width),
10089 make_number (img->height),
10090 window_and_pixmap_id,
10091 pixel_colors);
10092 UNGCPRO;
10093 return PROCESSP (img->data.lisp_val);
10097 /* Kill the Ghostscript process that was started to fill PIXMAP on
10098 frame F. Called from XTread_socket when receiving an event
10099 telling Emacs that Ghostscript has finished drawing. */
10101 void
10102 x_kill_gs_process (pixmap, f)
10103 Pixmap pixmap;
10104 struct frame *f;
10106 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10107 int class, i;
10108 struct image *img;
10110 /* Find the image containing PIXMAP. */
10111 for (i = 0; i < c->used; ++i)
10112 if (c->images[i]->pixmap == pixmap)
10113 break;
10115 /* Kill the GS process. We should have found PIXMAP in the image
10116 cache and its image should contain a process object. */
10117 xassert (i < c->used);
10118 img = c->images[i];
10119 xassert (PROCESSP (img->data.lisp_val));
10120 Fkill_process (img->data.lisp_val, Qnil);
10121 img->data.lisp_val = Qnil;
10123 /* On displays with a mutable colormap, figure out the colors
10124 allocated for the image by looking at the pixels of an XImage for
10125 img->pixmap. */
10126 class = FRAME_X_VISUAL (f)->class;
10127 if (class != StaticColor && class != StaticGray && class != TrueColor)
10129 XImage *ximg;
10131 BLOCK_INPUT;
10133 /* Try to get an XImage for img->pixmep. */
10134 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10135 0, 0, img->width, img->height, ~0, ZPixmap);
10136 if (ximg)
10138 int x, y;
10140 /* Initialize the color table. */
10141 init_color_table ();
10143 /* For each pixel of the image, look its color up in the
10144 color table. After having done so, the color table will
10145 contain an entry for each color used by the image. */
10146 for (y = 0; y < img->height; ++y)
10147 for (x = 0; x < img->width; ++x)
10149 unsigned long pixel = XGetPixel (ximg, x, y);
10150 lookup_pixel_color (f, pixel);
10153 /* Record colors in the image. Free color table and XImage. */
10154 img->colors = colors_in_color_table (&img->ncolors);
10155 free_color_table ();
10156 XDestroyImage (ximg);
10158 #if 0 /* This doesn't seem to be the case. If we free the colors
10159 here, we get a BadAccess later in x_clear_image when
10160 freeing the colors. */
10161 /* We have allocated colors once, but Ghostscript has also
10162 allocated colors on behalf of us. So, to get the
10163 reference counts right, free them once. */
10164 if (img->ncolors)
10165 x_free_colors (f, img->colors, img->ncolors);
10166 #endif
10168 else
10169 image_error ("Cannot get X image of `%s'; colors will not be freed",
10170 img->spec, Qnil);
10172 UNBLOCK_INPUT;
10175 /* Now that we have the pixmap, compute mask and transform the
10176 image if requested. */
10177 BLOCK_INPUT;
10178 postprocess_image (f, img);
10179 UNBLOCK_INPUT;
10184 /***********************************************************************
10185 Window properties
10186 ***********************************************************************/
10188 DEFUN ("x-change-window-property", Fx_change_window_property,
10189 Sx_change_window_property, 2, 3, 0,
10190 "Change window property PROP to VALUE on the X window of FRAME.\n\
10191 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
10192 selected frame. Value is VALUE.")
10193 (prop, value, frame)
10194 Lisp_Object frame, prop, value;
10196 struct frame *f = check_x_frame (frame);
10197 Atom prop_atom;
10199 CHECK_STRING (prop, 1);
10200 CHECK_STRING (value, 2);
10202 BLOCK_INPUT;
10203 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10204 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10205 prop_atom, XA_STRING, 8, PropModeReplace,
10206 XSTRING (value)->data, XSTRING (value)->size);
10208 /* Make sure the property is set when we return. */
10209 XFlush (FRAME_X_DISPLAY (f));
10210 UNBLOCK_INPUT;
10212 return value;
10216 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10217 Sx_delete_window_property, 1, 2, 0,
10218 "Remove window property PROP from X window of FRAME.\n\
10219 FRAME nil or omitted means use the selected frame. Value is PROP.")
10220 (prop, frame)
10221 Lisp_Object prop, frame;
10223 struct frame *f = check_x_frame (frame);
10224 Atom prop_atom;
10226 CHECK_STRING (prop, 1);
10227 BLOCK_INPUT;
10228 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10229 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10231 /* Make sure the property is removed when we return. */
10232 XFlush (FRAME_X_DISPLAY (f));
10233 UNBLOCK_INPUT;
10235 return prop;
10239 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10240 1, 2, 0,
10241 "Value is the value of window property PROP on FRAME.\n\
10242 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10243 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10244 value.")
10245 (prop, frame)
10246 Lisp_Object prop, frame;
10248 struct frame *f = check_x_frame (frame);
10249 Atom prop_atom;
10250 int rc;
10251 Lisp_Object prop_value = Qnil;
10252 char *tmp_data = NULL;
10253 Atom actual_type;
10254 int actual_format;
10255 unsigned long actual_size, bytes_remaining;
10257 CHECK_STRING (prop, 1);
10258 BLOCK_INPUT;
10259 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10260 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10261 prop_atom, 0, 0, False, XA_STRING,
10262 &actual_type, &actual_format, &actual_size,
10263 &bytes_remaining, (unsigned char **) &tmp_data);
10264 if (rc == Success)
10266 int size = bytes_remaining;
10268 XFree (tmp_data);
10269 tmp_data = NULL;
10271 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10272 prop_atom, 0, bytes_remaining,
10273 False, XA_STRING,
10274 &actual_type, &actual_format,
10275 &actual_size, &bytes_remaining,
10276 (unsigned char **) &tmp_data);
10277 if (rc == Success)
10278 prop_value = make_string (tmp_data, size);
10280 XFree (tmp_data);
10283 UNBLOCK_INPUT;
10284 return prop_value;
10289 /***********************************************************************
10290 Busy cursor
10291 ***********************************************************************/
10293 /* If non-null, an asynchronous timer that, when it expires, displays
10294 an hourglass cursor on all frames. */
10296 static struct atimer *hourglass_atimer;
10298 /* Non-zero means an hourglass cursor is currently shown. */
10300 static int hourglass_shown_p;
10302 /* Number of seconds to wait before displaying an hourglass cursor. */
10304 static Lisp_Object Vhourglass_delay;
10306 /* Default number of seconds to wait before displaying an hourglass
10307 cursor. */
10309 #define DEFAULT_HOURGLASS_DELAY 1
10311 /* Function prototypes. */
10313 static void show_hourglass P_ ((struct atimer *));
10314 static void hide_hourglass P_ ((void));
10317 /* Cancel a currently active hourglass timer, and start a new one. */
10319 void
10320 start_hourglass ()
10322 EMACS_TIME delay;
10323 int secs, usecs = 0;
10325 cancel_hourglass ();
10327 if (INTEGERP (Vhourglass_delay)
10328 && XINT (Vhourglass_delay) > 0)
10329 secs = XFASTINT (Vhourglass_delay);
10330 else if (FLOATP (Vhourglass_delay)
10331 && XFLOAT_DATA (Vhourglass_delay) > 0)
10333 Lisp_Object tem;
10334 tem = Ftruncate (Vhourglass_delay, Qnil);
10335 secs = XFASTINT (tem);
10336 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10338 else
10339 secs = DEFAULT_HOURGLASS_DELAY;
10341 EMACS_SET_SECS_USECS (delay, secs, usecs);
10342 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10343 show_hourglass, NULL);
10347 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10348 shown. */
10350 void
10351 cancel_hourglass ()
10353 if (hourglass_atimer)
10355 cancel_atimer (hourglass_atimer);
10356 hourglass_atimer = NULL;
10359 if (hourglass_shown_p)
10360 hide_hourglass ();
10364 /* Timer function of hourglass_atimer. TIMER is equal to
10365 hourglass_atimer.
10367 Display an hourglass pointer on all frames by mapping the frames'
10368 hourglass_window. Set the hourglass_p flag in the frames'
10369 output_data.x structure to indicate that an hourglass cursor is
10370 shown on the frames. */
10372 static void
10373 show_hourglass (timer)
10374 struct atimer *timer;
10376 /* The timer implementation will cancel this timer automatically
10377 after this function has run. Set hourglass_atimer to null
10378 so that we know the timer doesn't have to be canceled. */
10379 hourglass_atimer = NULL;
10381 if (!hourglass_shown_p)
10383 Lisp_Object rest, frame;
10385 BLOCK_INPUT;
10387 FOR_EACH_FRAME (rest, frame)
10389 struct frame *f = XFRAME (frame);
10391 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10393 Display *dpy = FRAME_X_DISPLAY (f);
10395 #ifdef USE_X_TOOLKIT
10396 if (f->output_data.x->widget)
10397 #else
10398 if (FRAME_OUTER_WINDOW (f))
10399 #endif
10401 f->output_data.x->hourglass_p = 1;
10403 if (!f->output_data.x->hourglass_window)
10405 unsigned long mask = CWCursor;
10406 XSetWindowAttributes attrs;
10408 attrs.cursor = f->output_data.x->hourglass_cursor;
10410 f->output_data.x->hourglass_window
10411 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10412 0, 0, 32000, 32000, 0, 0,
10413 InputOnly,
10414 CopyFromParent,
10415 mask, &attrs);
10418 XMapRaised (dpy, f->output_data.x->hourglass_window);
10419 XFlush (dpy);
10424 hourglass_shown_p = 1;
10425 UNBLOCK_INPUT;
10430 /* Hide the hourglass pointer on all frames, if it is currently
10431 shown. */
10433 static void
10434 hide_hourglass ()
10436 if (hourglass_shown_p)
10438 Lisp_Object rest, frame;
10440 BLOCK_INPUT;
10441 FOR_EACH_FRAME (rest, frame)
10443 struct frame *f = XFRAME (frame);
10445 if (FRAME_X_P (f)
10446 /* Watch out for newly created frames. */
10447 && f->output_data.x->hourglass_window)
10449 XUnmapWindow (FRAME_X_DISPLAY (f),
10450 f->output_data.x->hourglass_window);
10451 /* Sync here because XTread_socket looks at the
10452 hourglass_p flag that is reset to zero below. */
10453 XSync (FRAME_X_DISPLAY (f), False);
10454 f->output_data.x->hourglass_p = 0;
10458 hourglass_shown_p = 0;
10459 UNBLOCK_INPUT;
10465 /***********************************************************************
10466 Tool tips
10467 ***********************************************************************/
10469 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10470 Lisp_Object, Lisp_Object));
10471 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10472 Lisp_Object, int, int, int *, int *));
10474 /* The frame of a currently visible tooltip. */
10476 Lisp_Object tip_frame;
10478 /* If non-nil, a timer started that hides the last tooltip when it
10479 fires. */
10481 Lisp_Object tip_timer;
10482 Window tip_window;
10484 /* If non-nil, a vector of 3 elements containing the last args
10485 with which x-show-tip was called. See there. */
10487 Lisp_Object last_show_tip_args;
10489 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10491 Lisp_Object Vx_max_tooltip_size;
10494 static Lisp_Object
10495 unwind_create_tip_frame (frame)
10496 Lisp_Object frame;
10498 Lisp_Object deleted;
10500 deleted = unwind_create_frame (frame);
10501 if (EQ (deleted, Qt))
10503 tip_window = None;
10504 tip_frame = Qnil;
10507 return deleted;
10511 /* Create a frame for a tooltip on the display described by DPYINFO.
10512 PARMS is a list of frame parameters. TEXT is the string to
10513 display in the tip frame. Value is the frame.
10515 Note that functions called here, esp. x_default_parameter can
10516 signal errors, for instance when a specified color name is
10517 undefined. We have to make sure that we're in a consistent state
10518 when this happens. */
10520 static Lisp_Object
10521 x_create_tip_frame (dpyinfo, parms, text)
10522 struct x_display_info *dpyinfo;
10523 Lisp_Object parms, text;
10525 struct frame *f;
10526 Lisp_Object frame, tem;
10527 Lisp_Object name;
10528 long window_prompting = 0;
10529 int width, height;
10530 int count = BINDING_STACK_SIZE ();
10531 struct gcpro gcpro1, gcpro2, gcpro3;
10532 struct kboard *kb;
10533 int face_change_count_before = face_change_count;
10534 Lisp_Object buffer;
10535 struct buffer *old_buffer;
10537 check_x ();
10539 /* Use this general default value to start with until we know if
10540 this frame has a specified name. */
10541 Vx_resource_name = Vinvocation_name;
10543 #ifdef MULTI_KBOARD
10544 kb = dpyinfo->kboard;
10545 #else
10546 kb = &the_only_kboard;
10547 #endif
10549 /* Get the name of the frame to use for resource lookup. */
10550 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10551 if (!STRINGP (name)
10552 && !EQ (name, Qunbound)
10553 && !NILP (name))
10554 error ("Invalid frame name--not a string or nil");
10555 Vx_resource_name = name;
10557 frame = Qnil;
10558 GCPRO3 (parms, name, frame);
10559 f = make_frame (1);
10560 XSETFRAME (frame, f);
10562 buffer = Fget_buffer_create (build_string (" *tip*"));
10563 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10564 old_buffer = current_buffer;
10565 set_buffer_internal_1 (XBUFFER (buffer));
10566 current_buffer->truncate_lines = Qnil;
10567 Ferase_buffer ();
10568 Finsert (1, &text);
10569 set_buffer_internal_1 (old_buffer);
10571 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10572 record_unwind_protect (unwind_create_tip_frame, frame);
10574 /* By setting the output method, we're essentially saying that
10575 the frame is live, as per FRAME_LIVE_P. If we get a signal
10576 from this point on, x_destroy_window might screw up reference
10577 counts etc. */
10578 f->output_method = output_x_window;
10579 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10580 bzero (f->output_data.x, sizeof (struct x_output));
10581 f->output_data.x->icon_bitmap = -1;
10582 f->output_data.x->fontset = -1;
10583 f->output_data.x->scroll_bar_foreground_pixel = -1;
10584 f->output_data.x->scroll_bar_background_pixel = -1;
10585 f->icon_name = Qnil;
10586 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10587 #if GLYPH_DEBUG
10588 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
10589 dpyinfo_refcount = dpyinfo->reference_count;
10590 #endif /* GLYPH_DEBUG */
10591 #ifdef MULTI_KBOARD
10592 FRAME_KBOARD (f) = kb;
10593 #endif
10594 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10595 f->output_data.x->explicit_parent = 0;
10597 /* These colors will be set anyway later, but it's important
10598 to get the color reference counts right, so initialize them! */
10600 Lisp_Object black;
10601 struct gcpro gcpro1;
10603 black = build_string ("black");
10604 GCPRO1 (black);
10605 f->output_data.x->foreground_pixel
10606 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10607 f->output_data.x->background_pixel
10608 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10609 f->output_data.x->cursor_pixel
10610 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10611 f->output_data.x->cursor_foreground_pixel
10612 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10613 f->output_data.x->border_pixel
10614 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10615 f->output_data.x->mouse_pixel
10616 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10617 UNGCPRO;
10620 /* Set the name; the functions to which we pass f expect the name to
10621 be set. */
10622 if (EQ (name, Qunbound) || NILP (name))
10624 f->name = build_string (dpyinfo->x_id_name);
10625 f->explicit_name = 0;
10627 else
10629 f->name = name;
10630 f->explicit_name = 1;
10631 /* use the frame's title when getting resources for this frame. */
10632 specbind (Qx_resource_name, name);
10635 /* Extract the window parameters from the supplied values that are
10636 needed to determine window geometry. */
10638 Lisp_Object font;
10640 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10642 BLOCK_INPUT;
10643 /* First, try whatever font the caller has specified. */
10644 if (STRINGP (font))
10646 tem = Fquery_fontset (font, Qnil);
10647 if (STRINGP (tem))
10648 font = x_new_fontset (f, XSTRING (tem)->data);
10649 else
10650 font = x_new_font (f, XSTRING (font)->data);
10653 /* Try out a font which we hope has bold and italic variations. */
10654 if (!STRINGP (font))
10655 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10656 if (!STRINGP (font))
10657 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10658 if (! STRINGP (font))
10659 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10660 if (! STRINGP (font))
10661 /* This was formerly the first thing tried, but it finds too many fonts
10662 and takes too long. */
10663 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10664 /* If those didn't work, look for something which will at least work. */
10665 if (! STRINGP (font))
10666 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10667 UNBLOCK_INPUT;
10668 if (! STRINGP (font))
10669 font = build_string ("fixed");
10671 x_default_parameter (f, parms, Qfont, font,
10672 "font", "Font", RES_TYPE_STRING);
10675 x_default_parameter (f, parms, Qborder_width, make_number (2),
10676 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10678 /* This defaults to 2 in order to match xterm. We recognize either
10679 internalBorderWidth or internalBorder (which is what xterm calls
10680 it). */
10681 if (NILP (Fassq (Qinternal_border_width, parms)))
10683 Lisp_Object value;
10685 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10686 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10687 if (! EQ (value, Qunbound))
10688 parms = Fcons (Fcons (Qinternal_border_width, value),
10689 parms);
10692 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10693 "internalBorderWidth", "internalBorderWidth",
10694 RES_TYPE_NUMBER);
10696 /* Also do the stuff which must be set before the window exists. */
10697 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10698 "foreground", "Foreground", RES_TYPE_STRING);
10699 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10700 "background", "Background", RES_TYPE_STRING);
10701 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10702 "pointerColor", "Foreground", RES_TYPE_STRING);
10703 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10704 "cursorColor", "Foreground", RES_TYPE_STRING);
10705 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10706 "borderColor", "BorderColor", RES_TYPE_STRING);
10708 /* Init faces before x_default_parameter is called for scroll-bar
10709 parameters because that function calls x_set_scroll_bar_width,
10710 which calls change_frame_size, which calls Fset_window_buffer,
10711 which runs hooks, which call Fvertical_motion. At the end, we
10712 end up in init_iterator with a null face cache, which should not
10713 happen. */
10714 init_frame_faces (f);
10716 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10717 window_prompting = x_figure_window_size (f, parms);
10719 if (window_prompting & XNegative)
10721 if (window_prompting & YNegative)
10722 f->output_data.x->win_gravity = SouthEastGravity;
10723 else
10724 f->output_data.x->win_gravity = NorthEastGravity;
10726 else
10728 if (window_prompting & YNegative)
10729 f->output_data.x->win_gravity = SouthWestGravity;
10730 else
10731 f->output_data.x->win_gravity = NorthWestGravity;
10734 f->output_data.x->size_hint_flags = window_prompting;
10736 XSetWindowAttributes attrs;
10737 unsigned long mask;
10739 BLOCK_INPUT;
10740 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
10741 if (DoesSaveUnders (dpyinfo->screen))
10742 mask |= CWSaveUnder;
10744 /* Window managers look at the override-redirect flag to determine
10745 whether or net to give windows a decoration (Xlib spec, chapter
10746 3.2.8). */
10747 attrs.override_redirect = True;
10748 attrs.save_under = True;
10749 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10750 /* Arrange for getting MapNotify and UnmapNotify events. */
10751 attrs.event_mask = StructureNotifyMask;
10752 tip_window
10753 = FRAME_X_WINDOW (f)
10754 = XCreateWindow (FRAME_X_DISPLAY (f),
10755 FRAME_X_DISPLAY_INFO (f)->root_window,
10756 /* x, y, width, height */
10757 0, 0, 1, 1,
10758 /* Border. */
10760 CopyFromParent, InputOutput, CopyFromParent,
10761 mask, &attrs);
10762 UNBLOCK_INPUT;
10765 x_make_gc (f);
10767 x_default_parameter (f, parms, Qauto_raise, Qnil,
10768 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10769 x_default_parameter (f, parms, Qauto_lower, Qnil,
10770 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10771 x_default_parameter (f, parms, Qcursor_type, Qbox,
10772 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10774 /* Dimensions, especially f->height, must be done via change_frame_size.
10775 Change will not be effected unless different from the current
10776 f->height. */
10777 width = f->width;
10778 height = f->height;
10779 f->height = 0;
10780 SET_FRAME_WIDTH (f, 0);
10781 change_frame_size (f, height, width, 1, 0, 0);
10783 /* Set up faces after all frame parameters are known. This call
10784 also merges in face attributes specified for new frames.
10786 Frame parameters may be changed if .Xdefaults contains
10787 specifications for the default font. For example, if there is an
10788 `Emacs.default.attributeBackground: pink', the `background-color'
10789 attribute of the frame get's set, which let's the internal border
10790 of the tooltip frame appear in pink. Prevent this. */
10792 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
10794 /* Set tip_frame here, so that */
10795 tip_frame = frame;
10796 call1 (Qface_set_after_frame_default, frame);
10798 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
10799 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
10800 Qnil));
10803 f->no_split = 1;
10805 UNGCPRO;
10807 /* It is now ok to make the frame official even if we get an error
10808 below. And the frame needs to be on Vframe_list or making it
10809 visible won't work. */
10810 Vframe_list = Fcons (frame, Vframe_list);
10812 /* Now that the frame is official, it counts as a reference to
10813 its display. */
10814 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10816 /* Setting attributes of faces of the tooltip frame from resources
10817 and similar will increment face_change_count, which leads to the
10818 clearing of all current matrices. Since this isn't necessary
10819 here, avoid it by resetting face_change_count to the value it
10820 had before we created the tip frame. */
10821 face_change_count = face_change_count_before;
10823 /* Discard the unwind_protect. */
10824 return unbind_to (count, frame);
10828 /* Compute where to display tip frame F. PARMS is the list of frame
10829 parameters for F. DX and DY are specified offsets from the current
10830 location of the mouse. WIDTH and HEIGHT are the width and height
10831 of the tooltip. Return coordinates relative to the root window of
10832 the display in *ROOT_X, and *ROOT_Y. */
10834 static void
10835 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
10836 struct frame *f;
10837 Lisp_Object parms, dx, dy;
10838 int width, height;
10839 int *root_x, *root_y;
10841 Lisp_Object left, top;
10842 int win_x, win_y;
10843 Window root, child;
10844 unsigned pmask;
10846 /* User-specified position? */
10847 left = Fcdr (Fassq (Qleft, parms));
10848 top = Fcdr (Fassq (Qtop, parms));
10850 /* Move the tooltip window where the mouse pointer is. Resize and
10851 show it. */
10852 if (!INTEGERP (left) && !INTEGERP (top))
10854 BLOCK_INPUT;
10855 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10856 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
10857 UNBLOCK_INPUT;
10860 if (INTEGERP (top))
10861 *root_y = XINT (top);
10862 else if (*root_y + XINT (dy) - height < 0)
10863 *root_y -= XINT (dy);
10864 else
10866 *root_y -= height;
10867 *root_y += XINT (dy);
10870 if (INTEGERP (left))
10871 *root_x = XINT (left);
10872 else if (*root_x + XINT (dx) + width > FRAME_X_DISPLAY_INFO (f)->width)
10873 *root_x -= width + XINT (dx);
10874 else
10875 *root_x += XINT (dx);
10879 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10880 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10881 A tooltip window is a small X window displaying a string.\n\
10883 FRAME nil or omitted means use the selected frame.\n\
10885 PARMS is an optional list of frame parameters which can be\n\
10886 used to change the tooltip's appearance.\n\
10888 Automatically hide the tooltip after TIMEOUT seconds.\n\
10889 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10891 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10892 the tooltip is displayed at that x-position. Otherwise it is\n\
10893 displayed at the mouse position, with offset DX added (default is 5 if\n\
10894 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10895 parameter is specified, it determines the y-position of the tooltip\n\
10896 window, otherwise it is displayed at the mouse position, with offset\n\
10897 DY added (default is -10).\n\
10899 A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
10900 Text larger than the specified size is clipped.")
10901 (string, frame, parms, timeout, dx, dy)
10902 Lisp_Object string, frame, parms, timeout, dx, dy;
10904 struct frame *f;
10905 struct window *w;
10906 Lisp_Object buffer, top, left, max_width, max_height;
10907 int root_x, root_y;
10908 struct buffer *old_buffer;
10909 struct text_pos pos;
10910 int i, width, height;
10911 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10912 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10913 int count = BINDING_STACK_SIZE ();
10915 specbind (Qinhibit_redisplay, Qt);
10917 GCPRO4 (string, parms, frame, timeout);
10919 CHECK_STRING (string, 0);
10920 f = check_x_frame (frame);
10921 if (NILP (timeout))
10922 timeout = make_number (5);
10923 else
10924 CHECK_NATNUM (timeout, 2);
10926 if (NILP (dx))
10927 dx = make_number (5);
10928 else
10929 CHECK_NUMBER (dx, 5);
10931 if (NILP (dy))
10932 dy = make_number (-10);
10933 else
10934 CHECK_NUMBER (dy, 6);
10936 if (NILP (last_show_tip_args))
10937 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
10939 if (!NILP (tip_frame))
10941 Lisp_Object last_string = AREF (last_show_tip_args, 0);
10942 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
10943 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
10945 if (EQ (frame, last_frame)
10946 && !NILP (Fequal (last_string, string))
10947 && !NILP (Fequal (last_parms, parms)))
10949 struct frame *f = XFRAME (tip_frame);
10951 /* Only DX and DY have changed. */
10952 if (!NILP (tip_timer))
10954 Lisp_Object timer = tip_timer;
10955 tip_timer = Qnil;
10956 call1 (Qcancel_timer, timer);
10959 BLOCK_INPUT;
10960 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
10961 PIXEL_HEIGHT (f), &root_x, &root_y);
10962 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10963 root_x, root_y);
10964 UNBLOCK_INPUT;
10965 goto start_timer;
10969 /* Hide a previous tip, if any. */
10970 Fx_hide_tip ();
10972 ASET (last_show_tip_args, 0, string);
10973 ASET (last_show_tip_args, 1, frame);
10974 ASET (last_show_tip_args, 2, parms);
10976 /* Add default values to frame parameters. */
10977 if (NILP (Fassq (Qname, parms)))
10978 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10979 if (NILP (Fassq (Qinternal_border_width, parms)))
10980 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10981 if (NILP (Fassq (Qborder_width, parms)))
10982 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10983 if (NILP (Fassq (Qborder_color, parms)))
10984 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10985 if (NILP (Fassq (Qbackground_color, parms)))
10986 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10987 parms);
10989 /* Create a frame for the tooltip, and record it in the global
10990 variable tip_frame. */
10991 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
10992 f = XFRAME (frame);
10994 /* Set up the frame's root window. */
10995 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10996 w->left = w->top = make_number (0);
10998 if (CONSP (Vx_max_tooltip_size)
10999 && INTEGERP (XCAR (Vx_max_tooltip_size))
11000 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11001 && INTEGERP (XCDR (Vx_max_tooltip_size))
11002 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11004 w->width = XCAR (Vx_max_tooltip_size);
11005 w->height = XCDR (Vx_max_tooltip_size);
11007 else
11009 w->width = make_number (80);
11010 w->height = make_number (40);
11013 f->window_width = XINT (w->width);
11014 adjust_glyphs (f);
11015 w->pseudo_window_p = 1;
11017 /* Display the tooltip text in a temporary buffer. */
11018 old_buffer = current_buffer;
11019 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11020 current_buffer->truncate_lines = Qnil;
11021 clear_glyph_matrix (w->desired_matrix);
11022 clear_glyph_matrix (w->current_matrix);
11023 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11024 try_window (FRAME_ROOT_WINDOW (f), pos);
11026 /* Compute width and height of the tooltip. */
11027 width = height = 0;
11028 for (i = 0; i < w->desired_matrix->nrows; ++i)
11030 struct glyph_row *row = &w->desired_matrix->rows[i];
11031 struct glyph *last;
11032 int row_width;
11034 /* Stop at the first empty row at the end. */
11035 if (!row->enabled_p || !row->displays_text_p)
11036 break;
11038 /* Let the row go over the full width of the frame. */
11039 row->full_width_p = 1;
11041 /* There's a glyph at the end of rows that is used to place
11042 the cursor there. Don't include the width of this glyph. */
11043 if (row->used[TEXT_AREA])
11045 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
11046 row_width = row->pixel_width - last->pixel_width;
11048 else
11049 row_width = row->pixel_width;
11051 height += row->height;
11052 width = max (width, row_width);
11055 /* Add the frame's internal border to the width and height the X
11056 window should have. */
11057 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11058 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11060 /* Move the tooltip window where the mouse pointer is. Resize and
11061 show it. */
11062 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
11064 BLOCK_INPUT;
11065 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11066 root_x, root_y, width, height);
11067 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11068 UNBLOCK_INPUT;
11070 /* Draw into the window. */
11071 w->must_be_updated_p = 1;
11072 update_single_window (w, 1);
11074 /* Restore original current buffer. */
11075 set_buffer_internal_1 (old_buffer);
11076 windows_or_buffers_changed = old_windows_or_buffers_changed;
11078 start_timer:
11079 /* Let the tip disappear after timeout seconds. */
11080 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11081 intern ("x-hide-tip"));
11083 UNGCPRO;
11084 return unbind_to (count, Qnil);
11088 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11089 "Hide the current tooltip window, if there is any.\n\
11090 Value is t is tooltip was open, nil otherwise.")
11093 int count;
11094 Lisp_Object deleted, frame, timer;
11095 struct gcpro gcpro1, gcpro2;
11097 /* Return quickly if nothing to do. */
11098 if (NILP (tip_timer) && NILP (tip_frame))
11099 return Qnil;
11101 frame = tip_frame;
11102 timer = tip_timer;
11103 GCPRO2 (frame, timer);
11104 tip_frame = tip_timer = deleted = Qnil;
11106 count = BINDING_STACK_SIZE ();
11107 specbind (Qinhibit_redisplay, Qt);
11108 specbind (Qinhibit_quit, Qt);
11110 if (!NILP (timer))
11111 call1 (Qcancel_timer, timer);
11113 if (FRAMEP (frame))
11115 Fdelete_frame (frame, Qnil);
11116 deleted = Qt;
11118 #ifdef USE_LUCID
11119 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11120 redisplay procedure is not called when a tip frame over menu
11121 items is unmapped. Redisplay the menu manually... */
11123 struct frame *f = SELECTED_FRAME ();
11124 Widget w = f->output_data.x->menubar_widget;
11125 extern void xlwmenu_redisplay P_ ((Widget));
11127 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11128 && w != NULL)
11130 BLOCK_INPUT;
11131 xlwmenu_redisplay (w);
11132 UNBLOCK_INPUT;
11135 #endif /* USE_LUCID */
11138 UNGCPRO;
11139 return unbind_to (count, deleted);
11144 /***********************************************************************
11145 File selection dialog
11146 ***********************************************************************/
11148 #ifdef USE_MOTIF
11150 /* Callback for "OK" and "Cancel" on file selection dialog. */
11152 static void
11153 file_dialog_cb (widget, client_data, call_data)
11154 Widget widget;
11155 XtPointer call_data, client_data;
11157 int *result = (int *) client_data;
11158 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11159 *result = cb->reason;
11163 /* Callback for unmapping a file selection dialog. This is used to
11164 capture the case where a dialog is closed via a window manager's
11165 closer button, for example. Using a XmNdestroyCallback didn't work
11166 in this case. */
11168 static void
11169 file_dialog_unmap_cb (widget, client_data, call_data)
11170 Widget widget;
11171 XtPointer call_data, client_data;
11173 int *result = (int *) client_data;
11174 *result = XmCR_CANCEL;
11178 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11179 "Read file name, prompting with PROMPT in directory DIR.\n\
11180 Use a file selection dialog.\n\
11181 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
11182 specified. Don't let the user enter a file name in the file\n\
11183 selection dialog's entry field, if MUSTMATCH is non-nil.")
11184 (prompt, dir, default_filename, mustmatch)
11185 Lisp_Object prompt, dir, default_filename, mustmatch;
11187 int result;
11188 struct frame *f = SELECTED_FRAME ();
11189 Lisp_Object file = Qnil;
11190 Widget dialog, text, list, help;
11191 Arg al[10];
11192 int ac = 0;
11193 extern XtAppContext Xt_app_con;
11194 char *title;
11195 XmString dir_xmstring, pattern_xmstring;
11196 int popup_activated_flag;
11197 int count = specpdl_ptr - specpdl;
11198 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11200 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11201 CHECK_STRING (prompt, 0);
11202 CHECK_STRING (dir, 1);
11204 /* Prevent redisplay. */
11205 specbind (Qinhibit_redisplay, Qt);
11207 BLOCK_INPUT;
11209 /* Create the dialog with PROMPT as title, using DIR as initial
11210 directory and using "*" as pattern. */
11211 dir = Fexpand_file_name (dir, Qnil);
11212 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
11213 pattern_xmstring = XmStringCreateLocalized ("*");
11215 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
11216 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11217 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11218 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11219 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11220 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11221 "fsb", al, ac);
11222 XmStringFree (dir_xmstring);
11223 XmStringFree (pattern_xmstring);
11225 /* Add callbacks for OK and Cancel. */
11226 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11227 (XtPointer) &result);
11228 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11229 (XtPointer) &result);
11230 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11231 (XtPointer) &result);
11233 /* Disable the help button since we can't display help. */
11234 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11235 XtSetSensitive (help, False);
11237 /* Mark OK button as default. */
11238 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11239 XmNshowAsDefault, True, NULL);
11241 /* If MUSTMATCH is non-nil, disable the file entry field of the
11242 dialog, so that the user must select a file from the files list
11243 box. We can't remove it because we wouldn't have a way to get at
11244 the result file name, then. */
11245 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11246 if (!NILP (mustmatch))
11248 Widget label;
11249 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11250 XtSetSensitive (text, False);
11251 XtSetSensitive (label, False);
11254 /* Manage the dialog, so that list boxes get filled. */
11255 XtManageChild (dialog);
11257 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11258 must include the path for this to work. */
11259 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11260 if (STRINGP (default_filename))
11262 XmString default_xmstring;
11263 int item_pos;
11265 default_xmstring
11266 = XmStringCreateLocalized (XSTRING (default_filename)->data);
11268 if (!XmListItemExists (list, default_xmstring))
11270 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11271 XmListAddItem (list, default_xmstring, 0);
11272 item_pos = 0;
11274 else
11275 item_pos = XmListItemPos (list, default_xmstring);
11276 XmStringFree (default_xmstring);
11278 /* Select the item and scroll it into view. */
11279 XmListSelectPos (list, item_pos, True);
11280 XmListSetPos (list, item_pos);
11283 /* Process events until the user presses Cancel or OK. Block
11284 and unblock input here so that we get a chance of processing
11285 expose events. */
11286 UNBLOCK_INPUT;
11287 result = 0;
11288 while (result == 0)
11290 BLOCK_INPUT;
11291 XtAppProcessEvent (Xt_app_con, XtIMAll);
11292 UNBLOCK_INPUT;
11294 BLOCK_INPUT;
11296 /* Get the result. */
11297 if (result == XmCR_OK)
11299 XmString text;
11300 String data;
11302 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11303 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11304 XmStringFree (text);
11305 file = build_string (data);
11306 XtFree (data);
11308 else
11309 file = Qnil;
11311 /* Clean up. */
11312 XtUnmanageChild (dialog);
11313 XtDestroyWidget (dialog);
11314 UNBLOCK_INPUT;
11315 UNGCPRO;
11317 /* Make "Cancel" equivalent to C-g. */
11318 if (NILP (file))
11319 Fsignal (Qquit, Qnil);
11321 return unbind_to (count, file);
11324 #endif /* USE_MOTIF */
11328 /***********************************************************************
11329 Keyboard
11330 ***********************************************************************/
11332 #ifdef HAVE_XKBGETKEYBOARD
11333 #include <X11/XKBlib.h>
11334 #include <X11/keysym.h>
11335 #endif
11337 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11338 Sx_backspace_delete_keys_p, 0, 1, 0,
11339 "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
11340 FRAME nil means use the selected frame.\n\
11341 Value is t if we know that both keys are present, and are mapped to the\n\
11342 usual X keysyms.")
11343 (frame)
11344 Lisp_Object frame;
11346 #ifdef HAVE_XKBGETKEYBOARD
11347 XkbDescPtr kb;
11348 struct frame *f = check_x_frame (frame);
11349 Display *dpy = FRAME_X_DISPLAY (f);
11350 Lisp_Object have_keys;
11351 int major, minor, op, event, error;
11353 BLOCK_INPUT;
11355 /* Check library version in case we're dynamically linked. */
11356 major = XkbMajorVersion;
11357 minor = XkbMinorVersion;
11358 if (!XkbLibraryVersion (&major, &minor))
11360 UNBLOCK_INPUT;
11361 return Qnil;
11364 /* Check that the server supports XKB. */
11365 major = XkbMajorVersion;
11366 minor = XkbMinorVersion;
11367 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11369 UNBLOCK_INPUT;
11370 return Qnil;
11373 have_keys = Qnil;
11374 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11375 if (kb)
11377 int delete_keycode = 0, backspace_keycode = 0, i;
11379 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11381 for (i = kb->min_key_code;
11382 (i < kb->max_key_code
11383 && (delete_keycode == 0 || backspace_keycode == 0));
11384 ++i)
11386 /* The XKB symbolic key names can be seen most easily in
11387 the PS file generated by `xkbprint -label name
11388 $DISPLAY'. */
11389 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11390 delete_keycode = i;
11391 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11392 backspace_keycode = i;
11395 XkbFreeNames (kb, 0, True);
11398 XkbFreeClientMap (kb, 0, True);
11400 if (delete_keycode
11401 && backspace_keycode
11402 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11403 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11404 have_keys = Qt;
11406 UNBLOCK_INPUT;
11407 return have_keys;
11408 #else /* not HAVE_XKBGETKEYBOARD */
11409 return Qnil;
11410 #endif /* not HAVE_XKBGETKEYBOARD */
11415 /***********************************************************************
11416 Initialization
11417 ***********************************************************************/
11419 void
11420 syms_of_xfns ()
11422 /* This is zero if not using X windows. */
11423 x_in_use = 0;
11425 /* The section below is built by the lisp expression at the top of the file,
11426 just above where these variables are declared. */
11427 /*&&& init symbols here &&&*/
11428 Qauto_raise = intern ("auto-raise");
11429 staticpro (&Qauto_raise);
11430 Qauto_lower = intern ("auto-lower");
11431 staticpro (&Qauto_lower);
11432 Qbar = intern ("bar");
11433 staticpro (&Qbar);
11434 Qborder_color = intern ("border-color");
11435 staticpro (&Qborder_color);
11436 Qborder_width = intern ("border-width");
11437 staticpro (&Qborder_width);
11438 Qbox = intern ("box");
11439 staticpro (&Qbox);
11440 Qcursor_color = intern ("cursor-color");
11441 staticpro (&Qcursor_color);
11442 Qcursor_type = intern ("cursor-type");
11443 staticpro (&Qcursor_type);
11444 Qgeometry = intern ("geometry");
11445 staticpro (&Qgeometry);
11446 Qicon_left = intern ("icon-left");
11447 staticpro (&Qicon_left);
11448 Qicon_top = intern ("icon-top");
11449 staticpro (&Qicon_top);
11450 Qicon_type = intern ("icon-type");
11451 staticpro (&Qicon_type);
11452 Qicon_name = intern ("icon-name");
11453 staticpro (&Qicon_name);
11454 Qinternal_border_width = intern ("internal-border-width");
11455 staticpro (&Qinternal_border_width);
11456 Qleft = intern ("left");
11457 staticpro (&Qleft);
11458 Qright = intern ("right");
11459 staticpro (&Qright);
11460 Qmouse_color = intern ("mouse-color");
11461 staticpro (&Qmouse_color);
11462 Qnone = intern ("none");
11463 staticpro (&Qnone);
11464 Qparent_id = intern ("parent-id");
11465 staticpro (&Qparent_id);
11466 Qscroll_bar_width = intern ("scroll-bar-width");
11467 staticpro (&Qscroll_bar_width);
11468 Qsuppress_icon = intern ("suppress-icon");
11469 staticpro (&Qsuppress_icon);
11470 Qundefined_color = intern ("undefined-color");
11471 staticpro (&Qundefined_color);
11472 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11473 staticpro (&Qvertical_scroll_bars);
11474 Qvisibility = intern ("visibility");
11475 staticpro (&Qvisibility);
11476 Qwindow_id = intern ("window-id");
11477 staticpro (&Qwindow_id);
11478 Qouter_window_id = intern ("outer-window-id");
11479 staticpro (&Qouter_window_id);
11480 Qx_frame_parameter = intern ("x-frame-parameter");
11481 staticpro (&Qx_frame_parameter);
11482 Qx_resource_name = intern ("x-resource-name");
11483 staticpro (&Qx_resource_name);
11484 Quser_position = intern ("user-position");
11485 staticpro (&Quser_position);
11486 Quser_size = intern ("user-size");
11487 staticpro (&Quser_size);
11488 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11489 staticpro (&Qscroll_bar_foreground);
11490 Qscroll_bar_background = intern ("scroll-bar-background");
11491 staticpro (&Qscroll_bar_background);
11492 Qscreen_gamma = intern ("screen-gamma");
11493 staticpro (&Qscreen_gamma);
11494 Qline_spacing = intern ("line-spacing");
11495 staticpro (&Qline_spacing);
11496 Qcenter = intern ("center");
11497 staticpro (&Qcenter);
11498 Qcompound_text = intern ("compound-text");
11499 staticpro (&Qcompound_text);
11500 Qcancel_timer = intern ("cancel-timer");
11501 staticpro (&Qcancel_timer);
11502 Qwait_for_wm = intern ("wait-for-wm");
11503 staticpro (&Qwait_for_wm);
11504 /* This is the end of symbol initialization. */
11506 /* Text property `display' should be nonsticky by default. */
11507 Vtext_property_default_nonsticky
11508 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11511 Qlaplace = intern ("laplace");
11512 staticpro (&Qlaplace);
11513 Qemboss = intern ("emboss");
11514 staticpro (&Qemboss);
11515 Qedge_detection = intern ("edge-detection");
11516 staticpro (&Qedge_detection);
11517 Qheuristic = intern ("heuristic");
11518 staticpro (&Qheuristic);
11519 QCmatrix = intern (":matrix");
11520 staticpro (&QCmatrix);
11521 QCcolor_adjustment = intern (":color-adjustment");
11522 staticpro (&QCcolor_adjustment);
11523 QCmask = intern (":mask");
11524 staticpro (&QCmask);
11526 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11527 staticpro (&Qface_set_after_frame_default);
11529 Fput (Qundefined_color, Qerror_conditions,
11530 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11531 Fput (Qundefined_color, Qerror_message,
11532 build_string ("Undefined color"));
11534 init_x_parm_symbols ();
11536 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11537 "Non-nil means always draw a cross over disabled images.\n\
11538 Disabled images are those having an `:conversion disabled' property.\n\
11539 A cross is always drawn on black & white displays.");
11540 cross_disabled_images = 0;
11542 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11543 "List of directories to search for bitmap files for X.");
11544 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11546 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11547 "The shape of the pointer when over text.\n\
11548 Changing the value does not affect existing frames\n\
11549 unless you set the mouse color.");
11550 Vx_pointer_shape = Qnil;
11552 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11553 "The name Emacs uses to look up X resources.\n\
11554 `x-get-resource' uses this as the first component of the instance name\n\
11555 when requesting resource values.\n\
11556 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11557 was invoked, or to the value specified with the `-name' or `-rn'\n\
11558 switches, if present.\n\
11560 It may be useful to bind this variable locally around a call\n\
11561 to `x-get-resource'. See also the variable `x-resource-class'.");
11562 Vx_resource_name = Qnil;
11564 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11565 "The class Emacs uses to look up X resources.\n\
11566 `x-get-resource' uses this as the first component of the instance class\n\
11567 when requesting resource values.\n\
11568 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11570 Setting this variable permanently is not a reasonable thing to do,\n\
11571 but binding this variable locally around a call to `x-get-resource'\n\
11572 is a reasonable practice. See also the variable `x-resource-name'.");
11573 Vx_resource_class = build_string (EMACS_CLASS);
11575 #if 0 /* This doesn't really do anything. */
11576 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11577 "The shape of the pointer when not over text.\n\
11578 This variable takes effect when you create a new frame\n\
11579 or when you set the mouse color.");
11580 #endif
11581 Vx_nontext_pointer_shape = Qnil;
11583 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
11584 "The shape of the pointer when Emacs is busy.\n\
11585 This variable takes effect when you create a new frame\n\
11586 or when you set the mouse color.");
11587 Vx_hourglass_pointer_shape = Qnil;
11589 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
11590 "Non-zero means Emacs displays an hourglass pointer on window systems.");
11591 display_hourglass_p = 1;
11593 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
11594 "*Seconds to wait before displaying an hourglass pointer.\n\
11595 Value must be an integer or float.");
11596 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
11598 #if 0 /* This doesn't really do anything. */
11599 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11600 "The shape of the pointer when over the mode line.\n\
11601 This variable takes effect when you create a new frame\n\
11602 or when you set the mouse color.");
11603 #endif
11604 Vx_mode_pointer_shape = Qnil;
11606 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11607 &Vx_sensitive_text_pointer_shape,
11608 "The shape of the pointer when over mouse-sensitive text.\n\
11609 This variable takes effect when you create a new frame\n\
11610 or when you set the mouse color.");
11611 Vx_sensitive_text_pointer_shape = Qnil;
11613 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11614 &Vx_window_horizontal_drag_shape,
11615 "Pointer shape to use for indicating a window can be dragged horizontally.\n\
11616 This variable takes effect when you create a new frame\n\
11617 or when you set the mouse color.");
11618 Vx_window_horizontal_drag_shape = Qnil;
11620 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11621 "A string indicating the foreground color of the cursor box.");
11622 Vx_cursor_fore_pixel = Qnil;
11624 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
11625 "Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).\n\
11626 Text larger than this is clipped.");
11627 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
11629 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11630 "Non-nil if no X window manager is in use.\n\
11631 Emacs doesn't try to figure this out; this is always nil\n\
11632 unless you set it to something else.");
11633 /* We don't have any way to find this out, so set it to nil
11634 and maybe the user would like to set it to t. */
11635 Vx_no_window_manager = Qnil;
11637 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11638 &Vx_pixel_size_width_font_regexp,
11639 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11641 Since Emacs gets width of a font matching with this regexp from\n\
11642 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11643 such a font. This is especially effective for such large fonts as\n\
11644 Chinese, Japanese, and Korean.");
11645 Vx_pixel_size_width_font_regexp = Qnil;
11647 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11648 "Time after which cached images are removed from the cache.\n\
11649 When an image has not been displayed this many seconds, remove it\n\
11650 from the image cache. Value must be an integer or nil with nil\n\
11651 meaning don't clear the cache.");
11652 Vimage_cache_eviction_delay = make_number (30 * 60);
11654 #ifdef USE_X_TOOLKIT
11655 Fprovide (intern ("x-toolkit"));
11657 #ifdef USE_MOTIF
11658 Fprovide (intern ("motif"));
11660 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
11661 "Version info for LessTif/Motif.");
11662 Vmotif_version_string = build_string (XmVERSION_STRING);
11663 #endif /* USE_MOTIF */
11664 #endif /* USE_X_TOOLKIT */
11666 defsubr (&Sx_get_resource);
11668 /* X window properties. */
11669 defsubr (&Sx_change_window_property);
11670 defsubr (&Sx_delete_window_property);
11671 defsubr (&Sx_window_property);
11673 defsubr (&Sxw_display_color_p);
11674 defsubr (&Sx_display_grayscale_p);
11675 defsubr (&Sxw_color_defined_p);
11676 defsubr (&Sxw_color_values);
11677 defsubr (&Sx_server_max_request_size);
11678 defsubr (&Sx_server_vendor);
11679 defsubr (&Sx_server_version);
11680 defsubr (&Sx_display_pixel_width);
11681 defsubr (&Sx_display_pixel_height);
11682 defsubr (&Sx_display_mm_width);
11683 defsubr (&Sx_display_mm_height);
11684 defsubr (&Sx_display_screens);
11685 defsubr (&Sx_display_planes);
11686 defsubr (&Sx_display_color_cells);
11687 defsubr (&Sx_display_visual_class);
11688 defsubr (&Sx_display_backing_store);
11689 defsubr (&Sx_display_save_under);
11690 defsubr (&Sx_parse_geometry);
11691 defsubr (&Sx_create_frame);
11692 defsubr (&Sx_open_connection);
11693 defsubr (&Sx_close_connection);
11694 defsubr (&Sx_display_list);
11695 defsubr (&Sx_synchronize);
11696 defsubr (&Sx_focus_frame);
11697 defsubr (&Sx_backspace_delete_keys_p);
11699 /* Setting callback functions for fontset handler. */
11700 get_font_info_func = x_get_font_info;
11702 #if 0 /* This function pointer doesn't seem to be used anywhere.
11703 And the pointer assigned has the wrong type, anyway. */
11704 list_fonts_func = x_list_fonts;
11705 #endif
11707 load_font_func = x_load_font;
11708 find_ccl_program_func = x_find_ccl_program;
11709 query_font_func = x_query_font;
11710 set_frame_fontset_func = x_set_font;
11711 check_window_system_func = check_x;
11713 /* Images. */
11714 Qxbm = intern ("xbm");
11715 staticpro (&Qxbm);
11716 QCtype = intern (":type");
11717 staticpro (&QCtype);
11718 QCconversion = intern (":conversion");
11719 staticpro (&QCconversion);
11720 QCheuristic_mask = intern (":heuristic-mask");
11721 staticpro (&QCheuristic_mask);
11722 QCcolor_symbols = intern (":color-symbols");
11723 staticpro (&QCcolor_symbols);
11724 QCascent = intern (":ascent");
11725 staticpro (&QCascent);
11726 QCmargin = intern (":margin");
11727 staticpro (&QCmargin);
11728 QCrelief = intern (":relief");
11729 staticpro (&QCrelief);
11730 Qpostscript = intern ("postscript");
11731 staticpro (&Qpostscript);
11732 QCloader = intern (":loader");
11733 staticpro (&QCloader);
11734 QCbounding_box = intern (":bounding-box");
11735 staticpro (&QCbounding_box);
11736 QCpt_width = intern (":pt-width");
11737 staticpro (&QCpt_width);
11738 QCpt_height = intern (":pt-height");
11739 staticpro (&QCpt_height);
11740 QCindex = intern (":index");
11741 staticpro (&QCindex);
11742 Qpbm = intern ("pbm");
11743 staticpro (&Qpbm);
11745 #if HAVE_XPM
11746 Qxpm = intern ("xpm");
11747 staticpro (&Qxpm);
11748 #endif
11750 #if HAVE_JPEG
11751 Qjpeg = intern ("jpeg");
11752 staticpro (&Qjpeg);
11753 #endif
11755 #if HAVE_TIFF
11756 Qtiff = intern ("tiff");
11757 staticpro (&Qtiff);
11758 #endif
11760 #if HAVE_GIF
11761 Qgif = intern ("gif");
11762 staticpro (&Qgif);
11763 #endif
11765 #if HAVE_PNG
11766 Qpng = intern ("png");
11767 staticpro (&Qpng);
11768 #endif
11770 defsubr (&Sclear_image_cache);
11771 defsubr (&Simage_size);
11772 defsubr (&Simage_mask_p);
11774 hourglass_atimer = NULL;
11775 hourglass_shown_p = 0;
11777 defsubr (&Sx_show_tip);
11778 defsubr (&Sx_hide_tip);
11779 tip_timer = Qnil;
11780 staticpro (&tip_timer);
11781 tip_frame = Qnil;
11782 staticpro (&tip_frame);
11784 last_show_tip_args = Qnil;
11785 staticpro (&last_show_tip_args);
11787 #ifdef USE_MOTIF
11788 defsubr (&Sx_file_dialog);
11789 #endif
11793 void
11794 init_xfns ()
11796 image_types = NULL;
11797 Vimage_types = Qnil;
11799 define_image_type (&xbm_type);
11800 define_image_type (&gs_type);
11801 define_image_type (&pbm_type);
11803 #if HAVE_XPM
11804 define_image_type (&xpm_type);
11805 #endif
11807 #if HAVE_JPEG
11808 define_image_type (&jpeg_type);
11809 #endif
11811 #if HAVE_TIFF
11812 define_image_type (&tiff_type);
11813 #endif
11815 #if HAVE_GIF
11816 define_image_type (&gif_type);
11817 #endif
11819 #if HAVE_PNG
11820 define_image_type (&png_type);
11821 #endif
11824 #endif /* HAVE_X_WINDOWS */