Instructions to create pretest or release tarballs.
[emacs.git] / src / xfns.c
blob67e10f742b3e8d7f50c27a46b461b878b27be8a6
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
35 #include "lisp.h"
36 #include "xterm.h"
37 #include "frame.h"
38 #include "window.h"
39 #include "buffer.h"
40 #include "intervals.h"
41 #include "dispextern.h"
42 #include "keyboard.h"
43 #include "blockinput.h"
44 #include <epaths.h>
45 #include "charset.h"
46 #include "coding.h"
47 #include "fontset.h"
48 #include "systime.h"
49 #include "termhooks.h"
50 #include "atimer.h"
52 #ifdef HAVE_X_WINDOWS
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
58 #ifndef VMS
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
61 #else
62 #include <X11/bitmaps/gray>
63 #endif
64 #else
65 #include "[.bitmaps]gray.xbm"
66 #endif
68 #ifdef USE_X_TOOLKIT
69 #include <X11/Shell.h>
71 #ifndef USE_MOTIF
72 #include <X11/Xaw/Paned.h>
73 #include <X11/Xaw/Label.h>
74 #endif /* USE_MOTIF */
76 #ifdef USG
77 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
78 #include <X11/Xos.h>
79 #define USG
80 #else
81 #include <X11/Xos.h>
82 #endif
84 #include "widget.h"
86 #include "../lwlib/lwlib.h"
88 #ifdef USE_MOTIF
89 #include <Xm/Xm.h>
90 #include <Xm/DialogS.h>
91 #include <Xm/FileSB.h>
92 #endif
94 /* Do the EDITRES protocol if running X11R5
95 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
98 #define HACK_EDITRES
99 extern void _XEditResCheckMessages ();
100 #endif /* R5 + Athena */
102 /* Unique id counter for widgets created by the Lucid Widget Library. */
104 extern LWLIB_ID widget_id_tick;
106 #ifdef USE_LUCID
107 /* This is part of a kludge--see lwlib/xlwmenu.c. */
108 extern XFontStruct *xlwmenu_default_font;
109 #endif
111 extern void free_frame_menubar ();
112 extern double atof ();
114 #ifdef USE_MOTIF
116 /* LessTif/Motif version info. */
118 static Lisp_Object Vmotif_version_string;
120 #endif /* USE_MOTIF */
122 #endif /* USE_X_TOOLKIT */
124 #define min(a,b) ((a) < (b) ? (a) : (b))
125 #define max(a,b) ((a) > (b) ? (a) : (b))
127 #ifdef HAVE_X11R4
128 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
129 #else
130 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
131 #endif
133 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
134 it, and including `bitmaps/gray' more than once is a problem when
135 config.h defines `static' as an empty replacement string. */
137 int gray_bitmap_width = gray_width;
138 int gray_bitmap_height = gray_height;
139 char *gray_bitmap_bits = gray_bits;
141 /* The name we're using in resource queries. Most often "emacs". */
143 Lisp_Object Vx_resource_name;
145 /* The application class we're using in resource queries.
146 Normally "Emacs". */
148 Lisp_Object Vx_resource_class;
150 /* Non-zero means we're allowed to display an hourglass cursor. */
152 int display_hourglass_p;
154 /* The background and shape of the mouse pointer, and shape when not
155 over text or in the modeline. */
157 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
158 Lisp_Object Vx_hourglass_pointer_shape;
160 /* The shape when over mouse-sensitive text. */
162 Lisp_Object Vx_sensitive_text_pointer_shape;
164 /* If non-nil, the pointer shape to indicate that windows can be
165 dragged horizontally. */
167 Lisp_Object Vx_window_horizontal_drag_shape;
169 /* Color of chars displayed in cursor box. */
171 Lisp_Object Vx_cursor_fore_pixel;
173 /* Nonzero if using X. */
175 static int x_in_use;
177 /* Non nil if no window manager is in use. */
179 Lisp_Object Vx_no_window_manager;
181 /* Search path for bitmap files. */
183 Lisp_Object Vx_bitmap_file_path;
185 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
187 Lisp_Object Vx_pixel_size_width_font_regexp;
189 Lisp_Object Qauto_raise;
190 Lisp_Object Qauto_lower;
191 Lisp_Object Qbar;
192 Lisp_Object Qborder_color;
193 Lisp_Object Qborder_width;
194 Lisp_Object Qbox;
195 Lisp_Object Qcursor_color;
196 Lisp_Object Qcursor_type;
197 Lisp_Object Qgeometry;
198 Lisp_Object Qicon_left;
199 Lisp_Object Qicon_top;
200 Lisp_Object Qicon_type;
201 Lisp_Object Qicon_name;
202 Lisp_Object Qinternal_border_width;
203 Lisp_Object Qleft;
204 Lisp_Object Qright;
205 Lisp_Object Qmouse_color;
206 Lisp_Object Qnone;
207 Lisp_Object Qouter_window_id;
208 Lisp_Object Qparent_id;
209 Lisp_Object Qscroll_bar_width;
210 Lisp_Object Qsuppress_icon;
211 extern Lisp_Object Qtop;
212 Lisp_Object Qundefined_color;
213 Lisp_Object Qvertical_scroll_bars;
214 Lisp_Object Qvisibility;
215 Lisp_Object Qwindow_id;
216 Lisp_Object Qx_frame_parameter;
217 Lisp_Object Qx_resource_name;
218 Lisp_Object Quser_position;
219 Lisp_Object Quser_size;
220 extern Lisp_Object Qdisplay;
221 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
222 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
223 Lisp_Object Qcompound_text, Qcancel_timer;
224 Lisp_Object Qwait_for_wm;
226 /* The below are defined in frame.c. */
228 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
229 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
230 extern Lisp_Object Qtool_bar_lines;
232 extern Lisp_Object Vwindow_system_version;
234 Lisp_Object Qface_set_after_frame_default;
236 #if GLYPH_DEBUG
237 int image_cache_refcount, dpyinfo_refcount;
238 #endif
242 /* Error if we are not connected to X. */
244 void
245 check_x ()
247 if (! x_in_use)
248 error ("X windows are not in use or not initialized");
251 /* Nonzero if we can use mouse menus.
252 You should not call this unless HAVE_MENUS is defined. */
255 have_menus_p ()
257 return x_in_use;
260 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
261 and checking validity for X. */
263 FRAME_PTR
264 check_x_frame (frame)
265 Lisp_Object frame;
267 FRAME_PTR f;
269 if (NILP (frame))
270 frame = selected_frame;
271 CHECK_LIVE_FRAME (frame, 0);
272 f = XFRAME (frame);
273 if (! FRAME_X_P (f))
274 error ("Non-X frame used");
275 return f;
278 /* Let the user specify an X display with a frame.
279 nil stands for the selected frame--or, if that is not an X frame,
280 the first X display on the list. */
282 static struct x_display_info *
283 check_x_display_info (frame)
284 Lisp_Object frame;
286 struct x_display_info *dpyinfo = NULL;
288 if (NILP (frame))
290 struct frame *sf = XFRAME (selected_frame);
292 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
293 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
294 else if (x_display_list != 0)
295 dpyinfo = x_display_list;
296 else
297 error ("X windows are not in use or not initialized");
299 else if (STRINGP (frame))
300 dpyinfo = x_display_info_for_name (frame);
301 else
303 FRAME_PTR f;
305 CHECK_LIVE_FRAME (frame, 0);
306 f = XFRAME (frame);
307 if (! FRAME_X_P (f))
308 error ("Non-X frame used");
309 dpyinfo = FRAME_X_DISPLAY_INFO (f);
312 return dpyinfo;
316 /* Return the Emacs frame-object corresponding to an X window.
317 It could be the frame's main window or an icon window. */
319 /* This function can be called during GC, so use GC_xxx type test macros. */
321 struct frame *
322 x_window_to_frame (dpyinfo, wdesc)
323 struct x_display_info *dpyinfo;
324 int wdesc;
326 Lisp_Object tail, frame;
327 struct frame *f;
329 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
331 frame = XCAR (tail);
332 if (!GC_FRAMEP (frame))
333 continue;
334 f = XFRAME (frame);
335 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
336 continue;
337 if (f->output_data.x->hourglass_window == wdesc)
338 return f;
339 #ifdef USE_X_TOOLKIT
340 if ((f->output_data.x->edit_widget
341 && XtWindow (f->output_data.x->edit_widget) == wdesc)
342 /* A tooltip frame? */
343 || (!f->output_data.x->edit_widget
344 && FRAME_X_WINDOW (f) == wdesc)
345 || f->output_data.x->icon_desc == wdesc)
346 return f;
347 #else /* not USE_X_TOOLKIT */
348 if (FRAME_X_WINDOW (f) == wdesc
349 || f->output_data.x->icon_desc == wdesc)
350 return f;
351 #endif /* not USE_X_TOOLKIT */
353 return 0;
356 #ifdef USE_X_TOOLKIT
357 /* Like x_window_to_frame but also compares the window with the widget's
358 windows. */
360 struct frame *
361 x_any_window_to_frame (dpyinfo, wdesc)
362 struct x_display_info *dpyinfo;
363 int wdesc;
365 Lisp_Object tail, frame;
366 struct frame *f, *found;
367 struct x_output *x;
369 found = NULL;
370 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
372 frame = XCAR (tail);
373 if (!GC_FRAMEP (frame))
374 continue;
376 f = XFRAME (frame);
377 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
379 /* This frame matches if the window is any of its widgets. */
380 x = f->output_data.x;
381 if (x->hourglass_window == wdesc)
382 found = f;
383 else if (x->widget)
385 if (wdesc == XtWindow (x->widget)
386 || wdesc == XtWindow (x->column_widget)
387 || wdesc == XtWindow (x->edit_widget))
388 found = f;
389 /* Match if the window is this frame's menubar. */
390 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
391 found = f;
393 else if (FRAME_X_WINDOW (f) == wdesc)
394 /* A tooltip frame. */
395 found = f;
399 return found;
402 /* Likewise, but exclude the menu bar widget. */
404 struct frame *
405 x_non_menubar_window_to_frame (dpyinfo, wdesc)
406 struct x_display_info *dpyinfo;
407 int wdesc;
409 Lisp_Object tail, frame;
410 struct frame *f;
411 struct x_output *x;
413 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
415 frame = XCAR (tail);
416 if (!GC_FRAMEP (frame))
417 continue;
418 f = XFRAME (frame);
419 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
420 continue;
421 x = f->output_data.x;
422 /* This frame matches if the window is any of its widgets. */
423 if (x->hourglass_window == wdesc)
424 return f;
425 else if (x->widget)
427 if (wdesc == XtWindow (x->widget)
428 || wdesc == XtWindow (x->column_widget)
429 || wdesc == XtWindow (x->edit_widget))
430 return f;
432 else if (FRAME_X_WINDOW (f) == wdesc)
433 /* A tooltip frame. */
434 return f;
436 return 0;
439 /* Likewise, but consider only the menu bar widget. */
441 struct frame *
442 x_menubar_window_to_frame (dpyinfo, wdesc)
443 struct x_display_info *dpyinfo;
444 int wdesc;
446 Lisp_Object tail, frame;
447 struct frame *f;
448 struct x_output *x;
450 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
452 frame = XCAR (tail);
453 if (!GC_FRAMEP (frame))
454 continue;
455 f = XFRAME (frame);
456 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
457 continue;
458 x = f->output_data.x;
459 /* Match if the window is this frame's menubar. */
460 if (x->menubar_widget
461 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
462 return f;
464 return 0;
467 /* Return the frame whose principal (outermost) window is WDESC.
468 If WDESC is some other (smaller) window, we return 0. */
470 struct frame *
471 x_top_window_to_frame (dpyinfo, wdesc)
472 struct x_display_info *dpyinfo;
473 int wdesc;
475 Lisp_Object tail, frame;
476 struct frame *f;
477 struct x_output *x;
479 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
481 frame = XCAR (tail);
482 if (!GC_FRAMEP (frame))
483 continue;
484 f = XFRAME (frame);
485 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
486 continue;
487 x = f->output_data.x;
489 if (x->widget)
491 /* This frame matches if the window is its topmost widget. */
492 if (wdesc == XtWindow (x->widget))
493 return f;
494 #if 0 /* I don't know why it did this,
495 but it seems logically wrong,
496 and it causes trouble for MapNotify events. */
497 /* Match if the window is this frame's menubar. */
498 if (x->menubar_widget
499 && wdesc == XtWindow (x->menubar_widget))
500 return f;
501 #endif
503 else if (FRAME_X_WINDOW (f) == wdesc)
504 /* Tooltip frame. */
505 return f;
507 return 0;
509 #endif /* USE_X_TOOLKIT */
513 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
514 id, which is just an int that this section returns. Bitmaps are
515 reference counted so they can be shared among frames.
517 Bitmap indices are guaranteed to be > 0, so a negative number can
518 be used to indicate no bitmap.
520 If you use x_create_bitmap_from_data, then you must keep track of
521 the bitmaps yourself. That is, creating a bitmap from the same
522 data more than once will not be caught. */
525 /* Functions to access the contents of a bitmap, given an id. */
528 x_bitmap_height (f, id)
529 FRAME_PTR f;
530 int id;
532 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
536 x_bitmap_width (f, id)
537 FRAME_PTR f;
538 int id;
540 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
544 x_bitmap_pixmap (f, id)
545 FRAME_PTR f;
546 int id;
548 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
552 /* Allocate a new bitmap record. Returns index of new record. */
554 static int
555 x_allocate_bitmap_record (f)
556 FRAME_PTR f;
558 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
559 int i;
561 if (dpyinfo->bitmaps == NULL)
563 dpyinfo->bitmaps_size = 10;
564 dpyinfo->bitmaps
565 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
566 dpyinfo->bitmaps_last = 1;
567 return 1;
570 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
571 return ++dpyinfo->bitmaps_last;
573 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
574 if (dpyinfo->bitmaps[i].refcount == 0)
575 return i + 1;
577 dpyinfo->bitmaps_size *= 2;
578 dpyinfo->bitmaps
579 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
580 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
581 return ++dpyinfo->bitmaps_last;
584 /* Add one reference to the reference count of the bitmap with id ID. */
586 void
587 x_reference_bitmap (f, id)
588 FRAME_PTR f;
589 int id;
591 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
594 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
597 x_create_bitmap_from_data (f, bits, width, height)
598 struct frame *f;
599 char *bits;
600 unsigned int width, height;
602 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
603 Pixmap bitmap;
604 int id;
606 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
607 bits, width, height);
609 if (! bitmap)
610 return -1;
612 id = x_allocate_bitmap_record (f);
613 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
614 dpyinfo->bitmaps[id - 1].file = NULL;
615 dpyinfo->bitmaps[id - 1].refcount = 1;
616 dpyinfo->bitmaps[id - 1].depth = 1;
617 dpyinfo->bitmaps[id - 1].height = height;
618 dpyinfo->bitmaps[id - 1].width = width;
620 return id;
623 /* Create bitmap from file FILE for frame F. */
626 x_create_bitmap_from_file (f, file)
627 struct frame *f;
628 Lisp_Object file;
630 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
631 unsigned int width, height;
632 Pixmap bitmap;
633 int xhot, yhot, result, id;
634 Lisp_Object found;
635 int fd;
636 char *filename;
638 /* Look for an existing bitmap with the same name. */
639 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
641 if (dpyinfo->bitmaps[id].refcount
642 && dpyinfo->bitmaps[id].file
643 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
645 ++dpyinfo->bitmaps[id].refcount;
646 return id + 1;
650 /* Search bitmap-file-path for the file, if appropriate. */
651 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
652 if (fd < 0)
653 return -1;
654 emacs_close (fd);
656 filename = (char *) XSTRING (found)->data;
658 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
659 filename, &width, &height, &bitmap, &xhot, &yhot);
660 if (result != BitmapSuccess)
661 return -1;
663 id = x_allocate_bitmap_record (f);
664 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
665 dpyinfo->bitmaps[id - 1].refcount = 1;
666 dpyinfo->bitmaps[id - 1].file
667 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
668 dpyinfo->bitmaps[id - 1].depth = 1;
669 dpyinfo->bitmaps[id - 1].height = height;
670 dpyinfo->bitmaps[id - 1].width = width;
671 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
673 return id;
676 /* Remove reference to bitmap with id number ID. */
678 void
679 x_destroy_bitmap (f, id)
680 FRAME_PTR f;
681 int id;
683 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
685 if (id > 0)
687 --dpyinfo->bitmaps[id - 1].refcount;
688 if (dpyinfo->bitmaps[id - 1].refcount == 0)
690 BLOCK_INPUT;
691 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
692 if (dpyinfo->bitmaps[id - 1].file)
694 xfree (dpyinfo->bitmaps[id - 1].file);
695 dpyinfo->bitmaps[id - 1].file = NULL;
697 UNBLOCK_INPUT;
702 /* Free all the bitmaps for the display specified by DPYINFO. */
704 static void
705 x_destroy_all_bitmaps (dpyinfo)
706 struct x_display_info *dpyinfo;
708 int i;
709 for (i = 0; i < dpyinfo->bitmaps_last; i++)
710 if (dpyinfo->bitmaps[i].refcount > 0)
712 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
713 if (dpyinfo->bitmaps[i].file)
714 xfree (dpyinfo->bitmaps[i].file);
716 dpyinfo->bitmaps_last = 0;
719 /* Connect the frame-parameter names for X frames
720 to the ways of passing the parameter values to the window system.
722 The name of a parameter, as a Lisp symbol,
723 has an `x-frame-parameter' property which is an integer in Lisp
724 that is an index in this table. */
726 struct x_frame_parm_table
728 char *name;
729 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
732 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
733 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
734 static void x_change_window_heights P_ ((Lisp_Object, int));
735 static void x_disable_image P_ ((struct frame *, struct image *));
736 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
749 Lisp_Object));
750 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
754 Lisp_Object));
755 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
760 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
761 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
762 Lisp_Object));
763 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
764 Lisp_Object));
765 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
766 Lisp_Object,
767 Lisp_Object,
768 char *, char *,
769 int));
770 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
771 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
772 Lisp_Object));
773 static void init_color_table P_ ((void));
774 static void free_color_table P_ ((void));
775 static unsigned long *colors_in_color_table P_ ((int *n));
776 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
777 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
781 static struct x_frame_parm_table x_frame_parms[] =
783 "auto-raise", x_set_autoraise,
784 "auto-lower", x_set_autolower,
785 "background-color", x_set_background_color,
786 "border-color", x_set_border_color,
787 "border-width", x_set_border_width,
788 "cursor-color", x_set_cursor_color,
789 "cursor-type", x_set_cursor_type,
790 "font", x_set_font,
791 "foreground-color", x_set_foreground_color,
792 "icon-name", x_set_icon_name,
793 "icon-type", x_set_icon_type,
794 "internal-border-width", x_set_internal_border_width,
795 "menu-bar-lines", x_set_menu_bar_lines,
796 "mouse-color", x_set_mouse_color,
797 "name", x_explicitly_set_name,
798 "scroll-bar-width", x_set_scroll_bar_width,
799 "title", x_set_title,
800 "unsplittable", x_set_unsplittable,
801 "vertical-scroll-bars", x_set_vertical_scroll_bars,
802 "visibility", x_set_visibility,
803 "tool-bar-lines", x_set_tool_bar_lines,
804 "scroll-bar-foreground", x_set_scroll_bar_foreground,
805 "scroll-bar-background", x_set_scroll_bar_background,
806 "screen-gamma", x_set_screen_gamma,
807 "line-spacing", x_set_line_spacing,
808 "wait-for-wm", x_set_wait_for_wm
811 /* Attach the `x-frame-parameter' properties to
812 the Lisp symbol names of parameters relevant to X. */
814 void
815 init_x_parm_symbols ()
817 int i;
819 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
820 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
821 make_number (i));
824 /* Change the parameters of frame F as specified by ALIST.
825 If a parameter is not specially recognized, do nothing special;
826 otherwise call the `x_set_...' function for that parameter.
827 Except for certain geometry properties, always call store_frame_param
828 to store the new value in the parameter alist. */
830 void
831 x_set_frame_parameters (f, alist)
832 FRAME_PTR f;
833 Lisp_Object alist;
835 Lisp_Object tail;
837 /* If both of these parameters are present, it's more efficient to
838 set them both at once. So we wait until we've looked at the
839 entire list before we set them. */
840 int width, height;
842 /* Same here. */
843 Lisp_Object left, top;
845 /* Same with these. */
846 Lisp_Object icon_left, icon_top;
848 /* Record in these vectors all the parms specified. */
849 Lisp_Object *parms;
850 Lisp_Object *values;
851 int i, p;
852 int left_no_change = 0, top_no_change = 0;
853 int icon_left_no_change = 0, icon_top_no_change = 0;
855 struct gcpro gcpro1, gcpro2;
857 i = 0;
858 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
859 i++;
861 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
862 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
864 /* Extract parm names and values into those vectors. */
866 i = 0;
867 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
869 Lisp_Object elt;
871 elt = Fcar (tail);
872 parms[i] = Fcar (elt);
873 values[i] = Fcdr (elt);
874 i++;
876 /* TAIL and ALIST are not used again below here. */
877 alist = tail = Qnil;
879 GCPRO2 (*parms, *values);
880 gcpro1.nvars = i;
881 gcpro2.nvars = i;
883 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
884 because their values appear in VALUES and strings are not valid. */
885 top = left = Qunbound;
886 icon_left = icon_top = Qunbound;
888 /* Provide default values for HEIGHT and WIDTH. */
889 if (FRAME_NEW_WIDTH (f))
890 width = FRAME_NEW_WIDTH (f);
891 else
892 width = FRAME_WIDTH (f);
894 if (FRAME_NEW_HEIGHT (f))
895 height = FRAME_NEW_HEIGHT (f);
896 else
897 height = FRAME_HEIGHT (f);
899 /* Process foreground_color and background_color before anything else.
900 They are independent of other properties, but other properties (e.g.,
901 cursor_color) are dependent upon them. */
902 for (p = 0; p < i; p++)
904 Lisp_Object prop, val;
906 prop = parms[p];
907 val = values[p];
908 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
910 register Lisp_Object param_index, old_value;
912 param_index = Fget (prop, Qx_frame_parameter);
913 old_value = get_frame_param (f, prop);
914 store_frame_param (f, prop, val);
915 if (NATNUMP (param_index)
916 && (XFASTINT (param_index)
917 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
918 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
922 /* Now process them in reverse of specified order. */
923 for (i--; i >= 0; i--)
925 Lisp_Object prop, val;
927 prop = parms[i];
928 val = values[i];
930 if (EQ (prop, Qwidth) && NUMBERP (val))
931 width = XFASTINT (val);
932 else if (EQ (prop, Qheight) && NUMBERP (val))
933 height = XFASTINT (val);
934 else if (EQ (prop, Qtop))
935 top = val;
936 else if (EQ (prop, Qleft))
937 left = val;
938 else if (EQ (prop, Qicon_top))
939 icon_top = val;
940 else if (EQ (prop, Qicon_left))
941 icon_left = val;
942 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
943 /* Processed above. */
944 continue;
945 else
947 register Lisp_Object param_index, old_value;
949 param_index = Fget (prop, Qx_frame_parameter);
950 old_value = get_frame_param (f, prop);
951 store_frame_param (f, prop, val);
952 if (NATNUMP (param_index)
953 && (XFASTINT (param_index)
954 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
955 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
959 /* Don't die if just one of these was set. */
960 if (EQ (left, Qunbound))
962 left_no_change = 1;
963 if (f->output_data.x->left_pos < 0)
964 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
965 else
966 XSETINT (left, f->output_data.x->left_pos);
968 if (EQ (top, Qunbound))
970 top_no_change = 1;
971 if (f->output_data.x->top_pos < 0)
972 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
973 else
974 XSETINT (top, f->output_data.x->top_pos);
977 /* If one of the icon positions was not set, preserve or default it. */
978 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
980 icon_left_no_change = 1;
981 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
982 if (NILP (icon_left))
983 XSETINT (icon_left, 0);
985 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
987 icon_top_no_change = 1;
988 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
989 if (NILP (icon_top))
990 XSETINT (icon_top, 0);
993 /* Don't set these parameters unless they've been explicitly
994 specified. The window might be mapped or resized while we're in
995 this function, and we don't want to override that unless the lisp
996 code has asked for it.
998 Don't set these parameters unless they actually differ from the
999 window's current parameters; the window may not actually exist
1000 yet. */
1002 Lisp_Object frame;
1004 check_frame_size (f, &height, &width);
1006 XSETFRAME (frame, f);
1008 if (width != FRAME_WIDTH (f)
1009 || height != FRAME_HEIGHT (f)
1010 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1011 Fset_frame_size (frame, make_number (width), make_number (height));
1013 if ((!NILP (left) || !NILP (top))
1014 && ! (left_no_change && top_no_change)
1015 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1016 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1018 int leftpos = 0;
1019 int toppos = 0;
1021 /* Record the signs. */
1022 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1023 if (EQ (left, Qminus))
1024 f->output_data.x->size_hint_flags |= XNegative;
1025 else if (INTEGERP (left))
1027 leftpos = XINT (left);
1028 if (leftpos < 0)
1029 f->output_data.x->size_hint_flags |= XNegative;
1031 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1032 && CONSP (XCDR (left))
1033 && INTEGERP (XCAR (XCDR (left))))
1035 leftpos = - XINT (XCAR (XCDR (left)));
1036 f->output_data.x->size_hint_flags |= XNegative;
1038 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1039 && CONSP (XCDR (left))
1040 && INTEGERP (XCAR (XCDR (left))))
1042 leftpos = XINT (XCAR (XCDR (left)));
1045 if (EQ (top, Qminus))
1046 f->output_data.x->size_hint_flags |= YNegative;
1047 else if (INTEGERP (top))
1049 toppos = XINT (top);
1050 if (toppos < 0)
1051 f->output_data.x->size_hint_flags |= YNegative;
1053 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1054 && CONSP (XCDR (top))
1055 && INTEGERP (XCAR (XCDR (top))))
1057 toppos = - XINT (XCAR (XCDR (top)));
1058 f->output_data.x->size_hint_flags |= YNegative;
1060 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1061 && CONSP (XCDR (top))
1062 && INTEGERP (XCAR (XCDR (top))))
1064 toppos = XINT (XCAR (XCDR (top)));
1068 /* Store the numeric value of the position. */
1069 f->output_data.x->top_pos = toppos;
1070 f->output_data.x->left_pos = leftpos;
1072 f->output_data.x->win_gravity = NorthWestGravity;
1074 /* Actually set that position, and convert to absolute. */
1075 x_set_offset (f, leftpos, toppos, -1);
1078 if ((!NILP (icon_left) || !NILP (icon_top))
1079 && ! (icon_left_no_change && icon_top_no_change))
1080 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1083 UNGCPRO;
1086 /* Store the screen positions of frame F into XPTR and YPTR.
1087 These are the positions of the containing window manager window,
1088 not Emacs's own window. */
1090 void
1091 x_real_positions (f, xptr, yptr)
1092 FRAME_PTR f;
1093 int *xptr, *yptr;
1095 int win_x, win_y;
1096 Window child;
1098 /* This is pretty gross, but seems to be the easiest way out of
1099 the problem that arises when restarting window-managers. */
1101 #ifdef USE_X_TOOLKIT
1102 Window outer = (f->output_data.x->widget
1103 ? XtWindow (f->output_data.x->widget)
1104 : FRAME_X_WINDOW (f));
1105 #else
1106 Window outer = f->output_data.x->window_desc;
1107 #endif
1108 Window tmp_root_window;
1109 Window *tmp_children;
1110 unsigned int tmp_nchildren;
1112 while (1)
1114 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1115 Window outer_window;
1117 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1118 &f->output_data.x->parent_desc,
1119 &tmp_children, &tmp_nchildren);
1120 XFree ((char *) tmp_children);
1122 win_x = win_y = 0;
1124 /* Find the position of the outside upper-left corner of
1125 the inner window, with respect to the outer window. */
1126 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1127 outer_window = f->output_data.x->parent_desc;
1128 else
1129 outer_window = outer;
1131 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1133 /* From-window, to-window. */
1134 outer_window,
1135 FRAME_X_DISPLAY_INFO (f)->root_window,
1137 /* From-position, to-position. */
1138 0, 0, &win_x, &win_y,
1140 /* Child of win. */
1141 &child);
1143 /* It is possible for the window returned by the XQueryNotify
1144 to become invalid by the time we call XTranslateCoordinates.
1145 That can happen when you restart some window managers.
1146 If so, we get an error in XTranslateCoordinates.
1147 Detect that and try the whole thing over. */
1148 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1150 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1151 break;
1154 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1157 *xptr = win_x;
1158 *yptr = win_y;
1161 /* Insert a description of internally-recorded parameters of frame X
1162 into the parameter alist *ALISTPTR that is to be given to the user.
1163 Only parameters that are specific to the X window system
1164 and whose values are not correctly recorded in the frame's
1165 param_alist need to be considered here. */
1167 void
1168 x_report_frame_params (f, alistptr)
1169 struct frame *f;
1170 Lisp_Object *alistptr;
1172 char buf[16];
1173 Lisp_Object tem;
1175 /* Represent negative positions (off the top or left screen edge)
1176 in a way that Fmodify_frame_parameters will understand correctly. */
1177 XSETINT (tem, f->output_data.x->left_pos);
1178 if (f->output_data.x->left_pos >= 0)
1179 store_in_alist (alistptr, Qleft, tem);
1180 else
1181 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1183 XSETINT (tem, f->output_data.x->top_pos);
1184 if (f->output_data.x->top_pos >= 0)
1185 store_in_alist (alistptr, Qtop, tem);
1186 else
1187 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1189 store_in_alist (alistptr, Qborder_width,
1190 make_number (f->output_data.x->border_width));
1191 store_in_alist (alistptr, Qinternal_border_width,
1192 make_number (f->output_data.x->internal_border_width));
1193 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1194 store_in_alist (alistptr, Qwindow_id,
1195 build_string (buf));
1196 #ifdef USE_X_TOOLKIT
1197 /* Tooltip frame may not have this widget. */
1198 if (f->output_data.x->widget)
1199 #endif
1200 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1201 store_in_alist (alistptr, Qouter_window_id,
1202 build_string (buf));
1203 store_in_alist (alistptr, Qicon_name, f->icon_name);
1204 FRAME_SAMPLE_VISIBILITY (f);
1205 store_in_alist (alistptr, Qvisibility,
1206 (FRAME_VISIBLE_P (f) ? Qt
1207 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1208 store_in_alist (alistptr, Qdisplay,
1209 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1211 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1212 tem = Qnil;
1213 else
1214 XSETFASTINT (tem, f->output_data.x->parent_desc);
1215 store_in_alist (alistptr, Qparent_id, tem);
1220 /* Gamma-correct COLOR on frame F. */
1222 void
1223 gamma_correct (f, color)
1224 struct frame *f;
1225 XColor *color;
1227 if (f->gamma)
1229 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1230 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1231 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1236 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1237 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1238 allocate the color. Value is zero if COLOR_NAME is invalid, or
1239 no color could be allocated. */
1242 x_defined_color (f, color_name, color, alloc_p)
1243 struct frame *f;
1244 char *color_name;
1245 XColor *color;
1246 int alloc_p;
1248 int success_p;
1249 Display *dpy = FRAME_X_DISPLAY (f);
1250 Colormap cmap = FRAME_X_COLORMAP (f);
1252 BLOCK_INPUT;
1253 success_p = XParseColor (dpy, cmap, color_name, color);
1254 if (success_p && alloc_p)
1255 success_p = x_alloc_nearest_color (f, cmap, color);
1256 UNBLOCK_INPUT;
1258 return success_p;
1262 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1263 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1264 Signal an error if color can't be allocated. */
1267 x_decode_color (f, color_name, mono_color)
1268 FRAME_PTR f;
1269 Lisp_Object color_name;
1270 int mono_color;
1272 XColor cdef;
1274 CHECK_STRING (color_name, 0);
1276 #if 0 /* Don't do this. It's wrong when we're not using the default
1277 colormap, it makes freeing difficult, and it's probably not
1278 an important optimization. */
1279 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1280 return BLACK_PIX_DEFAULT (f);
1281 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1282 return WHITE_PIX_DEFAULT (f);
1283 #endif
1285 /* Return MONO_COLOR for monochrome frames. */
1286 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1287 return mono_color;
1289 /* x_defined_color is responsible for coping with failures
1290 by looking for a near-miss. */
1291 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1292 return cdef.pixel;
1294 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1295 Fcons (color_name, Qnil)));
1296 return 0;
1301 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1302 the previous value of that parameter, NEW_VALUE is the new value. */
1304 static void
1305 x_set_line_spacing (f, new_value, old_value)
1306 struct frame *f;
1307 Lisp_Object new_value, old_value;
1309 if (NILP (new_value))
1310 f->extra_line_spacing = 0;
1311 else if (NATNUMP (new_value))
1312 f->extra_line_spacing = XFASTINT (new_value);
1313 else
1314 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1315 Fcons (new_value, Qnil)));
1316 if (FRAME_VISIBLE_P (f))
1317 redraw_frame (f);
1321 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1322 the previous value of that parameter, NEW_VALUE is the new value.
1323 See also the comment of wait_for_wm in struct x_output. */
1325 static void
1326 x_set_wait_for_wm (f, new_value, old_value)
1327 struct frame *f;
1328 Lisp_Object new_value, old_value;
1330 f->output_data.x->wait_for_wm = !NILP (new_value);
1334 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1335 the previous value of that parameter, NEW_VALUE is the new
1336 value. */
1338 static void
1339 x_set_screen_gamma (f, new_value, old_value)
1340 struct frame *f;
1341 Lisp_Object new_value, old_value;
1343 if (NILP (new_value))
1344 f->gamma = 0;
1345 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1346 /* The value 0.4545 is the normal viewing gamma. */
1347 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1348 else
1349 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1350 Fcons (new_value, Qnil)));
1352 clear_face_cache (0);
1356 /* Functions called only from `x_set_frame_param'
1357 to set individual parameters.
1359 If FRAME_X_WINDOW (f) is 0,
1360 the frame is being created and its X-window does not exist yet.
1361 In that case, just record the parameter's new value
1362 in the standard place; do not attempt to change the window. */
1364 void
1365 x_set_foreground_color (f, arg, oldval)
1366 struct frame *f;
1367 Lisp_Object arg, oldval;
1369 struct x_output *x = f->output_data.x;
1370 unsigned long fg, old_fg;
1372 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1373 old_fg = x->foreground_pixel;
1374 x->foreground_pixel = fg;
1376 if (FRAME_X_WINDOW (f) != 0)
1378 Display *dpy = FRAME_X_DISPLAY (f);
1380 BLOCK_INPUT;
1381 XSetForeground (dpy, x->normal_gc, fg);
1382 XSetBackground (dpy, x->reverse_gc, fg);
1384 if (x->cursor_pixel == old_fg)
1386 unload_color (f, x->cursor_pixel);
1387 x->cursor_pixel = x_copy_color (f, fg);
1388 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1391 UNBLOCK_INPUT;
1393 update_face_from_frame_parameter (f, Qforeground_color, arg);
1395 if (FRAME_VISIBLE_P (f))
1396 redraw_frame (f);
1399 unload_color (f, old_fg);
1402 void
1403 x_set_background_color (f, arg, oldval)
1404 struct frame *f;
1405 Lisp_Object arg, oldval;
1407 struct x_output *x = f->output_data.x;
1408 unsigned long bg;
1410 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1411 unload_color (f, x->background_pixel);
1412 x->background_pixel = bg;
1414 if (FRAME_X_WINDOW (f) != 0)
1416 Display *dpy = FRAME_X_DISPLAY (f);
1418 BLOCK_INPUT;
1419 XSetBackground (dpy, x->normal_gc, bg);
1420 XSetForeground (dpy, x->reverse_gc, bg);
1421 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1422 XSetForeground (dpy, x->cursor_gc, bg);
1424 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1425 toolkit scroll bars. */
1427 Lisp_Object bar;
1428 for (bar = FRAME_SCROLL_BARS (f);
1429 !NILP (bar);
1430 bar = XSCROLL_BAR (bar)->next)
1432 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1433 XSetWindowBackground (dpy, window, bg);
1436 #endif /* USE_TOOLKIT_SCROLL_BARS */
1438 UNBLOCK_INPUT;
1439 update_face_from_frame_parameter (f, Qbackground_color, arg);
1441 if (FRAME_VISIBLE_P (f))
1442 redraw_frame (f);
1446 void
1447 x_set_mouse_color (f, arg, oldval)
1448 struct frame *f;
1449 Lisp_Object arg, oldval;
1451 struct x_output *x = f->output_data.x;
1452 Display *dpy = FRAME_X_DISPLAY (f);
1453 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1454 Cursor hourglass_cursor, horizontal_drag_cursor;
1455 int count;
1456 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1457 unsigned long mask_color = x->background_pixel;
1459 /* Don't let pointers be invisible. */
1460 if (mask_color == pixel)
1462 x_free_colors (f, &pixel, 1);
1463 pixel = x_copy_color (f, x->foreground_pixel);
1466 unload_color (f, x->mouse_pixel);
1467 x->mouse_pixel = pixel;
1469 BLOCK_INPUT;
1471 /* It's not okay to crash if the user selects a screwy cursor. */
1472 count = x_catch_errors (dpy);
1474 if (!NILP (Vx_pointer_shape))
1476 CHECK_NUMBER (Vx_pointer_shape, 0);
1477 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1479 else
1480 cursor = XCreateFontCursor (dpy, XC_xterm);
1481 x_check_errors (dpy, "bad text pointer cursor: %s");
1483 if (!NILP (Vx_nontext_pointer_shape))
1485 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1486 nontext_cursor
1487 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1489 else
1490 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1491 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1493 if (!NILP (Vx_hourglass_pointer_shape))
1495 CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
1496 hourglass_cursor
1497 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1499 else
1500 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1501 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1503 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1504 if (!NILP (Vx_mode_pointer_shape))
1506 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1507 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1509 else
1510 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1511 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1513 if (!NILP (Vx_sensitive_text_pointer_shape))
1515 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1516 cross_cursor
1517 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1519 else
1520 cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
1522 if (!NILP (Vx_window_horizontal_drag_shape))
1524 CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
1525 horizontal_drag_cursor
1526 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1528 else
1529 horizontal_drag_cursor
1530 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1532 /* Check and report errors with the above calls. */
1533 x_check_errors (dpy, "can't set cursor shape: %s");
1534 x_uncatch_errors (dpy, count);
1537 XColor fore_color, back_color;
1539 fore_color.pixel = x->mouse_pixel;
1540 x_query_color (f, &fore_color);
1541 back_color.pixel = mask_color;
1542 x_query_color (f, &back_color);
1544 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1545 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1546 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1547 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1548 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1549 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1552 if (FRAME_X_WINDOW (f) != 0)
1553 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1555 if (cursor != x->text_cursor
1556 && x->text_cursor != 0)
1557 XFreeCursor (dpy, x->text_cursor);
1558 x->text_cursor = cursor;
1560 if (nontext_cursor != x->nontext_cursor
1561 && x->nontext_cursor != 0)
1562 XFreeCursor (dpy, x->nontext_cursor);
1563 x->nontext_cursor = nontext_cursor;
1565 if (hourglass_cursor != x->hourglass_cursor
1566 && x->hourglass_cursor != 0)
1567 XFreeCursor (dpy, x->hourglass_cursor);
1568 x->hourglass_cursor = hourglass_cursor;
1570 if (mode_cursor != x->modeline_cursor
1571 && x->modeline_cursor != 0)
1572 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1573 x->modeline_cursor = mode_cursor;
1575 if (cross_cursor != x->cross_cursor
1576 && x->cross_cursor != 0)
1577 XFreeCursor (dpy, x->cross_cursor);
1578 x->cross_cursor = cross_cursor;
1580 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1581 && x->horizontal_drag_cursor != 0)
1582 XFreeCursor (dpy, x->horizontal_drag_cursor);
1583 x->horizontal_drag_cursor = horizontal_drag_cursor;
1585 XFlush (dpy);
1586 UNBLOCK_INPUT;
1588 update_face_from_frame_parameter (f, Qmouse_color, arg);
1591 void
1592 x_set_cursor_color (f, arg, oldval)
1593 struct frame *f;
1594 Lisp_Object arg, oldval;
1596 unsigned long fore_pixel, pixel;
1597 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1598 struct x_output *x = f->output_data.x;
1600 if (!NILP (Vx_cursor_fore_pixel))
1602 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1603 WHITE_PIX_DEFAULT (f));
1604 fore_pixel_allocated_p = 1;
1606 else
1607 fore_pixel = x->background_pixel;
1609 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1610 pixel_allocated_p = 1;
1612 /* Make sure that the cursor color differs from the background color. */
1613 if (pixel == x->background_pixel)
1615 if (pixel_allocated_p)
1617 x_free_colors (f, &pixel, 1);
1618 pixel_allocated_p = 0;
1621 pixel = x->mouse_pixel;
1622 if (pixel == fore_pixel)
1624 if (fore_pixel_allocated_p)
1626 x_free_colors (f, &fore_pixel, 1);
1627 fore_pixel_allocated_p = 0;
1629 fore_pixel = x->background_pixel;
1633 unload_color (f, x->cursor_foreground_pixel);
1634 if (!fore_pixel_allocated_p)
1635 fore_pixel = x_copy_color (f, fore_pixel);
1636 x->cursor_foreground_pixel = fore_pixel;
1638 unload_color (f, x->cursor_pixel);
1639 if (!pixel_allocated_p)
1640 pixel = x_copy_color (f, pixel);
1641 x->cursor_pixel = pixel;
1643 if (FRAME_X_WINDOW (f) != 0)
1645 BLOCK_INPUT;
1646 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1647 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1648 UNBLOCK_INPUT;
1650 if (FRAME_VISIBLE_P (f))
1652 x_update_cursor (f, 0);
1653 x_update_cursor (f, 1);
1657 update_face_from_frame_parameter (f, Qcursor_color, arg);
1660 /* Set the border-color of frame F to value described by ARG.
1661 ARG can be a string naming a color.
1662 The border-color is used for the border that is drawn by the X server.
1663 Note that this does not fully take effect if done before
1664 F has an x-window; it must be redone when the window is created.
1666 Note: this is done in two routines because of the way X10 works.
1668 Note: under X11, this is normally the province of the window manager,
1669 and so emacs' border colors may be overridden. */
1671 void
1672 x_set_border_color (f, arg, oldval)
1673 struct frame *f;
1674 Lisp_Object arg, oldval;
1676 int pix;
1678 CHECK_STRING (arg, 0);
1679 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1680 x_set_border_pixel (f, pix);
1681 update_face_from_frame_parameter (f, Qborder_color, arg);
1684 /* Set the border-color of frame F to pixel value PIX.
1685 Note that this does not fully take effect if done before
1686 F has an x-window. */
1688 void
1689 x_set_border_pixel (f, pix)
1690 struct frame *f;
1691 int pix;
1693 unload_color (f, f->output_data.x->border_pixel);
1694 f->output_data.x->border_pixel = pix;
1696 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1698 BLOCK_INPUT;
1699 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1700 (unsigned long)pix);
1701 UNBLOCK_INPUT;
1703 if (FRAME_VISIBLE_P (f))
1704 redraw_frame (f);
1709 /* Value is the internal representation of the specified cursor type
1710 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1711 of the bar cursor. */
1713 enum text_cursor_kinds
1714 x_specified_cursor_type (arg, width)
1715 Lisp_Object arg;
1716 int *width;
1718 enum text_cursor_kinds type;
1720 if (EQ (arg, Qbar))
1722 type = BAR_CURSOR;
1723 *width = 2;
1725 else if (CONSP (arg)
1726 && EQ (XCAR (arg), Qbar)
1727 && INTEGERP (XCDR (arg))
1728 && XINT (XCDR (arg)) >= 0)
1730 type = BAR_CURSOR;
1731 *width = XINT (XCDR (arg));
1733 else if (NILP (arg))
1734 type = NO_CURSOR;
1735 else
1736 /* Treat anything unknown as "box cursor".
1737 It was bad to signal an error; people have trouble fixing
1738 .Xdefaults with Emacs, when it has something bad in it. */
1739 type = FILLED_BOX_CURSOR;
1741 return type;
1744 void
1745 x_set_cursor_type (f, arg, oldval)
1746 FRAME_PTR f;
1747 Lisp_Object arg, oldval;
1749 int width;
1751 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1752 f->output_data.x->cursor_width = width;
1754 /* Make sure the cursor gets redrawn. This is overkill, but how
1755 often do people change cursor types? */
1756 update_mode_lines++;
1759 void
1760 x_set_icon_type (f, arg, oldval)
1761 struct frame *f;
1762 Lisp_Object arg, oldval;
1764 int result;
1766 if (STRINGP (arg))
1768 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1769 return;
1771 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1772 return;
1774 BLOCK_INPUT;
1775 if (NILP (arg))
1776 result = x_text_icon (f,
1777 (char *) XSTRING ((!NILP (f->icon_name)
1778 ? f->icon_name
1779 : f->name))->data);
1780 else
1781 result = x_bitmap_icon (f, arg);
1783 if (result)
1785 UNBLOCK_INPUT;
1786 error ("No icon window available");
1789 XFlush (FRAME_X_DISPLAY (f));
1790 UNBLOCK_INPUT;
1793 /* Return non-nil if frame F wants a bitmap icon. */
1795 Lisp_Object
1796 x_icon_type (f)
1797 FRAME_PTR f;
1799 Lisp_Object tem;
1801 tem = assq_no_quit (Qicon_type, f->param_alist);
1802 if (CONSP (tem))
1803 return XCDR (tem);
1804 else
1805 return Qnil;
1808 void
1809 x_set_icon_name (f, arg, oldval)
1810 struct frame *f;
1811 Lisp_Object arg, oldval;
1813 int result;
1815 if (STRINGP (arg))
1817 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1818 return;
1820 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1821 return;
1823 f->icon_name = arg;
1825 if (f->output_data.x->icon_bitmap != 0)
1826 return;
1828 BLOCK_INPUT;
1830 result = x_text_icon (f,
1831 (char *) XSTRING ((!NILP (f->icon_name)
1832 ? f->icon_name
1833 : !NILP (f->title)
1834 ? f->title
1835 : f->name))->data);
1837 if (result)
1839 UNBLOCK_INPUT;
1840 error ("No icon window available");
1843 XFlush (FRAME_X_DISPLAY (f));
1844 UNBLOCK_INPUT;
1847 void
1848 x_set_font (f, arg, oldval)
1849 struct frame *f;
1850 Lisp_Object arg, oldval;
1852 Lisp_Object result;
1853 Lisp_Object fontset_name;
1854 Lisp_Object frame;
1855 int old_fontset = f->output_data.x->fontset;
1857 CHECK_STRING (arg, 1);
1859 fontset_name = Fquery_fontset (arg, Qnil);
1861 BLOCK_INPUT;
1862 result = (STRINGP (fontset_name)
1863 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1864 : x_new_font (f, XSTRING (arg)->data));
1865 UNBLOCK_INPUT;
1867 if (EQ (result, Qnil))
1868 error ("Font `%s' is not defined", XSTRING (arg)->data);
1869 else if (EQ (result, Qt))
1870 error ("The characters of the given font have varying widths");
1871 else if (STRINGP (result))
1873 if (STRINGP (fontset_name))
1875 /* Fontset names are built from ASCII font names, so the
1876 names may be equal despite there was a change. */
1877 if (old_fontset == f->output_data.x->fontset)
1878 return;
1880 else if (!NILP (Fequal (result, oldval)))
1881 return;
1883 store_frame_param (f, Qfont, result);
1884 recompute_basic_faces (f);
1886 else
1887 abort ();
1889 do_pending_window_change (0);
1891 /* Don't call `face-set-after-frame-default' when faces haven't been
1892 initialized yet. This is the case when called from
1893 Fx_create_frame. In that case, the X widget or window doesn't
1894 exist either, and we can end up in x_report_frame_params with a
1895 null widget which gives a segfault. */
1896 if (FRAME_FACE_CACHE (f))
1898 XSETFRAME (frame, f);
1899 call1 (Qface_set_after_frame_default, frame);
1903 void
1904 x_set_border_width (f, arg, oldval)
1905 struct frame *f;
1906 Lisp_Object arg, oldval;
1908 CHECK_NUMBER (arg, 0);
1910 if (XINT (arg) == f->output_data.x->border_width)
1911 return;
1913 if (FRAME_X_WINDOW (f) != 0)
1914 error ("Cannot change the border width of a window");
1916 f->output_data.x->border_width = XINT (arg);
1919 void
1920 x_set_internal_border_width (f, arg, oldval)
1921 struct frame *f;
1922 Lisp_Object arg, oldval;
1924 int old = f->output_data.x->internal_border_width;
1926 CHECK_NUMBER (arg, 0);
1927 f->output_data.x->internal_border_width = XINT (arg);
1928 if (f->output_data.x->internal_border_width < 0)
1929 f->output_data.x->internal_border_width = 0;
1931 #ifdef USE_X_TOOLKIT
1932 if (f->output_data.x->edit_widget)
1933 widget_store_internal_border (f->output_data.x->edit_widget);
1934 #endif
1936 if (f->output_data.x->internal_border_width == old)
1937 return;
1939 if (FRAME_X_WINDOW (f) != 0)
1941 x_set_window_size (f, 0, f->width, f->height);
1942 SET_FRAME_GARBAGED (f);
1943 do_pending_window_change (0);
1945 else
1946 SET_FRAME_GARBAGED (f);
1949 void
1950 x_set_visibility (f, value, oldval)
1951 struct frame *f;
1952 Lisp_Object value, oldval;
1954 Lisp_Object frame;
1955 XSETFRAME (frame, f);
1957 if (NILP (value))
1958 Fmake_frame_invisible (frame, Qt);
1959 else if (EQ (value, Qicon))
1960 Ficonify_frame (frame);
1961 else
1962 Fmake_frame_visible (frame);
1966 /* Change window heights in windows rooted in WINDOW by N lines. */
1968 static void
1969 x_change_window_heights (window, n)
1970 Lisp_Object window;
1971 int n;
1973 struct window *w = XWINDOW (window);
1975 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1976 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1978 if (INTEGERP (w->orig_top))
1979 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1980 if (INTEGERP (w->orig_height))
1981 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1983 /* Handle just the top child in a vertical split. */
1984 if (!NILP (w->vchild))
1985 x_change_window_heights (w->vchild, n);
1987 /* Adjust all children in a horizontal split. */
1988 for (window = w->hchild; !NILP (window); window = w->next)
1990 w = XWINDOW (window);
1991 x_change_window_heights (window, n);
1995 void
1996 x_set_menu_bar_lines (f, value, oldval)
1997 struct frame *f;
1998 Lisp_Object value, oldval;
2000 int nlines;
2001 #ifndef USE_X_TOOLKIT
2002 int olines = FRAME_MENU_BAR_LINES (f);
2003 #endif
2005 /* Right now, menu bars don't work properly in minibuf-only frames;
2006 most of the commands try to apply themselves to the minibuffer
2007 frame itself, and get an error because you can't switch buffers
2008 in or split the minibuffer window. */
2009 if (FRAME_MINIBUF_ONLY_P (f))
2010 return;
2012 if (INTEGERP (value))
2013 nlines = XINT (value);
2014 else
2015 nlines = 0;
2017 /* Make sure we redisplay all windows in this frame. */
2018 windows_or_buffers_changed++;
2020 #ifdef USE_X_TOOLKIT
2021 FRAME_MENU_BAR_LINES (f) = 0;
2022 if (nlines)
2024 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2025 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
2026 /* Make sure next redisplay shows the menu bar. */
2027 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2029 else
2031 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2032 free_frame_menubar (f);
2033 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2034 if (FRAME_X_P (f))
2035 f->output_data.x->menubar_widget = 0;
2037 #else /* not USE_X_TOOLKIT */
2038 FRAME_MENU_BAR_LINES (f) = nlines;
2039 x_change_window_heights (f->root_window, nlines - olines);
2040 #endif /* not USE_X_TOOLKIT */
2041 adjust_glyphs (f);
2045 /* Set the number of lines used for the tool bar of frame F to VALUE.
2046 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2047 is the old number of tool bar lines. This function changes the
2048 height of all windows on frame F to match the new tool bar height.
2049 The frame's height doesn't change. */
2051 void
2052 x_set_tool_bar_lines (f, value, oldval)
2053 struct frame *f;
2054 Lisp_Object value, oldval;
2056 int delta, nlines, root_height;
2057 Lisp_Object root_window;
2059 /* Treat tool bars like menu bars. */
2060 if (FRAME_MINIBUF_ONLY_P (f))
2061 return;
2063 /* Use VALUE only if an integer >= 0. */
2064 if (INTEGERP (value) && XINT (value) >= 0)
2065 nlines = XFASTINT (value);
2066 else
2067 nlines = 0;
2069 /* Make sure we redisplay all windows in this frame. */
2070 ++windows_or_buffers_changed;
2072 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2074 /* Don't resize the tool-bar to more than we have room for. */
2075 root_window = FRAME_ROOT_WINDOW (f);
2076 root_height = XINT (XWINDOW (root_window)->height);
2077 if (root_height - delta < 1)
2079 delta = root_height - 1;
2080 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2083 FRAME_TOOL_BAR_LINES (f) = nlines;
2084 x_change_window_heights (root_window, delta);
2085 adjust_glyphs (f);
2087 /* We also have to make sure that the internal border at the top of
2088 the frame, below the menu bar or tool bar, is redrawn when the
2089 tool bar disappears. This is so because the internal border is
2090 below the tool bar if one is displayed, but is below the menu bar
2091 if there isn't a tool bar. The tool bar draws into the area
2092 below the menu bar. */
2093 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2095 updating_frame = f;
2096 clear_frame ();
2097 clear_current_matrices (f);
2098 updating_frame = NULL;
2101 /* If the tool bar gets smaller, the internal border below it
2102 has to be cleared. It was formerly part of the display
2103 of the larger tool bar, and updating windows won't clear it. */
2104 if (delta < 0)
2106 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2107 int width = PIXEL_WIDTH (f);
2108 int y = nlines * CANON_Y_UNIT (f);
2110 BLOCK_INPUT;
2111 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2112 0, y, width, height, False);
2113 UNBLOCK_INPUT;
2115 if (WINDOWP (f->tool_bar_window))
2116 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2121 /* Set the foreground color for scroll bars on frame F to VALUE.
2122 VALUE should be a string, a color name. If it isn't a string or
2123 isn't a valid color name, do nothing. OLDVAL is the old value of
2124 the frame parameter. */
2126 void
2127 x_set_scroll_bar_foreground (f, value, oldval)
2128 struct frame *f;
2129 Lisp_Object value, oldval;
2131 unsigned long pixel;
2133 if (STRINGP (value))
2134 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2135 else
2136 pixel = -1;
2138 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2139 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2141 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2142 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2144 /* Remove all scroll bars because they have wrong colors. */
2145 if (condemn_scroll_bars_hook)
2146 (*condemn_scroll_bars_hook) (f);
2147 if (judge_scroll_bars_hook)
2148 (*judge_scroll_bars_hook) (f);
2150 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2151 redraw_frame (f);
2156 /* Set the background color for scroll bars on frame F to VALUE VALUE
2157 should be a string, a color name. If it isn't a string or isn't a
2158 valid color name, do nothing. OLDVAL is the old value of the frame
2159 parameter. */
2161 void
2162 x_set_scroll_bar_background (f, value, oldval)
2163 struct frame *f;
2164 Lisp_Object value, oldval;
2166 unsigned long pixel;
2168 if (STRINGP (value))
2169 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2170 else
2171 pixel = -1;
2173 if (f->output_data.x->scroll_bar_background_pixel != -1)
2174 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2176 f->output_data.x->scroll_bar_background_pixel = pixel;
2177 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2179 /* Remove all scroll bars because they have wrong colors. */
2180 if (condemn_scroll_bars_hook)
2181 (*condemn_scroll_bars_hook) (f);
2182 if (judge_scroll_bars_hook)
2183 (*judge_scroll_bars_hook) (f);
2185 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2186 redraw_frame (f);
2191 /* Encode Lisp string STRING as a text in a format appropriate for
2192 XICCC (X Inter Client Communication Conventions).
2194 If STRING contains only ASCII characters, do no conversion and
2195 return the string data of STRING. Otherwise, encode the text by
2196 CODING_SYSTEM, and return a newly allocated memory area which
2197 should be freed by `xfree' by a caller.
2199 SELECTIONP non-zero means the string is being encoded for an X
2200 selection, so it is safe to run pre-write conversions (which
2201 may run Lisp code).
2203 Store the byte length of resulting text in *TEXT_BYTES.
2205 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2206 which means that the `encoding' of the result can be `STRING'.
2207 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2208 the result should be `COMPOUND_TEXT'. */
2210 unsigned char *
2211 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
2212 Lisp_Object string, coding_system;
2213 int *text_bytes, *stringp;
2214 int selectionp;
2216 unsigned char *str = XSTRING (string)->data;
2217 int chars = XSTRING (string)->size;
2218 int bytes = STRING_BYTES (XSTRING (string));
2219 int charset_info;
2220 int bufsize;
2221 unsigned char *buf;
2222 struct coding_system coding;
2224 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2225 if (charset_info == 0)
2227 /* No multibyte character in OBJ. We need not encode it. */
2228 *text_bytes = bytes;
2229 *stringp = 1;
2230 return str;
2233 setup_coding_system (coding_system, &coding);
2234 if (selectionp
2235 && SYMBOLP (coding.pre_write_conversion)
2236 && !NILP (Ffboundp (coding.pre_write_conversion)))
2238 string = run_pre_post_conversion_on_str (string, &coding, 1);
2239 str = XSTRING (string)->data;
2240 chars = XSTRING (string)->size;
2241 bytes = STRING_BYTES (XSTRING (string));
2243 coding.src_multibyte = 1;
2244 coding.dst_multibyte = 0;
2245 coding.mode |= CODING_MODE_LAST_BLOCK;
2246 if (coding.type == coding_type_iso2022)
2247 coding.flags |= CODING_FLAG_ISO_SAFE;
2248 /* We suppress producing escape sequences for composition. */
2249 coding.composing = COMPOSITION_DISABLED;
2250 bufsize = encoding_buffer_size (&coding, bytes);
2251 buf = (unsigned char *) xmalloc (bufsize);
2252 encode_coding (&coding, str, buf, bytes, bufsize);
2253 *text_bytes = coding.produced;
2254 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2255 return buf;
2259 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2260 x_id_name.
2262 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2263 name; if NAME is a string, set F's name to NAME and set
2264 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2266 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2267 suggesting a new name, which lisp code should override; if
2268 F->explicit_name is set, ignore the new name; otherwise, set it. */
2270 void
2271 x_set_name (f, name, explicit)
2272 struct frame *f;
2273 Lisp_Object name;
2274 int explicit;
2276 /* Make sure that requests from lisp code override requests from
2277 Emacs redisplay code. */
2278 if (explicit)
2280 /* If we're switching from explicit to implicit, we had better
2281 update the mode lines and thereby update the title. */
2282 if (f->explicit_name && NILP (name))
2283 update_mode_lines = 1;
2285 f->explicit_name = ! NILP (name);
2287 else if (f->explicit_name)
2288 return;
2290 /* If NAME is nil, set the name to the x_id_name. */
2291 if (NILP (name))
2293 /* Check for no change needed in this very common case
2294 before we do any consing. */
2295 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2296 XSTRING (f->name)->data))
2297 return;
2298 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2300 else
2301 CHECK_STRING (name, 0);
2303 /* Don't change the name if it's already NAME. */
2304 if (! NILP (Fstring_equal (name, f->name)))
2305 return;
2307 f->name = name;
2309 /* For setting the frame title, the title parameter should override
2310 the name parameter. */
2311 if (! NILP (f->title))
2312 name = f->title;
2314 if (FRAME_X_WINDOW (f))
2316 BLOCK_INPUT;
2317 #ifdef HAVE_X11R4
2319 XTextProperty text, icon;
2320 int bytes, stringp;
2321 Lisp_Object coding_system;
2323 coding_system = Qcompound_text;
2324 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2325 text.encoding = (stringp ? XA_STRING
2326 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2327 text.format = 8;
2328 text.nitems = bytes;
2330 if (NILP (f->icon_name))
2332 icon = text;
2334 else
2336 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2337 &bytes, &stringp);
2338 icon.encoding = (stringp ? XA_STRING
2339 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2340 icon.format = 8;
2341 icon.nitems = bytes;
2343 #ifdef USE_X_TOOLKIT
2344 XSetWMName (FRAME_X_DISPLAY (f),
2345 XtWindow (f->output_data.x->widget), &text);
2346 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2347 &icon);
2348 #else /* not USE_X_TOOLKIT */
2349 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2350 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2351 #endif /* not USE_X_TOOLKIT */
2352 if (!NILP (f->icon_name)
2353 && icon.value != XSTRING (f->icon_name)->data)
2354 xfree (icon.value);
2355 if (text.value != XSTRING (name)->data)
2356 xfree (text.value);
2358 #else /* not HAVE_X11R4 */
2359 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2360 XSTRING (name)->data);
2361 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2362 XSTRING (name)->data);
2363 #endif /* not HAVE_X11R4 */
2364 UNBLOCK_INPUT;
2368 /* This function should be called when the user's lisp code has
2369 specified a name for the frame; the name will override any set by the
2370 redisplay code. */
2371 void
2372 x_explicitly_set_name (f, arg, oldval)
2373 FRAME_PTR f;
2374 Lisp_Object arg, oldval;
2376 x_set_name (f, arg, 1);
2379 /* This function should be called by Emacs redisplay code to set the
2380 name; names set this way will never override names set by the user's
2381 lisp code. */
2382 void
2383 x_implicitly_set_name (f, arg, oldval)
2384 FRAME_PTR f;
2385 Lisp_Object arg, oldval;
2387 x_set_name (f, arg, 0);
2390 /* Change the title of frame F to NAME.
2391 If NAME is nil, use the frame name as the title.
2393 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2394 name; if NAME is a string, set F's name to NAME and set
2395 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2397 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2398 suggesting a new name, which lisp code should override; if
2399 F->explicit_name is set, ignore the new name; otherwise, set it. */
2401 void
2402 x_set_title (f, name, old_name)
2403 struct frame *f;
2404 Lisp_Object name, old_name;
2406 /* Don't change the title if it's already NAME. */
2407 if (EQ (name, f->title))
2408 return;
2410 update_mode_lines = 1;
2412 f->title = name;
2414 if (NILP (name))
2415 name = f->name;
2416 else
2417 CHECK_STRING (name, 0);
2419 if (FRAME_X_WINDOW (f))
2421 BLOCK_INPUT;
2422 #ifdef HAVE_X11R4
2424 XTextProperty text, icon;
2425 int bytes, stringp;
2426 Lisp_Object coding_system;
2428 coding_system = Qcompound_text;
2429 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2430 text.encoding = (stringp ? XA_STRING
2431 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2432 text.format = 8;
2433 text.nitems = bytes;
2435 if (NILP (f->icon_name))
2437 icon = text;
2439 else
2441 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2442 &bytes, &stringp);
2443 icon.encoding = (stringp ? XA_STRING
2444 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2445 icon.format = 8;
2446 icon.nitems = bytes;
2448 #ifdef USE_X_TOOLKIT
2449 XSetWMName (FRAME_X_DISPLAY (f),
2450 XtWindow (f->output_data.x->widget), &text);
2451 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2452 &icon);
2453 #else /* not USE_X_TOOLKIT */
2454 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2455 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2456 #endif /* not USE_X_TOOLKIT */
2457 if (!NILP (f->icon_name)
2458 && icon.value != XSTRING (f->icon_name)->data)
2459 xfree (icon.value);
2460 if (text.value != XSTRING (name)->data)
2461 xfree (text.value);
2463 #else /* not HAVE_X11R4 */
2464 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2465 XSTRING (name)->data);
2466 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2467 XSTRING (name)->data);
2468 #endif /* not HAVE_X11R4 */
2469 UNBLOCK_INPUT;
2473 void
2474 x_set_autoraise (f, arg, oldval)
2475 struct frame *f;
2476 Lisp_Object arg, oldval;
2478 f->auto_raise = !EQ (Qnil, arg);
2481 void
2482 x_set_autolower (f, arg, oldval)
2483 struct frame *f;
2484 Lisp_Object arg, oldval;
2486 f->auto_lower = !EQ (Qnil, arg);
2489 void
2490 x_set_unsplittable (f, arg, oldval)
2491 struct frame *f;
2492 Lisp_Object arg, oldval;
2494 f->no_split = !NILP (arg);
2497 void
2498 x_set_vertical_scroll_bars (f, arg, oldval)
2499 struct frame *f;
2500 Lisp_Object arg, oldval;
2502 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2503 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2504 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2505 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2507 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2508 = (NILP (arg)
2509 ? vertical_scroll_bar_none
2510 : EQ (Qright, arg)
2511 ? vertical_scroll_bar_right
2512 : vertical_scroll_bar_left);
2514 /* We set this parameter before creating the X window for the
2515 frame, so we can get the geometry right from the start.
2516 However, if the window hasn't been created yet, we shouldn't
2517 call x_set_window_size. */
2518 if (FRAME_X_WINDOW (f))
2519 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2520 do_pending_window_change (0);
2524 void
2525 x_set_scroll_bar_width (f, arg, oldval)
2526 struct frame *f;
2527 Lisp_Object arg, oldval;
2529 int wid = FONT_WIDTH (f->output_data.x->font);
2531 if (NILP (arg))
2533 #ifdef USE_TOOLKIT_SCROLL_BARS
2534 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2535 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2536 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2537 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2538 #else
2539 /* Make the actual width at least 14 pixels and a multiple of a
2540 character width. */
2541 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2543 /* Use all of that space (aside from required margins) for the
2544 scroll bar. */
2545 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2546 #endif
2548 if (FRAME_X_WINDOW (f))
2549 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2550 do_pending_window_change (0);
2552 else if (INTEGERP (arg) && XINT (arg) > 0
2553 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2555 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2556 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2558 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2559 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2560 if (FRAME_X_WINDOW (f))
2561 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2564 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2565 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2566 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2571 /* Subroutines of creating an X frame. */
2573 /* Make sure that Vx_resource_name is set to a reasonable value.
2574 Fix it up, or set it to `emacs' if it is too hopeless. */
2576 static void
2577 validate_x_resource_name ()
2579 int len = 0;
2580 /* Number of valid characters in the resource name. */
2581 int good_count = 0;
2582 /* Number of invalid characters in the resource name. */
2583 int bad_count = 0;
2584 Lisp_Object new;
2585 int i;
2587 if (!STRINGP (Vx_resource_class))
2588 Vx_resource_class = build_string (EMACS_CLASS);
2590 if (STRINGP (Vx_resource_name))
2592 unsigned char *p = XSTRING (Vx_resource_name)->data;
2593 int i;
2595 len = STRING_BYTES (XSTRING (Vx_resource_name));
2597 /* Only letters, digits, - and _ are valid in resource names.
2598 Count the valid characters and count the invalid ones. */
2599 for (i = 0; i < len; i++)
2601 int c = p[i];
2602 if (! ((c >= 'a' && c <= 'z')
2603 || (c >= 'A' && c <= 'Z')
2604 || (c >= '0' && c <= '9')
2605 || c == '-' || c == '_'))
2606 bad_count++;
2607 else
2608 good_count++;
2611 else
2612 /* Not a string => completely invalid. */
2613 bad_count = 5, good_count = 0;
2615 /* If name is valid already, return. */
2616 if (bad_count == 0)
2617 return;
2619 /* If name is entirely invalid, or nearly so, use `emacs'. */
2620 if (good_count == 0
2621 || (good_count == 1 && bad_count > 0))
2623 Vx_resource_name = build_string ("emacs");
2624 return;
2627 /* Name is partly valid. Copy it and replace the invalid characters
2628 with underscores. */
2630 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2632 for (i = 0; i < len; i++)
2634 int c = XSTRING (new)->data[i];
2635 if (! ((c >= 'a' && c <= 'z')
2636 || (c >= 'A' && c <= 'Z')
2637 || (c >= '0' && c <= '9')
2638 || c == '-' || c == '_'))
2639 XSTRING (new)->data[i] = '_';
2644 extern char *x_get_string_resource ();
2646 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2647 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2648 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2649 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2650 the name specified by the `-name' or `-rn' command-line arguments.\n\
2652 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2653 class, respectively. You must specify both of them or neither.\n\
2654 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2655 and the class is `Emacs.CLASS.SUBCLASS'.")
2656 (attribute, class, component, subclass)
2657 Lisp_Object attribute, class, component, subclass;
2659 register char *value;
2660 char *name_key;
2661 char *class_key;
2663 check_x ();
2665 CHECK_STRING (attribute, 0);
2666 CHECK_STRING (class, 0);
2668 if (!NILP (component))
2669 CHECK_STRING (component, 1);
2670 if (!NILP (subclass))
2671 CHECK_STRING (subclass, 2);
2672 if (NILP (component) != NILP (subclass))
2673 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2675 validate_x_resource_name ();
2677 /* Allocate space for the components, the dots which separate them,
2678 and the final '\0'. Make them big enough for the worst case. */
2679 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2680 + (STRINGP (component)
2681 ? STRING_BYTES (XSTRING (component)) : 0)
2682 + STRING_BYTES (XSTRING (attribute))
2683 + 3);
2685 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2686 + STRING_BYTES (XSTRING (class))
2687 + (STRINGP (subclass)
2688 ? STRING_BYTES (XSTRING (subclass)) : 0)
2689 + 3);
2691 /* Start with emacs.FRAMENAME for the name (the specific one)
2692 and with `Emacs' for the class key (the general one). */
2693 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2694 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2696 strcat (class_key, ".");
2697 strcat (class_key, XSTRING (class)->data);
2699 if (!NILP (component))
2701 strcat (class_key, ".");
2702 strcat (class_key, XSTRING (subclass)->data);
2704 strcat (name_key, ".");
2705 strcat (name_key, XSTRING (component)->data);
2708 strcat (name_key, ".");
2709 strcat (name_key, XSTRING (attribute)->data);
2711 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2712 name_key, class_key);
2714 if (value != (char *) 0)
2715 return build_string (value);
2716 else
2717 return Qnil;
2720 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2722 Lisp_Object
2723 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2724 struct x_display_info *dpyinfo;
2725 Lisp_Object attribute, class, component, subclass;
2727 register char *value;
2728 char *name_key;
2729 char *class_key;
2731 CHECK_STRING (attribute, 0);
2732 CHECK_STRING (class, 0);
2734 if (!NILP (component))
2735 CHECK_STRING (component, 1);
2736 if (!NILP (subclass))
2737 CHECK_STRING (subclass, 2);
2738 if (NILP (component) != NILP (subclass))
2739 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2741 validate_x_resource_name ();
2743 /* Allocate space for the components, the dots which separate them,
2744 and the final '\0'. Make them big enough for the worst case. */
2745 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2746 + (STRINGP (component)
2747 ? STRING_BYTES (XSTRING (component)) : 0)
2748 + STRING_BYTES (XSTRING (attribute))
2749 + 3);
2751 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2752 + STRING_BYTES (XSTRING (class))
2753 + (STRINGP (subclass)
2754 ? STRING_BYTES (XSTRING (subclass)) : 0)
2755 + 3);
2757 /* Start with emacs.FRAMENAME for the name (the specific one)
2758 and with `Emacs' for the class key (the general one). */
2759 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2760 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2762 strcat (class_key, ".");
2763 strcat (class_key, XSTRING (class)->data);
2765 if (!NILP (component))
2767 strcat (class_key, ".");
2768 strcat (class_key, XSTRING (subclass)->data);
2770 strcat (name_key, ".");
2771 strcat (name_key, XSTRING (component)->data);
2774 strcat (name_key, ".");
2775 strcat (name_key, XSTRING (attribute)->data);
2777 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2779 if (value != (char *) 0)
2780 return build_string (value);
2781 else
2782 return Qnil;
2785 /* Used when C code wants a resource value. */
2787 char *
2788 x_get_resource_string (attribute, class)
2789 char *attribute, *class;
2791 char *name_key;
2792 char *class_key;
2793 struct frame *sf = SELECTED_FRAME ();
2795 /* Allocate space for the components, the dots which separate them,
2796 and the final '\0'. */
2797 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2798 + strlen (attribute) + 2);
2799 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2800 + strlen (class) + 2);
2802 sprintf (name_key, "%s.%s",
2803 XSTRING (Vinvocation_name)->data,
2804 attribute);
2805 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2807 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2808 name_key, class_key);
2811 /* Types we might convert a resource string into. */
2812 enum resource_types
2814 RES_TYPE_NUMBER,
2815 RES_TYPE_FLOAT,
2816 RES_TYPE_BOOLEAN,
2817 RES_TYPE_STRING,
2818 RES_TYPE_SYMBOL
2821 /* Return the value of parameter PARAM.
2823 First search ALIST, then Vdefault_frame_alist, then the X defaults
2824 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2826 Convert the resource to the type specified by desired_type.
2828 If no default is specified, return Qunbound. If you call
2829 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2830 and don't let it get stored in any Lisp-visible variables! */
2832 static Lisp_Object
2833 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2834 struct x_display_info *dpyinfo;
2835 Lisp_Object alist, param;
2836 char *attribute;
2837 char *class;
2838 enum resource_types type;
2840 register Lisp_Object tem;
2842 tem = Fassq (param, alist);
2843 if (EQ (tem, Qnil))
2844 tem = Fassq (param, Vdefault_frame_alist);
2845 if (EQ (tem, Qnil))
2848 if (attribute)
2850 tem = display_x_get_resource (dpyinfo,
2851 build_string (attribute),
2852 build_string (class),
2853 Qnil, Qnil);
2855 if (NILP (tem))
2856 return Qunbound;
2858 switch (type)
2860 case RES_TYPE_NUMBER:
2861 return make_number (atoi (XSTRING (tem)->data));
2863 case RES_TYPE_FLOAT:
2864 return make_float (atof (XSTRING (tem)->data));
2866 case RES_TYPE_BOOLEAN:
2867 tem = Fdowncase (tem);
2868 if (!strcmp (XSTRING (tem)->data, "on")
2869 || !strcmp (XSTRING (tem)->data, "true"))
2870 return Qt;
2871 else
2872 return Qnil;
2874 case RES_TYPE_STRING:
2875 return tem;
2877 case RES_TYPE_SYMBOL:
2878 /* As a special case, we map the values `true' and `on'
2879 to Qt, and `false' and `off' to Qnil. */
2881 Lisp_Object lower;
2882 lower = Fdowncase (tem);
2883 if (!strcmp (XSTRING (lower)->data, "on")
2884 || !strcmp (XSTRING (lower)->data, "true"))
2885 return Qt;
2886 else if (!strcmp (XSTRING (lower)->data, "off")
2887 || !strcmp (XSTRING (lower)->data, "false"))
2888 return Qnil;
2889 else
2890 return Fintern (tem, Qnil);
2893 default:
2894 abort ();
2897 else
2898 return Qunbound;
2900 return Fcdr (tem);
2903 /* Like x_get_arg, but also record the value in f->param_alist. */
2905 static Lisp_Object
2906 x_get_and_record_arg (f, alist, param, attribute, class, type)
2907 struct frame *f;
2908 Lisp_Object alist, param;
2909 char *attribute;
2910 char *class;
2911 enum resource_types type;
2913 Lisp_Object value;
2915 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2916 attribute, class, type);
2917 if (! NILP (value))
2918 store_frame_param (f, param, value);
2920 return value;
2923 /* Record in frame F the specified or default value according to ALIST
2924 of the parameter named PROP (a Lisp symbol).
2925 If no value is specified for PROP, look for an X default for XPROP
2926 on the frame named NAME.
2927 If that is not found either, use the value DEFLT. */
2929 static Lisp_Object
2930 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2931 struct frame *f;
2932 Lisp_Object alist;
2933 Lisp_Object prop;
2934 Lisp_Object deflt;
2935 char *xprop;
2936 char *xclass;
2937 enum resource_types type;
2939 Lisp_Object tem;
2941 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2942 if (EQ (tem, Qunbound))
2943 tem = deflt;
2944 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2945 return tem;
2949 /* Record in frame F the specified or default value according to ALIST
2950 of the parameter named PROP (a Lisp symbol). If no value is
2951 specified for PROP, look for an X default for XPROP on the frame
2952 named NAME. If that is not found either, use the value DEFLT. */
2954 static Lisp_Object
2955 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2956 foreground_p)
2957 struct frame *f;
2958 Lisp_Object alist;
2959 Lisp_Object prop;
2960 char *xprop;
2961 char *xclass;
2962 int foreground_p;
2964 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2965 Lisp_Object tem;
2967 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2968 if (EQ (tem, Qunbound))
2970 #ifdef USE_TOOLKIT_SCROLL_BARS
2972 /* See if an X resource for the scroll bar color has been
2973 specified. */
2974 tem = display_x_get_resource (dpyinfo,
2975 build_string (foreground_p
2976 ? "foreground"
2977 : "background"),
2978 build_string (""),
2979 build_string ("verticalScrollBar"),
2980 build_string (""));
2981 if (!STRINGP (tem))
2983 /* If nothing has been specified, scroll bars will use a
2984 toolkit-dependent default. Because these defaults are
2985 difficult to get at without actually creating a scroll
2986 bar, use nil to indicate that no color has been
2987 specified. */
2988 tem = Qnil;
2991 #else /* not USE_TOOLKIT_SCROLL_BARS */
2993 tem = Qnil;
2995 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2998 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2999 return tem;
3004 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3005 "Parse an X-style geometry string STRING.\n\
3006 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
3007 The properties returned may include `top', `left', `height', and `width'.\n\
3008 The value of `left' or `top' may be an integer,\n\
3009 or a list (+ N) meaning N pixels relative to top/left corner,\n\
3010 or a list (- N) meaning -N pixels relative to bottom/right corner.")
3011 (string)
3012 Lisp_Object string;
3014 int geometry, x, y;
3015 unsigned int width, height;
3016 Lisp_Object result;
3018 CHECK_STRING (string, 0);
3020 geometry = XParseGeometry ((char *) XSTRING (string)->data,
3021 &x, &y, &width, &height);
3023 #if 0
3024 if (!!(geometry & XValue) != !!(geometry & YValue))
3025 error ("Must specify both x and y position, or neither");
3026 #endif
3028 result = Qnil;
3029 if (geometry & XValue)
3031 Lisp_Object element;
3033 if (x >= 0 && (geometry & XNegative))
3034 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3035 else if (x < 0 && ! (geometry & XNegative))
3036 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3037 else
3038 element = Fcons (Qleft, make_number (x));
3039 result = Fcons (element, result);
3042 if (geometry & YValue)
3044 Lisp_Object element;
3046 if (y >= 0 && (geometry & YNegative))
3047 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3048 else if (y < 0 && ! (geometry & YNegative))
3049 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3050 else
3051 element = Fcons (Qtop, make_number (y));
3052 result = Fcons (element, result);
3055 if (geometry & WidthValue)
3056 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3057 if (geometry & HeightValue)
3058 result = Fcons (Fcons (Qheight, make_number (height)), result);
3060 return result;
3063 /* Calculate the desired size and position of this window,
3064 and return the flags saying which aspects were specified.
3066 This function does not make the coordinates positive. */
3068 #define DEFAULT_ROWS 40
3069 #define DEFAULT_COLS 80
3071 static int
3072 x_figure_window_size (f, parms)
3073 struct frame *f;
3074 Lisp_Object parms;
3076 register Lisp_Object tem0, tem1, tem2;
3077 long window_prompting = 0;
3078 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3080 /* Default values if we fall through.
3081 Actually, if that happens we should get
3082 window manager prompting. */
3083 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3084 f->height = DEFAULT_ROWS;
3085 /* Window managers expect that if program-specified
3086 positions are not (0,0), they're intentional, not defaults. */
3087 f->output_data.x->top_pos = 0;
3088 f->output_data.x->left_pos = 0;
3090 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3091 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3092 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3093 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3095 if (!EQ (tem0, Qunbound))
3097 CHECK_NUMBER (tem0, 0);
3098 f->height = XINT (tem0);
3100 if (!EQ (tem1, Qunbound))
3102 CHECK_NUMBER (tem1, 0);
3103 SET_FRAME_WIDTH (f, XINT (tem1));
3105 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3106 window_prompting |= USSize;
3107 else
3108 window_prompting |= PSize;
3111 f->output_data.x->vertical_scroll_bar_extra
3112 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3114 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3115 f->output_data.x->flags_areas_extra
3116 = FRAME_FLAGS_AREA_WIDTH (f);
3117 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3118 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3120 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3121 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3122 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3123 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3125 if (EQ (tem0, Qminus))
3127 f->output_data.x->top_pos = 0;
3128 window_prompting |= YNegative;
3130 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3131 && CONSP (XCDR (tem0))
3132 && INTEGERP (XCAR (XCDR (tem0))))
3134 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3135 window_prompting |= YNegative;
3137 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3138 && CONSP (XCDR (tem0))
3139 && INTEGERP (XCAR (XCDR (tem0))))
3141 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3143 else if (EQ (tem0, Qunbound))
3144 f->output_data.x->top_pos = 0;
3145 else
3147 CHECK_NUMBER (tem0, 0);
3148 f->output_data.x->top_pos = XINT (tem0);
3149 if (f->output_data.x->top_pos < 0)
3150 window_prompting |= YNegative;
3153 if (EQ (tem1, Qminus))
3155 f->output_data.x->left_pos = 0;
3156 window_prompting |= XNegative;
3158 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3159 && CONSP (XCDR (tem1))
3160 && INTEGERP (XCAR (XCDR (tem1))))
3162 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3163 window_prompting |= XNegative;
3165 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3166 && CONSP (XCDR (tem1))
3167 && INTEGERP (XCAR (XCDR (tem1))))
3169 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3171 else if (EQ (tem1, Qunbound))
3172 f->output_data.x->left_pos = 0;
3173 else
3175 CHECK_NUMBER (tem1, 0);
3176 f->output_data.x->left_pos = XINT (tem1);
3177 if (f->output_data.x->left_pos < 0)
3178 window_prompting |= XNegative;
3181 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3182 window_prompting |= USPosition;
3183 else
3184 window_prompting |= PPosition;
3187 return window_prompting;
3190 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3192 Status
3193 XSetWMProtocols (dpy, w, protocols, count)
3194 Display *dpy;
3195 Window w;
3196 Atom *protocols;
3197 int count;
3199 Atom prop;
3200 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3201 if (prop == None) return False;
3202 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3203 (unsigned char *) protocols, count);
3204 return True;
3206 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3208 #ifdef USE_X_TOOLKIT
3210 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3211 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3212 already be present because of the toolkit (Motif adds some of them,
3213 for example, but Xt doesn't). */
3215 static void
3216 hack_wm_protocols (f, widget)
3217 FRAME_PTR f;
3218 Widget widget;
3220 Display *dpy = XtDisplay (widget);
3221 Window w = XtWindow (widget);
3222 int need_delete = 1;
3223 int need_focus = 1;
3224 int need_save = 1;
3226 BLOCK_INPUT;
3228 Atom type, *atoms = 0;
3229 int format = 0;
3230 unsigned long nitems = 0;
3231 unsigned long bytes_after;
3233 if ((XGetWindowProperty (dpy, w,
3234 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3235 (long)0, (long)100, False, XA_ATOM,
3236 &type, &format, &nitems, &bytes_after,
3237 (unsigned char **) &atoms)
3238 == Success)
3239 && format == 32 && type == XA_ATOM)
3240 while (nitems > 0)
3242 nitems--;
3243 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3244 need_delete = 0;
3245 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3246 need_focus = 0;
3247 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3248 need_save = 0;
3250 if (atoms) XFree ((char *) atoms);
3253 Atom props [10];
3254 int count = 0;
3255 if (need_delete)
3256 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3257 if (need_focus)
3258 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3259 if (need_save)
3260 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3261 if (count)
3262 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3263 XA_ATOM, 32, PropModeAppend,
3264 (unsigned char *) props, count);
3266 UNBLOCK_INPUT;
3268 #endif
3272 /* Support routines for XIC (X Input Context). */
3274 #ifdef HAVE_X_I18N
3276 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3277 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3280 /* Supported XIM styles, ordered by preferenc. */
3282 static XIMStyle supported_xim_styles[] =
3284 XIMPreeditPosition | XIMStatusArea,
3285 XIMPreeditPosition | XIMStatusNothing,
3286 XIMPreeditPosition | XIMStatusNone,
3287 XIMPreeditNothing | XIMStatusArea,
3288 XIMPreeditNothing | XIMStatusNothing,
3289 XIMPreeditNothing | XIMStatusNone,
3290 XIMPreeditNone | XIMStatusArea,
3291 XIMPreeditNone | XIMStatusNothing,
3292 XIMPreeditNone | XIMStatusNone,
3297 /* Create an X fontset on frame F with base font name
3298 BASE_FONTNAME.. */
3300 static XFontSet
3301 xic_create_xfontset (f, base_fontname)
3302 struct frame *f;
3303 char *base_fontname;
3305 XFontSet xfs;
3306 char **missing_list;
3307 int missing_count;
3308 char *def_string;
3310 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3311 base_fontname, &missing_list,
3312 &missing_count, &def_string);
3313 if (missing_list)
3314 XFreeStringList (missing_list);
3316 /* No need to free def_string. */
3317 return xfs;
3321 /* Value is the best input style, given user preferences USER (already
3322 checked to be supported by Emacs), and styles supported by the
3323 input method XIM. */
3325 static XIMStyle
3326 best_xim_style (user, xim)
3327 XIMStyles *user;
3328 XIMStyles *xim;
3330 int i, j;
3332 for (i = 0; i < user->count_styles; ++i)
3333 for (j = 0; j < xim->count_styles; ++j)
3334 if (user->supported_styles[i] == xim->supported_styles[j])
3335 return user->supported_styles[i];
3337 /* Return the default style. */
3338 return XIMPreeditNothing | XIMStatusNothing;
3341 /* Create XIC for frame F. */
3343 static XIMStyle xic_style;
3345 void
3346 create_frame_xic (f)
3347 struct frame *f;
3349 XIM xim;
3350 XIC xic = NULL;
3351 XFontSet xfs = NULL;
3353 if (FRAME_XIC (f))
3354 return;
3356 xim = FRAME_X_XIM (f);
3357 if (xim)
3359 XRectangle s_area;
3360 XPoint spot;
3361 XVaNestedList preedit_attr;
3362 XVaNestedList status_attr;
3363 char *base_fontname;
3364 int fontset;
3366 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3367 spot.x = 0; spot.y = 1;
3368 /* Create X fontset. */
3369 fontset = FRAME_FONTSET (f);
3370 if (fontset < 0)
3371 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3372 else
3374 /* Determine the base fontname from the ASCII font name of
3375 FONTSET. */
3376 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3377 char *p = ascii_font;
3378 int i;
3380 for (i = 0; *p; p++)
3381 if (*p == '-') i++;
3382 if (i != 14)
3383 /* As the font name doesn't conform to XLFD, we can't
3384 modify it to get a suitable base fontname for the
3385 frame. */
3386 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3387 else
3389 int len = strlen (ascii_font) + 1;
3390 char *p1 = NULL;
3392 for (i = 0, p = ascii_font; i < 8; p++)
3394 if (*p == '-')
3396 i++;
3397 if (i == 3)
3398 p1 = p + 1;
3401 base_fontname = (char *) alloca (len);
3402 bzero (base_fontname, len);
3403 strcpy (base_fontname, "-*-*-");
3404 bcopy (p1, base_fontname + 5, p - p1);
3405 strcat (base_fontname, "*-*-*-*-*-*-*");
3408 xfs = xic_create_xfontset (f, base_fontname);
3410 /* Determine XIC style. */
3411 if (xic_style == 0)
3413 XIMStyles supported_list;
3414 supported_list.count_styles = (sizeof supported_xim_styles
3415 / sizeof supported_xim_styles[0]);
3416 supported_list.supported_styles = supported_xim_styles;
3417 xic_style = best_xim_style (&supported_list,
3418 FRAME_X_XIM_STYLES (f));
3421 preedit_attr = XVaCreateNestedList (0,
3422 XNFontSet, xfs,
3423 XNForeground,
3424 FRAME_FOREGROUND_PIXEL (f),
3425 XNBackground,
3426 FRAME_BACKGROUND_PIXEL (f),
3427 (xic_style & XIMPreeditPosition
3428 ? XNSpotLocation
3429 : NULL),
3430 &spot,
3431 NULL);
3432 status_attr = XVaCreateNestedList (0,
3433 XNArea,
3434 &s_area,
3435 XNFontSet,
3436 xfs,
3437 XNForeground,
3438 FRAME_FOREGROUND_PIXEL (f),
3439 XNBackground,
3440 FRAME_BACKGROUND_PIXEL (f),
3441 NULL);
3443 xic = XCreateIC (xim,
3444 XNInputStyle, xic_style,
3445 XNClientWindow, FRAME_X_WINDOW(f),
3446 XNFocusWindow, FRAME_X_WINDOW(f),
3447 XNStatusAttributes, status_attr,
3448 XNPreeditAttributes, preedit_attr,
3449 NULL);
3450 XFree (preedit_attr);
3451 XFree (status_attr);
3454 FRAME_XIC (f) = xic;
3455 FRAME_XIC_STYLE (f) = xic_style;
3456 FRAME_XIC_FONTSET (f) = xfs;
3460 /* Destroy XIC and free XIC fontset of frame F, if any. */
3462 void
3463 free_frame_xic (f)
3464 struct frame *f;
3466 if (FRAME_XIC (f) == NULL)
3467 return;
3469 XDestroyIC (FRAME_XIC (f));
3470 if (FRAME_XIC_FONTSET (f))
3471 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3473 FRAME_XIC (f) = NULL;
3474 FRAME_XIC_FONTSET (f) = NULL;
3478 /* Place preedit area for XIC of window W's frame to specified
3479 pixel position X/Y. X and Y are relative to window W. */
3481 void
3482 xic_set_preeditarea (w, x, y)
3483 struct window *w;
3484 int x, y;
3486 struct frame *f = XFRAME (w->frame);
3487 XVaNestedList attr;
3488 XPoint spot;
3490 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3491 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3492 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3493 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3494 XFree (attr);
3498 /* Place status area for XIC in bottom right corner of frame F.. */
3500 void
3501 xic_set_statusarea (f)
3502 struct frame *f;
3504 XIC xic = FRAME_XIC (f);
3505 XVaNestedList attr;
3506 XRectangle area;
3507 XRectangle *needed;
3509 /* Negotiate geometry of status area. If input method has existing
3510 status area, use its current size. */
3511 area.x = area.y = area.width = area.height = 0;
3512 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3513 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3514 XFree (attr);
3516 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3517 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3518 XFree (attr);
3520 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3522 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3523 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3524 XFree (attr);
3527 area.width = needed->width;
3528 area.height = needed->height;
3529 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3530 area.y = (PIXEL_HEIGHT (f) - area.height
3531 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3532 XFree (needed);
3534 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3535 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3536 XFree (attr);
3540 /* Set X fontset for XIC of frame F, using base font name
3541 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3543 void
3544 xic_set_xfontset (f, base_fontname)
3545 struct frame *f;
3546 char *base_fontname;
3548 XVaNestedList attr;
3549 XFontSet xfs;
3551 xfs = xic_create_xfontset (f, base_fontname);
3553 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3554 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3555 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3556 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3557 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3558 XFree (attr);
3560 if (FRAME_XIC_FONTSET (f))
3561 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3562 FRAME_XIC_FONTSET (f) = xfs;
3565 #endif /* HAVE_X_I18N */
3569 #ifdef USE_X_TOOLKIT
3571 /* Create and set up the X widget for frame F. */
3573 static void
3574 x_window (f, window_prompting, minibuffer_only)
3575 struct frame *f;
3576 long window_prompting;
3577 int minibuffer_only;
3579 XClassHint class_hints;
3580 XSetWindowAttributes attributes;
3581 unsigned long attribute_mask;
3582 Widget shell_widget;
3583 Widget pane_widget;
3584 Widget frame_widget;
3585 Arg al [25];
3586 int ac;
3588 BLOCK_INPUT;
3590 /* Use the resource name as the top-level widget name
3591 for looking up resources. Make a non-Lisp copy
3592 for the window manager, so GC relocation won't bother it.
3594 Elsewhere we specify the window name for the window manager. */
3597 char *str = (char *) XSTRING (Vx_resource_name)->data;
3598 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3599 strcpy (f->namebuf, str);
3602 ac = 0;
3603 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3604 XtSetArg (al[ac], XtNinput, 1); ac++;
3605 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3606 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3607 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3608 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3609 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3610 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3611 applicationShellWidgetClass,
3612 FRAME_X_DISPLAY (f), al, ac);
3614 f->output_data.x->widget = shell_widget;
3615 /* maybe_set_screen_title_format (shell_widget); */
3617 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3618 (widget_value *) NULL,
3619 shell_widget, False,
3620 (lw_callback) NULL,
3621 (lw_callback) NULL,
3622 (lw_callback) NULL,
3623 (lw_callback) NULL);
3625 ac = 0;
3626 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3627 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3628 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3629 XtSetValues (pane_widget, al, ac);
3630 f->output_data.x->column_widget = pane_widget;
3632 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3633 the emacs screen when changing menubar. This reduces flickering. */
3635 ac = 0;
3636 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3637 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3638 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3639 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3640 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3641 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3642 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3643 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3644 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3645 al, ac);
3647 f->output_data.x->edit_widget = frame_widget;
3649 XtManageChild (frame_widget);
3651 /* Do some needed geometry management. */
3653 int len;
3654 char *tem, shell_position[32];
3655 Arg al[2];
3656 int ac = 0;
3657 int extra_borders = 0;
3658 int menubar_size
3659 = (f->output_data.x->menubar_widget
3660 ? (f->output_data.x->menubar_widget->core.height
3661 + f->output_data.x->menubar_widget->core.border_width)
3662 : 0);
3664 #if 0 /* Experimentally, we now get the right results
3665 for -geometry -0-0 without this. 24 Aug 96, rms. */
3666 if (FRAME_EXTERNAL_MENU_BAR (f))
3668 Dimension ibw = 0;
3669 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3670 menubar_size += ibw;
3672 #endif
3674 f->output_data.x->menubar_height = menubar_size;
3676 #ifndef USE_LUCID
3677 /* Motif seems to need this amount added to the sizes
3678 specified for the shell widget. The Athena/Lucid widgets don't.
3679 Both conclusions reached experimentally. -- rms. */
3680 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3681 &extra_borders, NULL);
3682 extra_borders *= 2;
3683 #endif
3685 /* Convert our geometry parameters into a geometry string
3686 and specify it.
3687 Note that we do not specify here whether the position
3688 is a user-specified or program-specified one.
3689 We pass that information later, in x_wm_set_size_hints. */
3691 int left = f->output_data.x->left_pos;
3692 int xneg = window_prompting & XNegative;
3693 int top = f->output_data.x->top_pos;
3694 int yneg = window_prompting & YNegative;
3695 if (xneg)
3696 left = -left;
3697 if (yneg)
3698 top = -top;
3700 if (window_prompting & USPosition)
3701 sprintf (shell_position, "=%dx%d%c%d%c%d",
3702 PIXEL_WIDTH (f) + extra_borders,
3703 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3704 (xneg ? '-' : '+'), left,
3705 (yneg ? '-' : '+'), top);
3706 else
3707 sprintf (shell_position, "=%dx%d",
3708 PIXEL_WIDTH (f) + extra_borders,
3709 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3712 len = strlen (shell_position) + 1;
3713 /* We don't free this because we don't know whether
3714 it is safe to free it while the frame exists.
3715 It isn't worth the trouble of arranging to free it
3716 when the frame is deleted. */
3717 tem = (char *) xmalloc (len);
3718 strncpy (tem, shell_position, len);
3719 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3720 XtSetValues (shell_widget, al, ac);
3723 XtManageChild (pane_widget);
3724 XtRealizeWidget (shell_widget);
3726 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3728 validate_x_resource_name ();
3730 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3731 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3732 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3734 #ifdef HAVE_X_I18N
3735 FRAME_XIC (f) = NULL;
3736 #ifdef USE_XIM
3737 create_frame_xic (f);
3738 #endif
3739 #endif
3741 f->output_data.x->wm_hints.input = True;
3742 f->output_data.x->wm_hints.flags |= InputHint;
3743 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3744 &f->output_data.x->wm_hints);
3746 hack_wm_protocols (f, shell_widget);
3748 #ifdef HACK_EDITRES
3749 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3750 #endif
3752 /* Do a stupid property change to force the server to generate a
3753 PropertyNotify event so that the event_stream server timestamp will
3754 be initialized to something relevant to the time we created the window.
3756 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3757 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3758 XA_ATOM, 32, PropModeAppend,
3759 (unsigned char*) NULL, 0);
3761 /* Make all the standard events reach the Emacs frame. */
3762 attributes.event_mask = STANDARD_EVENT_SET;
3764 #ifdef HAVE_X_I18N
3765 if (FRAME_XIC (f))
3767 /* XIM server might require some X events. */
3768 unsigned long fevent = NoEventMask;
3769 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3770 attributes.event_mask |= fevent;
3772 #endif /* HAVE_X_I18N */
3774 attribute_mask = CWEventMask;
3775 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3776 attribute_mask, &attributes);
3778 XtMapWidget (frame_widget);
3780 /* x_set_name normally ignores requests to set the name if the
3781 requested name is the same as the current name. This is the one
3782 place where that assumption isn't correct; f->name is set, but
3783 the X server hasn't been told. */
3785 Lisp_Object name;
3786 int explicit = f->explicit_name;
3788 f->explicit_name = 0;
3789 name = f->name;
3790 f->name = Qnil;
3791 x_set_name (f, name, explicit);
3794 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3795 f->output_data.x->text_cursor);
3797 UNBLOCK_INPUT;
3799 /* This is a no-op, except under Motif. Make sure main areas are
3800 set to something reasonable, in case we get an error later. */
3801 lw_set_main_areas (pane_widget, 0, frame_widget);
3804 #else /* not USE_X_TOOLKIT */
3806 /* Create and set up the X window for frame F. */
3808 void
3809 x_window (f)
3810 struct frame *f;
3813 XClassHint class_hints;
3814 XSetWindowAttributes attributes;
3815 unsigned long attribute_mask;
3817 attributes.background_pixel = f->output_data.x->background_pixel;
3818 attributes.border_pixel = f->output_data.x->border_pixel;
3819 attributes.bit_gravity = StaticGravity;
3820 attributes.backing_store = NotUseful;
3821 attributes.save_under = True;
3822 attributes.event_mask = STANDARD_EVENT_SET;
3823 attributes.colormap = FRAME_X_COLORMAP (f);
3824 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3825 | CWColormap);
3827 BLOCK_INPUT;
3828 FRAME_X_WINDOW (f)
3829 = XCreateWindow (FRAME_X_DISPLAY (f),
3830 f->output_data.x->parent_desc,
3831 f->output_data.x->left_pos,
3832 f->output_data.x->top_pos,
3833 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3834 f->output_data.x->border_width,
3835 CopyFromParent, /* depth */
3836 InputOutput, /* class */
3837 FRAME_X_VISUAL (f),
3838 attribute_mask, &attributes);
3840 #ifdef HAVE_X_I18N
3841 #ifdef USE_XIM
3842 create_frame_xic (f);
3843 if (FRAME_XIC (f))
3845 /* XIM server might require some X events. */
3846 unsigned long fevent = NoEventMask;
3847 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3848 attributes.event_mask |= fevent;
3849 attribute_mask = CWEventMask;
3850 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3851 attribute_mask, &attributes);
3853 #endif
3854 #endif /* HAVE_X_I18N */
3856 validate_x_resource_name ();
3858 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3859 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3860 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3862 /* The menubar is part of the ordinary display;
3863 it does not count in addition to the height of the window. */
3864 f->output_data.x->menubar_height = 0;
3866 /* This indicates that we use the "Passive Input" input model.
3867 Unless we do this, we don't get the Focus{In,Out} events that we
3868 need to draw the cursor correctly. Accursed bureaucrats.
3869 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3871 f->output_data.x->wm_hints.input = True;
3872 f->output_data.x->wm_hints.flags |= InputHint;
3873 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3874 &f->output_data.x->wm_hints);
3875 f->output_data.x->wm_hints.icon_pixmap = None;
3877 /* Request "save yourself" and "delete window" commands from wm. */
3879 Atom protocols[2];
3880 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3881 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3882 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3885 /* x_set_name normally ignores requests to set the name if the
3886 requested name is the same as the current name. This is the one
3887 place where that assumption isn't correct; f->name is set, but
3888 the X server hasn't been told. */
3890 Lisp_Object name;
3891 int explicit = f->explicit_name;
3893 f->explicit_name = 0;
3894 name = f->name;
3895 f->name = Qnil;
3896 x_set_name (f, name, explicit);
3899 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3900 f->output_data.x->text_cursor);
3902 UNBLOCK_INPUT;
3904 if (FRAME_X_WINDOW (f) == 0)
3905 error ("Unable to create window");
3908 #endif /* not USE_X_TOOLKIT */
3910 /* Handle the icon stuff for this window. Perhaps later we might
3911 want an x_set_icon_position which can be called interactively as
3912 well. */
3914 static void
3915 x_icon (f, parms)
3916 struct frame *f;
3917 Lisp_Object parms;
3919 Lisp_Object icon_x, icon_y;
3920 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3922 /* Set the position of the icon. Note that twm groups all
3923 icons in an icon window. */
3924 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3925 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3926 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3928 CHECK_NUMBER (icon_x, 0);
3929 CHECK_NUMBER (icon_y, 0);
3931 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3932 error ("Both left and top icon corners of icon must be specified");
3934 BLOCK_INPUT;
3936 if (! EQ (icon_x, Qunbound))
3937 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3939 /* Start up iconic or window? */
3940 x_wm_set_window_state
3941 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3942 Qicon)
3943 ? IconicState
3944 : NormalState));
3946 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3947 ? f->icon_name
3948 : f->name))->data);
3950 UNBLOCK_INPUT;
3953 /* Make the GCs needed for this window, setting the
3954 background, border and mouse colors; also create the
3955 mouse cursor and the gray border tile. */
3957 static char cursor_bits[] =
3959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3965 static void
3966 x_make_gc (f)
3967 struct frame *f;
3969 XGCValues gc_values;
3971 BLOCK_INPUT;
3973 /* Create the GCs of this frame.
3974 Note that many default values are used. */
3976 /* Normal video */
3977 gc_values.font = f->output_data.x->font->fid;
3978 gc_values.foreground = f->output_data.x->foreground_pixel;
3979 gc_values.background = f->output_data.x->background_pixel;
3980 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3981 f->output_data.x->normal_gc
3982 = XCreateGC (FRAME_X_DISPLAY (f),
3983 FRAME_X_WINDOW (f),
3984 GCLineWidth | GCFont | GCForeground | GCBackground,
3985 &gc_values);
3987 /* Reverse video style. */
3988 gc_values.foreground = f->output_data.x->background_pixel;
3989 gc_values.background = f->output_data.x->foreground_pixel;
3990 f->output_data.x->reverse_gc
3991 = XCreateGC (FRAME_X_DISPLAY (f),
3992 FRAME_X_WINDOW (f),
3993 GCFont | GCForeground | GCBackground | GCLineWidth,
3994 &gc_values);
3996 /* Cursor has cursor-color background, background-color foreground. */
3997 gc_values.foreground = f->output_data.x->background_pixel;
3998 gc_values.background = f->output_data.x->cursor_pixel;
3999 gc_values.fill_style = FillOpaqueStippled;
4000 gc_values.stipple
4001 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4002 FRAME_X_DISPLAY_INFO (f)->root_window,
4003 cursor_bits, 16, 16);
4004 f->output_data.x->cursor_gc
4005 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4006 (GCFont | GCForeground | GCBackground
4007 | GCFillStyle /* | GCStipple */ | GCLineWidth),
4008 &gc_values);
4010 /* Reliefs. */
4011 f->output_data.x->white_relief.gc = 0;
4012 f->output_data.x->black_relief.gc = 0;
4014 /* Create the gray border tile used when the pointer is not in
4015 the frame. Since this depends on the frame's pixel values,
4016 this must be done on a per-frame basis. */
4017 f->output_data.x->border_tile
4018 = (XCreatePixmapFromBitmapData
4019 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4020 gray_bits, gray_width, gray_height,
4021 f->output_data.x->foreground_pixel,
4022 f->output_data.x->background_pixel,
4023 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4025 UNBLOCK_INPUT;
4029 /* Free what was was allocated in x_make_gc. */
4031 void
4032 x_free_gcs (f)
4033 struct frame *f;
4035 Display *dpy = FRAME_X_DISPLAY (f);
4037 BLOCK_INPUT;
4039 if (f->output_data.x->normal_gc)
4041 XFreeGC (dpy, f->output_data.x->normal_gc);
4042 f->output_data.x->normal_gc = 0;
4045 if (f->output_data.x->reverse_gc)
4047 XFreeGC (dpy, f->output_data.x->reverse_gc);
4048 f->output_data.x->reverse_gc = 0;
4051 if (f->output_data.x->cursor_gc)
4053 XFreeGC (dpy, f->output_data.x->cursor_gc);
4054 f->output_data.x->cursor_gc = 0;
4057 if (f->output_data.x->border_tile)
4059 XFreePixmap (dpy, f->output_data.x->border_tile);
4060 f->output_data.x->border_tile = 0;
4063 UNBLOCK_INPUT;
4067 /* Handler for signals raised during x_create_frame and
4068 x_create_top_frame. FRAME is the frame which is partially
4069 constructed. */
4071 static Lisp_Object
4072 unwind_create_frame (frame)
4073 Lisp_Object frame;
4075 struct frame *f = XFRAME (frame);
4077 /* If frame is ``official'', nothing to do. */
4078 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4080 #if GLYPH_DEBUG
4081 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4082 #endif
4084 x_free_frame_resources (f);
4086 /* Check that reference counts are indeed correct. */
4087 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4088 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4089 return Qt;
4092 return Qnil;
4096 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4097 1, 1, 0,
4098 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
4099 Returns an Emacs frame object.\n\
4100 ALIST is an alist of frame parameters.\n\
4101 If the parameters specify that the frame should not have a minibuffer,\n\
4102 and do not specify a specific minibuffer window to use,\n\
4103 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4104 be shared by the new frame.\n\
4106 This function is an internal primitive--use `make-frame' instead.")
4107 (parms)
4108 Lisp_Object parms;
4110 struct frame *f;
4111 Lisp_Object frame, tem;
4112 Lisp_Object name;
4113 int minibuffer_only = 0;
4114 long window_prompting = 0;
4115 int width, height;
4116 int count = BINDING_STACK_SIZE ();
4117 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4118 Lisp_Object display;
4119 struct x_display_info *dpyinfo = NULL;
4120 Lisp_Object parent;
4121 struct kboard *kb;
4123 check_x ();
4125 /* Use this general default value to start with
4126 until we know if this frame has a specified name. */
4127 Vx_resource_name = Vinvocation_name;
4129 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4130 if (EQ (display, Qunbound))
4131 display = Qnil;
4132 dpyinfo = check_x_display_info (display);
4133 #ifdef MULTI_KBOARD
4134 kb = dpyinfo->kboard;
4135 #else
4136 kb = &the_only_kboard;
4137 #endif
4139 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4140 if (!STRINGP (name)
4141 && ! EQ (name, Qunbound)
4142 && ! NILP (name))
4143 error ("Invalid frame name--not a string or nil");
4145 if (STRINGP (name))
4146 Vx_resource_name = name;
4148 /* See if parent window is specified. */
4149 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4150 if (EQ (parent, Qunbound))
4151 parent = Qnil;
4152 if (! NILP (parent))
4153 CHECK_NUMBER (parent, 0);
4155 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4156 /* No need to protect DISPLAY because that's not used after passing
4157 it to make_frame_without_minibuffer. */
4158 frame = Qnil;
4159 GCPRO4 (parms, parent, name, frame);
4160 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4161 RES_TYPE_SYMBOL);
4162 if (EQ (tem, Qnone) || NILP (tem))
4163 f = make_frame_without_minibuffer (Qnil, kb, display);
4164 else if (EQ (tem, Qonly))
4166 f = make_minibuffer_frame ();
4167 minibuffer_only = 1;
4169 else if (WINDOWP (tem))
4170 f = make_frame_without_minibuffer (tem, kb, display);
4171 else
4172 f = make_frame (1);
4174 XSETFRAME (frame, f);
4176 /* Note that X Windows does support scroll bars. */
4177 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4179 f->output_method = output_x_window;
4180 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4181 bzero (f->output_data.x, sizeof (struct x_output));
4182 f->output_data.x->icon_bitmap = -1;
4183 f->output_data.x->fontset = -1;
4184 f->output_data.x->scroll_bar_foreground_pixel = -1;
4185 f->output_data.x->scroll_bar_background_pixel = -1;
4186 record_unwind_protect (unwind_create_frame, frame);
4188 f->icon_name
4189 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4190 RES_TYPE_STRING);
4191 if (! STRINGP (f->icon_name))
4192 f->icon_name = Qnil;
4194 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4195 #if GLYPH_DEBUG
4196 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4197 dpyinfo_refcount = dpyinfo->reference_count;
4198 #endif /* GLYPH_DEBUG */
4199 #ifdef MULTI_KBOARD
4200 FRAME_KBOARD (f) = kb;
4201 #endif
4203 /* These colors will be set anyway later, but it's important
4204 to get the color reference counts right, so initialize them! */
4206 Lisp_Object black;
4207 struct gcpro gcpro1;
4209 /* Function x_decode_color can signal an error. Make
4210 sure to initialize color slots so that we won't try
4211 to free colors we haven't allocated. */
4212 f->output_data.x->foreground_pixel = -1;
4213 f->output_data.x->background_pixel = -1;
4214 f->output_data.x->cursor_pixel = -1;
4215 f->output_data.x->cursor_foreground_pixel = -1;
4216 f->output_data.x->border_pixel = -1;
4217 f->output_data.x->mouse_pixel = -1;
4219 black = build_string ("black");
4220 GCPRO1 (black);
4221 f->output_data.x->foreground_pixel
4222 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4223 f->output_data.x->background_pixel
4224 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4225 f->output_data.x->cursor_pixel
4226 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4227 f->output_data.x->cursor_foreground_pixel
4228 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4229 f->output_data.x->border_pixel
4230 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4231 f->output_data.x->mouse_pixel
4232 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4233 UNGCPRO;
4236 /* Specify the parent under which to make this X window. */
4238 if (!NILP (parent))
4240 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4241 f->output_data.x->explicit_parent = 1;
4243 else
4245 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4246 f->output_data.x->explicit_parent = 0;
4249 /* Set the name; the functions to which we pass f expect the name to
4250 be set. */
4251 if (EQ (name, Qunbound) || NILP (name))
4253 f->name = build_string (dpyinfo->x_id_name);
4254 f->explicit_name = 0;
4256 else
4258 f->name = name;
4259 f->explicit_name = 1;
4260 /* use the frame's title when getting resources for this frame. */
4261 specbind (Qx_resource_name, name);
4264 /* Extract the window parameters from the supplied values
4265 that are needed to determine window geometry. */
4267 Lisp_Object font;
4269 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4271 BLOCK_INPUT;
4272 /* First, try whatever font the caller has specified. */
4273 if (STRINGP (font))
4275 tem = Fquery_fontset (font, Qnil);
4276 if (STRINGP (tem))
4277 font = x_new_fontset (f, XSTRING (tem)->data);
4278 else
4279 font = x_new_font (f, XSTRING (font)->data);
4282 /* Try out a font which we hope has bold and italic variations. */
4283 if (!STRINGP (font))
4284 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4285 if (!STRINGP (font))
4286 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4287 if (! STRINGP (font))
4288 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4289 if (! STRINGP (font))
4290 /* This was formerly the first thing tried, but it finds too many fonts
4291 and takes too long. */
4292 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4293 /* If those didn't work, look for something which will at least work. */
4294 if (! STRINGP (font))
4295 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4296 UNBLOCK_INPUT;
4297 if (! STRINGP (font))
4298 font = build_string ("fixed");
4300 x_default_parameter (f, parms, Qfont, font,
4301 "font", "Font", RES_TYPE_STRING);
4304 #ifdef USE_LUCID
4305 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4306 whereby it fails to get any font. */
4307 xlwmenu_default_font = f->output_data.x->font;
4308 #endif
4310 x_default_parameter (f, parms, Qborder_width, make_number (2),
4311 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4313 /* This defaults to 2 in order to match xterm. We recognize either
4314 internalBorderWidth or internalBorder (which is what xterm calls
4315 it). */
4316 if (NILP (Fassq (Qinternal_border_width, parms)))
4318 Lisp_Object value;
4320 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4321 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4322 if (! EQ (value, Qunbound))
4323 parms = Fcons (Fcons (Qinternal_border_width, value),
4324 parms);
4326 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4327 "internalBorderWidth", "internalBorderWidth",
4328 RES_TYPE_NUMBER);
4329 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4330 "verticalScrollBars", "ScrollBars",
4331 RES_TYPE_SYMBOL);
4333 /* Also do the stuff which must be set before the window exists. */
4334 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4335 "foreground", "Foreground", RES_TYPE_STRING);
4336 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4337 "background", "Background", RES_TYPE_STRING);
4338 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4339 "pointerColor", "Foreground", RES_TYPE_STRING);
4340 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4341 "cursorColor", "Foreground", RES_TYPE_STRING);
4342 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4343 "borderColor", "BorderColor", RES_TYPE_STRING);
4344 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4345 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4346 x_default_parameter (f, parms, Qline_spacing, Qnil,
4347 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4349 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4350 "scrollBarForeground",
4351 "ScrollBarForeground", 1);
4352 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4353 "scrollBarBackground",
4354 "ScrollBarBackground", 0);
4356 /* Init faces before x_default_parameter is called for scroll-bar
4357 parameters because that function calls x_set_scroll_bar_width,
4358 which calls change_frame_size, which calls Fset_window_buffer,
4359 which runs hooks, which call Fvertical_motion. At the end, we
4360 end up in init_iterator with a null face cache, which should not
4361 happen. */
4362 init_frame_faces (f);
4364 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4365 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4366 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4367 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4368 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4369 "bufferPredicate", "BufferPredicate",
4370 RES_TYPE_SYMBOL);
4371 x_default_parameter (f, parms, Qtitle, Qnil,
4372 "title", "Title", RES_TYPE_STRING);
4373 x_default_parameter (f, parms, Qwait_for_wm, Qt,
4374 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4376 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4378 /* Add the tool-bar height to the initial frame height so that the
4379 user gets a text display area of the size he specified with -g or
4380 via .Xdefaults. Later changes of the tool-bar height don't
4381 change the frame size. This is done so that users can create
4382 tall Emacs frames without having to guess how tall the tool-bar
4383 will get. */
4384 if (FRAME_TOOL_BAR_LINES (f))
4386 int margin, relief, bar_height;
4388 relief = (tool_bar_button_relief > 0
4389 ? tool_bar_button_relief
4390 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4392 if (INTEGERP (Vtool_bar_button_margin)
4393 && XINT (Vtool_bar_button_margin) > 0)
4394 margin = XFASTINT (Vtool_bar_button_margin);
4395 else if (CONSP (Vtool_bar_button_margin)
4396 && INTEGERP (XCDR (Vtool_bar_button_margin))
4397 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4398 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4399 else
4400 margin = 0;
4402 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4403 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4406 /* Compute the size of the X window. */
4407 window_prompting = x_figure_window_size (f, parms);
4409 if (window_prompting & XNegative)
4411 if (window_prompting & YNegative)
4412 f->output_data.x->win_gravity = SouthEastGravity;
4413 else
4414 f->output_data.x->win_gravity = NorthEastGravity;
4416 else
4418 if (window_prompting & YNegative)
4419 f->output_data.x->win_gravity = SouthWestGravity;
4420 else
4421 f->output_data.x->win_gravity = NorthWestGravity;
4424 f->output_data.x->size_hint_flags = window_prompting;
4426 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4427 f->no_split = minibuffer_only || EQ (tem, Qt);
4429 /* Create the X widget or window. */
4430 #ifdef USE_X_TOOLKIT
4431 x_window (f, window_prompting, minibuffer_only);
4432 #else
4433 x_window (f);
4434 #endif
4436 x_icon (f, parms);
4437 x_make_gc (f);
4439 /* Now consider the frame official. */
4440 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4441 Vframe_list = Fcons (frame, Vframe_list);
4443 /* We need to do this after creating the X window, so that the
4444 icon-creation functions can say whose icon they're describing. */
4445 x_default_parameter (f, parms, Qicon_type, Qnil,
4446 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4448 x_default_parameter (f, parms, Qauto_raise, Qnil,
4449 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4450 x_default_parameter (f, parms, Qauto_lower, Qnil,
4451 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4452 x_default_parameter (f, parms, Qcursor_type, Qbox,
4453 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4454 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4455 "scrollBarWidth", "ScrollBarWidth",
4456 RES_TYPE_NUMBER);
4458 /* Dimensions, especially f->height, must be done via change_frame_size.
4459 Change will not be effected unless different from the current
4460 f->height. */
4461 width = f->width;
4462 height = f->height;
4464 f->height = 0;
4465 SET_FRAME_WIDTH (f, 0);
4466 change_frame_size (f, height, width, 1, 0, 0);
4468 /* Set up faces after all frame parameters are known. This call
4469 also merges in face attributes specified for new frames. If we
4470 don't do this, the `menu' face for instance won't have the right
4471 colors, and the menu bar won't appear in the specified colors for
4472 new frames. */
4473 call1 (Qface_set_after_frame_default, frame);
4475 #ifdef USE_X_TOOLKIT
4476 /* Create the menu bar. */
4477 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4479 /* If this signals an error, we haven't set size hints for the
4480 frame and we didn't make it visible. */
4481 initialize_frame_menubar (f);
4483 /* This is a no-op, except under Motif where it arranges the
4484 main window for the widgets on it. */
4485 lw_set_main_areas (f->output_data.x->column_widget,
4486 f->output_data.x->menubar_widget,
4487 f->output_data.x->edit_widget);
4489 #endif /* USE_X_TOOLKIT */
4491 /* Tell the server what size and position, etc, we want, and how
4492 badly we want them. This should be done after we have the menu
4493 bar so that its size can be taken into account. */
4494 BLOCK_INPUT;
4495 x_wm_set_size_hint (f, window_prompting, 0);
4496 UNBLOCK_INPUT;
4498 /* Make the window appear on the frame and enable display, unless
4499 the caller says not to. However, with explicit parent, Emacs
4500 cannot control visibility, so don't try. */
4501 if (! f->output_data.x->explicit_parent)
4503 Lisp_Object visibility;
4505 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4506 RES_TYPE_SYMBOL);
4507 if (EQ (visibility, Qunbound))
4508 visibility = Qt;
4510 if (EQ (visibility, Qicon))
4511 x_iconify_frame (f);
4512 else if (! NILP (visibility))
4513 x_make_frame_visible (f);
4514 else
4515 /* Must have been Qnil. */
4519 UNGCPRO;
4521 /* Make sure windows on this frame appear in calls to next-window
4522 and similar functions. */
4523 Vwindow_list = Qnil;
4525 return unbind_to (count, frame);
4529 /* FRAME is used only to get a handle on the X display. We don't pass the
4530 display info directly because we're called from frame.c, which doesn't
4531 know about that structure. */
4533 Lisp_Object
4534 x_get_focus_frame (frame)
4535 struct frame *frame;
4537 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4538 Lisp_Object xfocus;
4539 if (! dpyinfo->x_focus_frame)
4540 return Qnil;
4542 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4543 return xfocus;
4547 /* In certain situations, when the window manager follows a
4548 click-to-focus policy, there seems to be no way around calling
4549 XSetInputFocus to give another frame the input focus .
4551 In an ideal world, XSetInputFocus should generally be avoided so
4552 that applications don't interfere with the window manager's focus
4553 policy. But I think it's okay to use when it's clearly done
4554 following a user-command. */
4556 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4557 "Set the input focus to FRAME.\n\
4558 FRAME nil means use the selected frame.")
4559 (frame)
4560 Lisp_Object frame;
4562 struct frame *f = check_x_frame (frame);
4563 Display *dpy = FRAME_X_DISPLAY (f);
4564 int count;
4566 BLOCK_INPUT;
4567 count = x_catch_errors (dpy);
4568 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4569 RevertToParent, CurrentTime);
4570 x_uncatch_errors (dpy, count);
4571 UNBLOCK_INPUT;
4573 return Qnil;
4577 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4578 "Internal function called by `color-defined-p', which see.")
4579 (color, frame)
4580 Lisp_Object color, frame;
4582 XColor foo;
4583 FRAME_PTR f = check_x_frame (frame);
4585 CHECK_STRING (color, 1);
4587 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4588 return Qt;
4589 else
4590 return Qnil;
4593 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4594 "Internal function called by `color-values', which see.")
4595 (color, frame)
4596 Lisp_Object color, frame;
4598 XColor foo;
4599 FRAME_PTR f = check_x_frame (frame);
4601 CHECK_STRING (color, 1);
4603 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4605 Lisp_Object rgb[3];
4607 rgb[0] = make_number (foo.red);
4608 rgb[1] = make_number (foo.green);
4609 rgb[2] = make_number (foo.blue);
4610 return Flist (3, rgb);
4612 else
4613 return Qnil;
4616 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4617 "Internal function called by `display-color-p', which see.")
4618 (display)
4619 Lisp_Object display;
4621 struct x_display_info *dpyinfo = check_x_display_info (display);
4623 if (dpyinfo->n_planes <= 2)
4624 return Qnil;
4626 switch (dpyinfo->visual->class)
4628 case StaticColor:
4629 case PseudoColor:
4630 case TrueColor:
4631 case DirectColor:
4632 return Qt;
4634 default:
4635 return Qnil;
4639 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4640 0, 1, 0,
4641 "Return t if the X display supports shades of gray.\n\
4642 Note that color displays do support shades of gray.\n\
4643 The optional argument DISPLAY specifies which display to ask about.\n\
4644 DISPLAY should be either a frame or a display name (a string).\n\
4645 If omitted or nil, that stands for the selected frame's display.")
4646 (display)
4647 Lisp_Object display;
4649 struct x_display_info *dpyinfo = check_x_display_info (display);
4651 if (dpyinfo->n_planes <= 1)
4652 return Qnil;
4654 switch (dpyinfo->visual->class)
4656 case StaticColor:
4657 case PseudoColor:
4658 case TrueColor:
4659 case DirectColor:
4660 case StaticGray:
4661 case GrayScale:
4662 return Qt;
4664 default:
4665 return Qnil;
4669 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4670 0, 1, 0,
4671 "Returns the width in pixels of the X display DISPLAY.\n\
4672 The optional argument DISPLAY specifies which display to ask about.\n\
4673 DISPLAY should be either a frame or a display name (a string).\n\
4674 If omitted or nil, that stands for the selected frame's display.")
4675 (display)
4676 Lisp_Object display;
4678 struct x_display_info *dpyinfo = check_x_display_info (display);
4680 return make_number (dpyinfo->width);
4683 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4684 Sx_display_pixel_height, 0, 1, 0,
4685 "Returns the height in pixels of the X display DISPLAY.\n\
4686 The optional argument DISPLAY specifies which display to ask about.\n\
4687 DISPLAY should be either a frame or a display name (a string).\n\
4688 If omitted or nil, that stands for the selected frame's display.")
4689 (display)
4690 Lisp_Object display;
4692 struct x_display_info *dpyinfo = check_x_display_info (display);
4694 return make_number (dpyinfo->height);
4697 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4698 0, 1, 0,
4699 "Returns the number of bitplanes of the X display DISPLAY.\n\
4700 The optional argument DISPLAY specifies which display to ask about.\n\
4701 DISPLAY should be either a frame or a display name (a string).\n\
4702 If omitted or nil, that stands for the selected frame's display.")
4703 (display)
4704 Lisp_Object display;
4706 struct x_display_info *dpyinfo = check_x_display_info (display);
4708 return make_number (dpyinfo->n_planes);
4711 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4712 0, 1, 0,
4713 "Returns the number of color cells of the X display DISPLAY.\n\
4714 The optional argument DISPLAY specifies which display to ask about.\n\
4715 DISPLAY should be either a frame or a display name (a string).\n\
4716 If omitted or nil, that stands for the selected frame's display.")
4717 (display)
4718 Lisp_Object display;
4720 struct x_display_info *dpyinfo = check_x_display_info (display);
4722 return make_number (DisplayCells (dpyinfo->display,
4723 XScreenNumberOfScreen (dpyinfo->screen)));
4726 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4727 Sx_server_max_request_size,
4728 0, 1, 0,
4729 "Returns the maximum request size of the X server of display DISPLAY.\n\
4730 The optional argument DISPLAY specifies which display to ask about.\n\
4731 DISPLAY should be either a frame or a display name (a string).\n\
4732 If omitted or nil, that stands for the selected frame's display.")
4733 (display)
4734 Lisp_Object display;
4736 struct x_display_info *dpyinfo = check_x_display_info (display);
4738 return make_number (MAXREQUEST (dpyinfo->display));
4741 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4742 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4743 The optional argument DISPLAY specifies which display to ask about.\n\
4744 DISPLAY should be either a frame or a display name (a string).\n\
4745 If omitted or nil, that stands for the selected frame's display.")
4746 (display)
4747 Lisp_Object display;
4749 struct x_display_info *dpyinfo = check_x_display_info (display);
4750 char *vendor = ServerVendor (dpyinfo->display);
4752 if (! vendor) vendor = "";
4753 return build_string (vendor);
4756 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4757 "Returns the version numbers of the X server of display DISPLAY.\n\
4758 The value is a list of three integers: the major and minor\n\
4759 version numbers of the X Protocol in use, and the vendor-specific release\n\
4760 number. See also the function `x-server-vendor'.\n\n\
4761 The optional argument DISPLAY specifies which display to ask about.\n\
4762 DISPLAY should be either a frame or a display name (a string).\n\
4763 If omitted or nil, that stands for the selected frame's display.")
4764 (display)
4765 Lisp_Object display;
4767 struct x_display_info *dpyinfo = check_x_display_info (display);
4768 Display *dpy = dpyinfo->display;
4770 return Fcons (make_number (ProtocolVersion (dpy)),
4771 Fcons (make_number (ProtocolRevision (dpy)),
4772 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4775 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4776 "Returns the number of screens on the X server of display DISPLAY.\n\
4777 The optional argument DISPLAY specifies which display to ask about.\n\
4778 DISPLAY should be either a frame or a display name (a string).\n\
4779 If omitted or nil, that stands for the selected frame's display.")
4780 (display)
4781 Lisp_Object display;
4783 struct x_display_info *dpyinfo = check_x_display_info (display);
4785 return make_number (ScreenCount (dpyinfo->display));
4788 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4789 "Returns the height in millimeters of the X display DISPLAY.\n\
4790 The optional argument DISPLAY specifies which display to ask about.\n\
4791 DISPLAY should be either a frame or a display name (a string).\n\
4792 If omitted or nil, that stands for the selected frame's display.")
4793 (display)
4794 Lisp_Object display;
4796 struct x_display_info *dpyinfo = check_x_display_info (display);
4798 return make_number (HeightMMOfScreen (dpyinfo->screen));
4801 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4802 "Returns the width in millimeters of the X display DISPLAY.\n\
4803 The optional argument DISPLAY specifies which display to ask about.\n\
4804 DISPLAY should be either a frame or a display name (a string).\n\
4805 If omitted or nil, that stands for the selected frame's display.")
4806 (display)
4807 Lisp_Object display;
4809 struct x_display_info *dpyinfo = check_x_display_info (display);
4811 return make_number (WidthMMOfScreen (dpyinfo->screen));
4814 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4815 Sx_display_backing_store, 0, 1, 0,
4816 "Returns an indication of whether X display DISPLAY does backing store.\n\
4817 The value may be `always', `when-mapped', or `not-useful'.\n\
4818 The optional argument DISPLAY specifies which display to ask about.\n\
4819 DISPLAY should be either a frame or a display name (a string).\n\
4820 If omitted or nil, that stands for the selected frame's display.")
4821 (display)
4822 Lisp_Object display;
4824 struct x_display_info *dpyinfo = check_x_display_info (display);
4825 Lisp_Object result;
4827 switch (DoesBackingStore (dpyinfo->screen))
4829 case Always:
4830 result = intern ("always");
4831 break;
4833 case WhenMapped:
4834 result = intern ("when-mapped");
4835 break;
4837 case NotUseful:
4838 result = intern ("not-useful");
4839 break;
4841 default:
4842 error ("Strange value for BackingStore parameter of screen");
4843 result = Qnil;
4846 return result;
4849 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4850 Sx_display_visual_class, 0, 1, 0,
4851 "Returns the visual class of the X display DISPLAY.\n\
4852 The value is one of the symbols `static-gray', `gray-scale',\n\
4853 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4854 The optional argument DISPLAY specifies which display to ask about.\n\
4855 DISPLAY should be either a frame or a display name (a string).\n\
4856 If omitted or nil, that stands for the selected frame's display.")
4857 (display)
4858 Lisp_Object display;
4860 struct x_display_info *dpyinfo = check_x_display_info (display);
4861 Lisp_Object result;
4863 switch (dpyinfo->visual->class)
4865 case StaticGray:
4866 result = intern ("static-gray");
4867 break;
4868 case GrayScale:
4869 result = intern ("gray-scale");
4870 break;
4871 case StaticColor:
4872 result = intern ("static-color");
4873 break;
4874 case PseudoColor:
4875 result = intern ("pseudo-color");
4876 break;
4877 case TrueColor:
4878 result = intern ("true-color");
4879 break;
4880 case DirectColor:
4881 result = intern ("direct-color");
4882 break;
4883 default:
4884 error ("Display has an unknown visual class");
4885 result = Qnil;
4888 return result;
4891 DEFUN ("x-display-save-under", Fx_display_save_under,
4892 Sx_display_save_under, 0, 1, 0,
4893 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4894 The optional argument DISPLAY specifies which display to ask about.\n\
4895 DISPLAY should be either a frame or a display name (a string).\n\
4896 If omitted or nil, that stands for the selected frame's display.")
4897 (display)
4898 Lisp_Object display;
4900 struct x_display_info *dpyinfo = check_x_display_info (display);
4902 if (DoesSaveUnders (dpyinfo->screen) == True)
4903 return Qt;
4904 else
4905 return Qnil;
4909 x_pixel_width (f)
4910 register struct frame *f;
4912 return PIXEL_WIDTH (f);
4916 x_pixel_height (f)
4917 register struct frame *f;
4919 return PIXEL_HEIGHT (f);
4923 x_char_width (f)
4924 register struct frame *f;
4926 return FONT_WIDTH (f->output_data.x->font);
4930 x_char_height (f)
4931 register struct frame *f;
4933 return f->output_data.x->line_height;
4937 x_screen_planes (f)
4938 register struct frame *f;
4940 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4945 /************************************************************************
4946 X Displays
4947 ************************************************************************/
4950 /* Mapping visual names to visuals. */
4952 static struct visual_class
4954 char *name;
4955 int class;
4957 visual_classes[] =
4959 {"StaticGray", StaticGray},
4960 {"GrayScale", GrayScale},
4961 {"StaticColor", StaticColor},
4962 {"PseudoColor", PseudoColor},
4963 {"TrueColor", TrueColor},
4964 {"DirectColor", DirectColor},
4965 NULL
4969 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4971 /* Value is the screen number of screen SCR. This is a substitute for
4972 the X function with the same name when that doesn't exist. */
4975 XScreenNumberOfScreen (scr)
4976 register Screen *scr;
4978 Display *dpy = scr->display;
4979 int i;
4981 for (i = 0; i < dpy->nscreens; ++i)
4982 if (scr == dpy->screens + i)
4983 break;
4985 return i;
4988 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4991 /* Select the visual that should be used on display DPYINFO. Set
4992 members of DPYINFO appropriately. Called from x_term_init. */
4994 void
4995 select_visual (dpyinfo)
4996 struct x_display_info *dpyinfo;
4998 Display *dpy = dpyinfo->display;
4999 Screen *screen = dpyinfo->screen;
5000 Lisp_Object value;
5002 /* See if a visual is specified. */
5003 value = display_x_get_resource (dpyinfo,
5004 build_string ("visualClass"),
5005 build_string ("VisualClass"),
5006 Qnil, Qnil);
5007 if (STRINGP (value))
5009 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5010 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5011 depth, a decimal number. NAME is compared with case ignored. */
5012 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
5013 char *dash;
5014 int i, class = -1;
5015 XVisualInfo vinfo;
5017 strcpy (s, XSTRING (value)->data);
5018 dash = index (s, '-');
5019 if (dash)
5021 dpyinfo->n_planes = atoi (dash + 1);
5022 *dash = '\0';
5024 else
5025 /* We won't find a matching visual with depth 0, so that
5026 an error will be printed below. */
5027 dpyinfo->n_planes = 0;
5029 /* Determine the visual class. */
5030 for (i = 0; visual_classes[i].name; ++i)
5031 if (xstricmp (s, visual_classes[i].name) == 0)
5033 class = visual_classes[i].class;
5034 break;
5037 /* Look up a matching visual for the specified class. */
5038 if (class == -1
5039 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5040 dpyinfo->n_planes, class, &vinfo))
5041 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
5043 dpyinfo->visual = vinfo.visual;
5045 else
5047 int n_visuals;
5048 XVisualInfo *vinfo, vinfo_template;
5050 dpyinfo->visual = DefaultVisualOfScreen (screen);
5052 #ifdef HAVE_X11R4
5053 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5054 #else
5055 vinfo_template.visualid = dpyinfo->visual->visualid;
5056 #endif
5057 vinfo_template.screen = XScreenNumberOfScreen (screen);
5058 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5059 &vinfo_template, &n_visuals);
5060 if (n_visuals != 1)
5061 fatal ("Can't get proper X visual info");
5063 dpyinfo->n_planes = vinfo->depth;
5064 XFree ((char *) vinfo);
5069 /* Return the X display structure for the display named NAME.
5070 Open a new connection if necessary. */
5072 struct x_display_info *
5073 x_display_info_for_name (name)
5074 Lisp_Object name;
5076 Lisp_Object names;
5077 struct x_display_info *dpyinfo;
5079 CHECK_STRING (name, 0);
5081 if (! EQ (Vwindow_system, intern ("x")))
5082 error ("Not using X Windows");
5084 for (dpyinfo = x_display_list, names = x_display_name_list;
5085 dpyinfo;
5086 dpyinfo = dpyinfo->next, names = XCDR (names))
5088 Lisp_Object tem;
5089 tem = Fstring_equal (XCAR (XCAR (names)), name);
5090 if (!NILP (tem))
5091 return dpyinfo;
5094 /* Use this general default value to start with. */
5095 Vx_resource_name = Vinvocation_name;
5097 validate_x_resource_name ();
5099 dpyinfo = x_term_init (name, (char *)0,
5100 (char *) XSTRING (Vx_resource_name)->data);
5102 if (dpyinfo == 0)
5103 error ("Cannot connect to X server %s", XSTRING (name)->data);
5105 x_in_use = 1;
5106 XSETFASTINT (Vwindow_system_version, 11);
5108 return dpyinfo;
5112 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5113 1, 3, 0, "Open a connection to an X server.\n\
5114 DISPLAY is the name of the display to connect to.\n\
5115 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5116 If the optional third arg MUST-SUCCEED is non-nil,\n\
5117 terminate Emacs if we can't open the connection.")
5118 (display, xrm_string, must_succeed)
5119 Lisp_Object display, xrm_string, must_succeed;
5121 unsigned char *xrm_option;
5122 struct x_display_info *dpyinfo;
5124 CHECK_STRING (display, 0);
5125 if (! NILP (xrm_string))
5126 CHECK_STRING (xrm_string, 1);
5128 if (! EQ (Vwindow_system, intern ("x")))
5129 error ("Not using X Windows");
5131 if (! NILP (xrm_string))
5132 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5133 else
5134 xrm_option = (unsigned char *) 0;
5136 validate_x_resource_name ();
5138 /* This is what opens the connection and sets x_current_display.
5139 This also initializes many symbols, such as those used for input. */
5140 dpyinfo = x_term_init (display, xrm_option,
5141 (char *) XSTRING (Vx_resource_name)->data);
5143 if (dpyinfo == 0)
5145 if (!NILP (must_succeed))
5146 fatal ("Cannot connect to X server %s.\n\
5147 Check the DISPLAY environment variable or use `-d'.\n\
5148 Also use the `xhost' program to verify that it is set to permit\n\
5149 connections from your machine.\n",
5150 XSTRING (display)->data);
5151 else
5152 error ("Cannot connect to X server %s", XSTRING (display)->data);
5155 x_in_use = 1;
5157 XSETFASTINT (Vwindow_system_version, 11);
5158 return Qnil;
5161 DEFUN ("x-close-connection", Fx_close_connection,
5162 Sx_close_connection, 1, 1, 0,
5163 "Close the connection to DISPLAY's X server.\n\
5164 For DISPLAY, specify either a frame or a display name (a string).\n\
5165 If DISPLAY is nil, that stands for the selected frame's display.")
5166 (display)
5167 Lisp_Object display;
5169 struct x_display_info *dpyinfo = check_x_display_info (display);
5170 int i;
5172 if (dpyinfo->reference_count > 0)
5173 error ("Display still has frames on it");
5175 BLOCK_INPUT;
5176 /* Free the fonts in the font table. */
5177 for (i = 0; i < dpyinfo->n_fonts; i++)
5178 if (dpyinfo->font_table[i].name)
5180 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5181 xfree (dpyinfo->font_table[i].full_name);
5182 xfree (dpyinfo->font_table[i].name);
5183 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5186 x_destroy_all_bitmaps (dpyinfo);
5187 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5189 #ifdef USE_X_TOOLKIT
5190 XtCloseDisplay (dpyinfo->display);
5191 #else
5192 XCloseDisplay (dpyinfo->display);
5193 #endif
5195 x_delete_display (dpyinfo);
5196 UNBLOCK_INPUT;
5198 return Qnil;
5201 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5202 "Return the list of display names that Emacs has connections to.")
5205 Lisp_Object tail, result;
5207 result = Qnil;
5208 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5209 result = Fcons (XCAR (XCAR (tail)), result);
5211 return result;
5214 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5215 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5216 If ON is nil, allow buffering of requests.\n\
5217 Turning on synchronization prohibits the Xlib routines from buffering\n\
5218 requests and seriously degrades performance, but makes debugging much\n\
5219 easier.\n\
5220 The optional second argument DISPLAY specifies which display to act on.\n\
5221 DISPLAY should be either a frame or a display name (a string).\n\
5222 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5223 (on, display)
5224 Lisp_Object display, on;
5226 struct x_display_info *dpyinfo = check_x_display_info (display);
5228 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5230 return Qnil;
5233 /* Wait for responses to all X commands issued so far for frame F. */
5235 void
5236 x_sync (f)
5237 FRAME_PTR f;
5239 BLOCK_INPUT;
5240 XSync (FRAME_X_DISPLAY (f), False);
5241 UNBLOCK_INPUT;
5245 /***********************************************************************
5246 Image types
5247 ***********************************************************************/
5249 /* Value is the number of elements of vector VECTOR. */
5251 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5253 /* List of supported image types. Use define_image_type to add new
5254 types. Use lookup_image_type to find a type for a given symbol. */
5256 static struct image_type *image_types;
5258 /* The symbol `image' which is the car of the lists used to represent
5259 images in Lisp. */
5261 extern Lisp_Object Qimage;
5263 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5265 Lisp_Object Qxbm;
5267 /* Keywords. */
5269 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5270 extern Lisp_Object QCdata;
5271 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5272 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5273 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5275 /* Other symbols. */
5277 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5279 /* Time in seconds after which images should be removed from the cache
5280 if not displayed. */
5282 Lisp_Object Vimage_cache_eviction_delay;
5284 /* Function prototypes. */
5286 static void define_image_type P_ ((struct image_type *type));
5287 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5288 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5289 static void x_laplace P_ ((struct frame *, struct image *));
5290 static void x_emboss P_ ((struct frame *, struct image *));
5291 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5292 Lisp_Object));
5295 /* Define a new image type from TYPE. This adds a copy of TYPE to
5296 image_types and adds the symbol *TYPE->type to Vimage_types. */
5298 static void
5299 define_image_type (type)
5300 struct image_type *type;
5302 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5303 The initialized data segment is read-only. */
5304 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5305 bcopy (type, p, sizeof *p);
5306 p->next = image_types;
5307 image_types = p;
5308 Vimage_types = Fcons (*p->type, Vimage_types);
5312 /* Look up image type SYMBOL, and return a pointer to its image_type
5313 structure. Value is null if SYMBOL is not a known image type. */
5315 static INLINE struct image_type *
5316 lookup_image_type (symbol)
5317 Lisp_Object symbol;
5319 struct image_type *type;
5321 for (type = image_types; type; type = type->next)
5322 if (EQ (symbol, *type->type))
5323 break;
5325 return type;
5329 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5330 valid image specification is a list whose car is the symbol
5331 `image', and whose rest is a property list. The property list must
5332 contain a value for key `:type'. That value must be the name of a
5333 supported image type. The rest of the property list depends on the
5334 image type. */
5337 valid_image_p (object)
5338 Lisp_Object object;
5340 int valid_p = 0;
5342 if (CONSP (object) && EQ (XCAR (object), Qimage))
5344 Lisp_Object tem;
5346 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5347 if (EQ (XCAR (tem), QCtype))
5349 tem = XCDR (tem);
5350 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5352 struct image_type *type;
5353 type = lookup_image_type (XCAR (tem));
5354 if (type)
5355 valid_p = type->valid_p (object);
5358 break;
5362 return valid_p;
5366 /* Log error message with format string FORMAT and argument ARG.
5367 Signaling an error, e.g. when an image cannot be loaded, is not a
5368 good idea because this would interrupt redisplay, and the error
5369 message display would lead to another redisplay. This function
5370 therefore simply displays a message. */
5372 static void
5373 image_error (format, arg1, arg2)
5374 char *format;
5375 Lisp_Object arg1, arg2;
5377 add_to_log (format, arg1, arg2);
5382 /***********************************************************************
5383 Image specifications
5384 ***********************************************************************/
5386 enum image_value_type
5388 IMAGE_DONT_CHECK_VALUE_TYPE,
5389 IMAGE_STRING_VALUE,
5390 IMAGE_STRING_OR_NIL_VALUE,
5391 IMAGE_SYMBOL_VALUE,
5392 IMAGE_POSITIVE_INTEGER_VALUE,
5393 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5394 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5395 IMAGE_ASCENT_VALUE,
5396 IMAGE_INTEGER_VALUE,
5397 IMAGE_FUNCTION_VALUE,
5398 IMAGE_NUMBER_VALUE,
5399 IMAGE_BOOL_VALUE
5402 /* Structure used when parsing image specifications. */
5404 struct image_keyword
5406 /* Name of keyword. */
5407 char *name;
5409 /* The type of value allowed. */
5410 enum image_value_type type;
5412 /* Non-zero means key must be present. */
5413 int mandatory_p;
5415 /* Used to recognize duplicate keywords in a property list. */
5416 int count;
5418 /* The value that was found. */
5419 Lisp_Object value;
5423 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5424 int, Lisp_Object));
5425 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5428 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5429 has the format (image KEYWORD VALUE ...). One of the keyword/
5430 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5431 image_keywords structures of size NKEYWORDS describing other
5432 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5434 static int
5435 parse_image_spec (spec, keywords, nkeywords, type)
5436 Lisp_Object spec;
5437 struct image_keyword *keywords;
5438 int nkeywords;
5439 Lisp_Object type;
5441 int i;
5442 Lisp_Object plist;
5444 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5445 return 0;
5447 plist = XCDR (spec);
5448 while (CONSP (plist))
5450 Lisp_Object key, value;
5452 /* First element of a pair must be a symbol. */
5453 key = XCAR (plist);
5454 plist = XCDR (plist);
5455 if (!SYMBOLP (key))
5456 return 0;
5458 /* There must follow a value. */
5459 if (!CONSP (plist))
5460 return 0;
5461 value = XCAR (plist);
5462 plist = XCDR (plist);
5464 /* Find key in KEYWORDS. Error if not found. */
5465 for (i = 0; i < nkeywords; ++i)
5466 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5467 break;
5469 if (i == nkeywords)
5470 continue;
5472 /* Record that we recognized the keyword. If a keywords
5473 was found more than once, it's an error. */
5474 keywords[i].value = value;
5475 ++keywords[i].count;
5477 if (keywords[i].count > 1)
5478 return 0;
5480 /* Check type of value against allowed type. */
5481 switch (keywords[i].type)
5483 case IMAGE_STRING_VALUE:
5484 if (!STRINGP (value))
5485 return 0;
5486 break;
5488 case IMAGE_STRING_OR_NIL_VALUE:
5489 if (!STRINGP (value) && !NILP (value))
5490 return 0;
5491 break;
5493 case IMAGE_SYMBOL_VALUE:
5494 if (!SYMBOLP (value))
5495 return 0;
5496 break;
5498 case IMAGE_POSITIVE_INTEGER_VALUE:
5499 if (!INTEGERP (value) || XINT (value) <= 0)
5500 return 0;
5501 break;
5503 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5504 if (INTEGERP (value) && XINT (value) >= 0)
5505 break;
5506 if (CONSP (value)
5507 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5508 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5509 break;
5510 return 0;
5512 case IMAGE_ASCENT_VALUE:
5513 if (SYMBOLP (value) && EQ (value, Qcenter))
5514 break;
5515 else if (INTEGERP (value)
5516 && XINT (value) >= 0
5517 && XINT (value) <= 100)
5518 break;
5519 return 0;
5521 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5522 if (!INTEGERP (value) || XINT (value) < 0)
5523 return 0;
5524 break;
5526 case IMAGE_DONT_CHECK_VALUE_TYPE:
5527 break;
5529 case IMAGE_FUNCTION_VALUE:
5530 value = indirect_function (value);
5531 if (SUBRP (value)
5532 || COMPILEDP (value)
5533 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5534 break;
5535 return 0;
5537 case IMAGE_NUMBER_VALUE:
5538 if (!INTEGERP (value) && !FLOATP (value))
5539 return 0;
5540 break;
5542 case IMAGE_INTEGER_VALUE:
5543 if (!INTEGERP (value))
5544 return 0;
5545 break;
5547 case IMAGE_BOOL_VALUE:
5548 if (!NILP (value) && !EQ (value, Qt))
5549 return 0;
5550 break;
5552 default:
5553 abort ();
5554 break;
5557 if (EQ (key, QCtype) && !EQ (type, value))
5558 return 0;
5561 /* Check that all mandatory fields are present. */
5562 for (i = 0; i < nkeywords; ++i)
5563 if (keywords[i].mandatory_p && keywords[i].count == 0)
5564 return 0;
5566 return NILP (plist);
5570 /* Return the value of KEY in image specification SPEC. Value is nil
5571 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5572 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5574 static Lisp_Object
5575 image_spec_value (spec, key, found)
5576 Lisp_Object spec, key;
5577 int *found;
5579 Lisp_Object tail;
5581 xassert (valid_image_p (spec));
5583 for (tail = XCDR (spec);
5584 CONSP (tail) && CONSP (XCDR (tail));
5585 tail = XCDR (XCDR (tail)))
5587 if (EQ (XCAR (tail), key))
5589 if (found)
5590 *found = 1;
5591 return XCAR (XCDR (tail));
5595 if (found)
5596 *found = 0;
5597 return Qnil;
5601 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5602 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5603 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5604 size in canonical character units.\n\
5605 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5606 or omitted means use the selected frame.")
5607 (spec, pixels, frame)
5608 Lisp_Object spec, pixels, frame;
5610 Lisp_Object size;
5612 size = Qnil;
5613 if (valid_image_p (spec))
5615 struct frame *f = check_x_frame (frame);
5616 int id = lookup_image (f, spec);
5617 struct image *img = IMAGE_FROM_ID (f, id);
5618 int width = img->width + 2 * img->hmargin;
5619 int height = img->height + 2 * img->vmargin;
5621 if (NILP (pixels))
5622 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5623 make_float ((double) height / CANON_Y_UNIT (f)));
5624 else
5625 size = Fcons (make_number (width), make_number (height));
5627 else
5628 error ("Invalid image specification");
5630 return size;
5634 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5635 "Return t if image SPEC has a mask bitmap.\n\
5636 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5637 or omitted means use the selected frame.")
5638 (spec, frame)
5639 Lisp_Object spec, frame;
5641 Lisp_Object mask;
5643 mask = Qnil;
5644 if (valid_image_p (spec))
5646 struct frame *f = check_x_frame (frame);
5647 int id = lookup_image (f, spec);
5648 struct image *img = IMAGE_FROM_ID (f, id);
5649 if (img->mask)
5650 mask = Qt;
5652 else
5653 error ("Invalid image specification");
5655 return mask;
5660 /***********************************************************************
5661 Image type independent image structures
5662 ***********************************************************************/
5664 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5665 static void free_image P_ ((struct frame *f, struct image *img));
5668 /* Allocate and return a new image structure for image specification
5669 SPEC. SPEC has a hash value of HASH. */
5671 static struct image *
5672 make_image (spec, hash)
5673 Lisp_Object spec;
5674 unsigned hash;
5676 struct image *img = (struct image *) xmalloc (sizeof *img);
5678 xassert (valid_image_p (spec));
5679 bzero (img, sizeof *img);
5680 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5681 xassert (img->type != NULL);
5682 img->spec = spec;
5683 img->data.lisp_val = Qnil;
5684 img->ascent = DEFAULT_IMAGE_ASCENT;
5685 img->hash = hash;
5686 return img;
5690 /* Free image IMG which was used on frame F, including its resources. */
5692 static void
5693 free_image (f, img)
5694 struct frame *f;
5695 struct image *img;
5697 if (img)
5699 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5701 /* Remove IMG from the hash table of its cache. */
5702 if (img->prev)
5703 img->prev->next = img->next;
5704 else
5705 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5707 if (img->next)
5708 img->next->prev = img->prev;
5710 c->images[img->id] = NULL;
5712 /* Free resources, then free IMG. */
5713 img->type->free (f, img);
5714 xfree (img);
5719 /* Prepare image IMG for display on frame F. Must be called before
5720 drawing an image. */
5722 void
5723 prepare_image_for_display (f, img)
5724 struct frame *f;
5725 struct image *img;
5727 EMACS_TIME t;
5729 /* We're about to display IMG, so set its timestamp to `now'. */
5730 EMACS_GET_TIME (t);
5731 img->timestamp = EMACS_SECS (t);
5733 /* If IMG doesn't have a pixmap yet, load it now, using the image
5734 type dependent loader function. */
5735 if (img->pixmap == None && !img->load_failed_p)
5736 img->load_failed_p = img->type->load (f, img) == 0;
5740 /* Value is the number of pixels for the ascent of image IMG when
5741 drawn in face FACE. */
5744 image_ascent (img, face)
5745 struct image *img;
5746 struct face *face;
5748 int height = img->height + img->vmargin;
5749 int ascent;
5751 if (img->ascent == CENTERED_IMAGE_ASCENT)
5753 if (face->font)
5754 /* This expression is arranged so that if the image can't be
5755 exactly centered, it will be moved slightly up. This is
5756 because a typical font is `top-heavy' (due to the presence
5757 uppercase letters), so the image placement should err towards
5758 being top-heavy too. It also just generally looks better. */
5759 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5760 else
5761 ascent = height / 2;
5763 else
5764 ascent = height * img->ascent / 100.0;
5766 return ascent;
5771 /***********************************************************************
5772 Helper functions for X image types
5773 ***********************************************************************/
5775 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5776 int, int));
5777 static void x_clear_image P_ ((struct frame *f, struct image *img));
5778 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5779 struct image *img,
5780 Lisp_Object color_name,
5781 unsigned long dflt));
5784 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5785 free the pixmap if any. MASK_P non-zero means clear the mask
5786 pixmap if any. COLORS_P non-zero means free colors allocated for
5787 the image, if any. */
5789 static void
5790 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5791 struct frame *f;
5792 struct image *img;
5793 int pixmap_p, mask_p, colors_p;
5795 if (pixmap_p && img->pixmap)
5797 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5798 img->pixmap = None;
5801 if (mask_p && img->mask)
5803 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5804 img->mask = None;
5807 if (colors_p && img->ncolors)
5809 x_free_colors (f, img->colors, img->ncolors);
5810 xfree (img->colors);
5811 img->colors = NULL;
5812 img->ncolors = 0;
5816 /* Free X resources of image IMG which is used on frame F. */
5818 static void
5819 x_clear_image (f, img)
5820 struct frame *f;
5821 struct image *img;
5823 BLOCK_INPUT;
5824 x_clear_image_1 (f, img, 1, 1, 1);
5825 UNBLOCK_INPUT;
5829 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5830 cannot be allocated, use DFLT. Add a newly allocated color to
5831 IMG->colors, so that it can be freed again. Value is the pixel
5832 color. */
5834 static unsigned long
5835 x_alloc_image_color (f, img, color_name, dflt)
5836 struct frame *f;
5837 struct image *img;
5838 Lisp_Object color_name;
5839 unsigned long dflt;
5841 XColor color;
5842 unsigned long result;
5844 xassert (STRINGP (color_name));
5846 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5848 /* This isn't called frequently so we get away with simply
5849 reallocating the color vector to the needed size, here. */
5850 ++img->ncolors;
5851 img->colors =
5852 (unsigned long *) xrealloc (img->colors,
5853 img->ncolors * sizeof *img->colors);
5854 img->colors[img->ncolors - 1] = color.pixel;
5855 result = color.pixel;
5857 else
5858 result = dflt;
5860 return result;
5865 /***********************************************************************
5866 Image Cache
5867 ***********************************************************************/
5869 static void cache_image P_ ((struct frame *f, struct image *img));
5870 static void postprocess_image P_ ((struct frame *, struct image *));
5873 /* Return a new, initialized image cache that is allocated from the
5874 heap. Call free_image_cache to free an image cache. */
5876 struct image_cache *
5877 make_image_cache ()
5879 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5880 int size;
5882 bzero (c, sizeof *c);
5883 c->size = 50;
5884 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5885 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5886 c->buckets = (struct image **) xmalloc (size);
5887 bzero (c->buckets, size);
5888 return c;
5892 /* Free image cache of frame F. Be aware that X frames share images
5893 caches. */
5895 void
5896 free_image_cache (f)
5897 struct frame *f;
5899 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5900 if (c)
5902 int i;
5904 /* Cache should not be referenced by any frame when freed. */
5905 xassert (c->refcount == 0);
5907 for (i = 0; i < c->used; ++i)
5908 free_image (f, c->images[i]);
5909 xfree (c->images);
5910 xfree (c->buckets);
5911 xfree (c);
5912 FRAME_X_IMAGE_CACHE (f) = NULL;
5917 /* Clear image cache of frame F. FORCE_P non-zero means free all
5918 images. FORCE_P zero means clear only images that haven't been
5919 displayed for some time. Should be called from time to time to
5920 reduce the number of loaded images. If image-eviction-seconds is
5921 non-nil, this frees images in the cache which weren't displayed for
5922 at least that many seconds. */
5924 void
5925 clear_image_cache (f, force_p)
5926 struct frame *f;
5927 int force_p;
5929 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5931 if (c && INTEGERP (Vimage_cache_eviction_delay))
5933 EMACS_TIME t;
5934 unsigned long old;
5935 int i, nfreed;
5937 EMACS_GET_TIME (t);
5938 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5940 /* Block input so that we won't be interrupted by a SIGIO
5941 while being in an inconsistent state. */
5942 BLOCK_INPUT;
5944 for (i = nfreed = 0; i < c->used; ++i)
5946 struct image *img = c->images[i];
5947 if (img != NULL
5948 && (force_p || img->timestamp < old))
5950 free_image (f, img);
5951 ++nfreed;
5955 /* We may be clearing the image cache because, for example,
5956 Emacs was iconified for a longer period of time. In that
5957 case, current matrices may still contain references to
5958 images freed above. So, clear these matrices. */
5959 if (nfreed)
5961 Lisp_Object tail, frame;
5963 FOR_EACH_FRAME (tail, frame)
5965 struct frame *f = XFRAME (frame);
5966 if (FRAME_X_P (f)
5967 && FRAME_X_IMAGE_CACHE (f) == c)
5968 clear_current_matrices (f);
5971 ++windows_or_buffers_changed;
5974 UNBLOCK_INPUT;
5979 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5980 0, 1, 0,
5981 "Clear the image cache of FRAME.\n\
5982 FRAME nil or omitted means use the selected frame.\n\
5983 FRAME t means clear the image caches of all frames.")
5984 (frame)
5985 Lisp_Object frame;
5987 if (EQ (frame, Qt))
5989 Lisp_Object tail;
5991 FOR_EACH_FRAME (tail, frame)
5992 if (FRAME_X_P (XFRAME (frame)))
5993 clear_image_cache (XFRAME (frame), 1);
5995 else
5996 clear_image_cache (check_x_frame (frame), 1);
5998 return Qnil;
6002 /* Compute masks and transform image IMG on frame F, as specified
6003 by the image's specification, */
6005 static void
6006 postprocess_image (f, img)
6007 struct frame *f;
6008 struct image *img;
6010 /* Manipulation of the image's mask. */
6011 if (img->pixmap)
6013 Lisp_Object conversion, spec;
6014 Lisp_Object mask;
6016 spec = img->spec;
6018 /* `:heuristic-mask t'
6019 `:mask heuristic'
6020 means build a mask heuristically.
6021 `:heuristic-mask (R G B)'
6022 `:mask (heuristic (R G B))'
6023 means build a mask from color (R G B) in the
6024 image.
6025 `:mask nil'
6026 means remove a mask, if any. */
6028 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6029 if (!NILP (mask))
6030 x_build_heuristic_mask (f, img, mask);
6031 else
6033 int found_p;
6035 mask = image_spec_value (spec, QCmask, &found_p);
6037 if (EQ (mask, Qheuristic))
6038 x_build_heuristic_mask (f, img, Qt);
6039 else if (CONSP (mask)
6040 && EQ (XCAR (mask), Qheuristic))
6042 if (CONSP (XCDR (mask)))
6043 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6044 else
6045 x_build_heuristic_mask (f, img, XCDR (mask));
6047 else if (NILP (mask) && found_p && img->mask)
6049 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6050 img->mask = None;
6055 /* Should we apply an image transformation algorithm? */
6056 conversion = image_spec_value (spec, QCconversion, NULL);
6057 if (EQ (conversion, Qdisabled))
6058 x_disable_image (f, img);
6059 else if (EQ (conversion, Qlaplace))
6060 x_laplace (f, img);
6061 else if (EQ (conversion, Qemboss))
6062 x_emboss (f, img);
6063 else if (CONSP (conversion)
6064 && EQ (XCAR (conversion), Qedge_detection))
6066 Lisp_Object tem;
6067 tem = XCDR (conversion);
6068 if (CONSP (tem))
6069 x_edge_detection (f, img,
6070 Fplist_get (tem, QCmatrix),
6071 Fplist_get (tem, QCcolor_adjustment));
6077 /* Return the id of image with Lisp specification SPEC on frame F.
6078 SPEC must be a valid Lisp image specification (see valid_image_p). */
6081 lookup_image (f, spec)
6082 struct frame *f;
6083 Lisp_Object spec;
6085 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6086 struct image *img;
6087 int i;
6088 unsigned hash;
6089 struct gcpro gcpro1;
6090 EMACS_TIME now;
6092 /* F must be a window-system frame, and SPEC must be a valid image
6093 specification. */
6094 xassert (FRAME_WINDOW_P (f));
6095 xassert (valid_image_p (spec));
6097 GCPRO1 (spec);
6099 /* Look up SPEC in the hash table of the image cache. */
6100 hash = sxhash (spec, 0);
6101 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6103 for (img = c->buckets[i]; img; img = img->next)
6104 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6105 break;
6107 /* If not found, create a new image and cache it. */
6108 if (img == NULL)
6110 extern Lisp_Object Qpostscript;
6112 BLOCK_INPUT;
6113 img = make_image (spec, hash);
6114 cache_image (f, img);
6115 img->load_failed_p = img->type->load (f, img) == 0;
6117 /* If we can't load the image, and we don't have a width and
6118 height, use some arbitrary width and height so that we can
6119 draw a rectangle for it. */
6120 if (img->load_failed_p)
6122 Lisp_Object value;
6124 value = image_spec_value (spec, QCwidth, NULL);
6125 img->width = (INTEGERP (value)
6126 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6127 value = image_spec_value (spec, QCheight, NULL);
6128 img->height = (INTEGERP (value)
6129 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6131 else
6133 /* Handle image type independent image attributes
6134 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
6135 Lisp_Object ascent, margin, relief;
6137 ascent = image_spec_value (spec, QCascent, NULL);
6138 if (INTEGERP (ascent))
6139 img->ascent = XFASTINT (ascent);
6140 else if (EQ (ascent, Qcenter))
6141 img->ascent = CENTERED_IMAGE_ASCENT;
6143 margin = image_spec_value (spec, QCmargin, NULL);
6144 if (INTEGERP (margin) && XINT (margin) >= 0)
6145 img->vmargin = img->hmargin = XFASTINT (margin);
6146 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6147 && INTEGERP (XCDR (margin)))
6149 if (XINT (XCAR (margin)) > 0)
6150 img->hmargin = XFASTINT (XCAR (margin));
6151 if (XINT (XCDR (margin)) > 0)
6152 img->vmargin = XFASTINT (XCDR (margin));
6155 relief = image_spec_value (spec, QCrelief, NULL);
6156 if (INTEGERP (relief))
6158 img->relief = XINT (relief);
6159 img->hmargin += abs (img->relief);
6160 img->vmargin += abs (img->relief);
6163 /* Do image transformations and compute masks, unless we
6164 don't have the image yet. */
6165 if (!EQ (*img->type->type, Qpostscript))
6166 postprocess_image (f, img);
6169 UNBLOCK_INPUT;
6170 xassert (!interrupt_input_blocked);
6173 /* We're using IMG, so set its timestamp to `now'. */
6174 EMACS_GET_TIME (now);
6175 img->timestamp = EMACS_SECS (now);
6177 UNGCPRO;
6179 /* Value is the image id. */
6180 return img->id;
6184 /* Cache image IMG in the image cache of frame F. */
6186 static void
6187 cache_image (f, img)
6188 struct frame *f;
6189 struct image *img;
6191 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6192 int i;
6194 /* Find a free slot in c->images. */
6195 for (i = 0; i < c->used; ++i)
6196 if (c->images[i] == NULL)
6197 break;
6199 /* If no free slot found, maybe enlarge c->images. */
6200 if (i == c->used && c->used == c->size)
6202 c->size *= 2;
6203 c->images = (struct image **) xrealloc (c->images,
6204 c->size * sizeof *c->images);
6207 /* Add IMG to c->images, and assign IMG an id. */
6208 c->images[i] = img;
6209 img->id = i;
6210 if (i == c->used)
6211 ++c->used;
6213 /* Add IMG to the cache's hash table. */
6214 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6215 img->next = c->buckets[i];
6216 if (img->next)
6217 img->next->prev = img;
6218 img->prev = NULL;
6219 c->buckets[i] = img;
6223 /* Call FN on every image in the image cache of frame F. Used to mark
6224 Lisp Objects in the image cache. */
6226 void
6227 forall_images_in_image_cache (f, fn)
6228 struct frame *f;
6229 void (*fn) P_ ((struct image *img));
6231 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6233 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6234 if (c)
6236 int i;
6237 for (i = 0; i < c->used; ++i)
6238 if (c->images[i])
6239 fn (c->images[i]);
6246 /***********************************************************************
6247 X support code
6248 ***********************************************************************/
6250 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6251 XImage **, Pixmap *));
6252 static void x_destroy_x_image P_ ((XImage *));
6253 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6256 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6257 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6258 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6259 via xmalloc. Print error messages via image_error if an error
6260 occurs. Value is non-zero if successful. */
6262 static int
6263 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6264 struct frame *f;
6265 int width, height, depth;
6266 XImage **ximg;
6267 Pixmap *pixmap;
6269 Display *display = FRAME_X_DISPLAY (f);
6270 Screen *screen = FRAME_X_SCREEN (f);
6271 Window window = FRAME_X_WINDOW (f);
6273 xassert (interrupt_input_blocked);
6275 if (depth <= 0)
6276 depth = DefaultDepthOfScreen (screen);
6277 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6278 depth, ZPixmap, 0, NULL, width, height,
6279 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6280 if (*ximg == NULL)
6282 image_error ("Unable to allocate X image", Qnil, Qnil);
6283 return 0;
6286 /* Allocate image raster. */
6287 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6289 /* Allocate a pixmap of the same size. */
6290 *pixmap = XCreatePixmap (display, window, width, height, depth);
6291 if (*pixmap == None)
6293 x_destroy_x_image (*ximg);
6294 *ximg = NULL;
6295 image_error ("Unable to create X pixmap", Qnil, Qnil);
6296 return 0;
6299 return 1;
6303 /* Destroy XImage XIMG. Free XIMG->data. */
6305 static void
6306 x_destroy_x_image (ximg)
6307 XImage *ximg;
6309 xassert (interrupt_input_blocked);
6310 if (ximg)
6312 xfree (ximg->data);
6313 ximg->data = NULL;
6314 XDestroyImage (ximg);
6319 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6320 are width and height of both the image and pixmap. */
6322 static void
6323 x_put_x_image (f, ximg, pixmap, width, height)
6324 struct frame *f;
6325 XImage *ximg;
6326 Pixmap pixmap;
6328 GC gc;
6330 xassert (interrupt_input_blocked);
6331 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6332 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6333 XFreeGC (FRAME_X_DISPLAY (f), gc);
6338 /***********************************************************************
6339 File Handling
6340 ***********************************************************************/
6342 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6343 static char *slurp_file P_ ((char *, int *));
6346 /* Find image file FILE. Look in data-directory, then
6347 x-bitmap-file-path. Value is the full name of the file found, or
6348 nil if not found. */
6350 static Lisp_Object
6351 x_find_image_file (file)
6352 Lisp_Object file;
6354 Lisp_Object file_found, search_path;
6355 struct gcpro gcpro1, gcpro2;
6356 int fd;
6358 file_found = Qnil;
6359 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6360 GCPRO2 (file_found, search_path);
6362 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6363 fd = openp (search_path, file, "", &file_found, 0);
6365 if (fd == -1)
6366 file_found = Qnil;
6367 else
6368 close (fd);
6370 UNGCPRO;
6371 return file_found;
6375 /* Read FILE into memory. Value is a pointer to a buffer allocated
6376 with xmalloc holding FILE's contents. Value is null if an error
6377 occurred. *SIZE is set to the size of the file. */
6379 static char *
6380 slurp_file (file, size)
6381 char *file;
6382 int *size;
6384 FILE *fp = NULL;
6385 char *buf = NULL;
6386 struct stat st;
6388 if (stat (file, &st) == 0
6389 && (fp = fopen (file, "r")) != NULL
6390 && (buf = (char *) xmalloc (st.st_size),
6391 fread (buf, 1, st.st_size, fp) == st.st_size))
6393 *size = st.st_size;
6394 fclose (fp);
6396 else
6398 if (fp)
6399 fclose (fp);
6400 if (buf)
6402 xfree (buf);
6403 buf = NULL;
6407 return buf;
6412 /***********************************************************************
6413 XBM images
6414 ***********************************************************************/
6416 static int xbm_scan P_ ((char **, char *, char *, int *));
6417 static int xbm_load P_ ((struct frame *f, struct image *img));
6418 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6419 char *, char *));
6420 static int xbm_image_p P_ ((Lisp_Object object));
6421 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6422 unsigned char **));
6423 static int xbm_file_p P_ ((Lisp_Object));
6426 /* Indices of image specification fields in xbm_format, below. */
6428 enum xbm_keyword_index
6430 XBM_TYPE,
6431 XBM_FILE,
6432 XBM_WIDTH,
6433 XBM_HEIGHT,
6434 XBM_DATA,
6435 XBM_FOREGROUND,
6436 XBM_BACKGROUND,
6437 XBM_ASCENT,
6438 XBM_MARGIN,
6439 XBM_RELIEF,
6440 XBM_ALGORITHM,
6441 XBM_HEURISTIC_MASK,
6442 XBM_MASK,
6443 XBM_LAST
6446 /* Vector of image_keyword structures describing the format
6447 of valid XBM image specifications. */
6449 static struct image_keyword xbm_format[XBM_LAST] =
6451 {":type", IMAGE_SYMBOL_VALUE, 1},
6452 {":file", IMAGE_STRING_VALUE, 0},
6453 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6454 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6455 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6456 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6457 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6458 {":ascent", IMAGE_ASCENT_VALUE, 0},
6459 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6460 {":relief", IMAGE_INTEGER_VALUE, 0},
6461 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6462 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6463 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6466 /* Structure describing the image type XBM. */
6468 static struct image_type xbm_type =
6470 &Qxbm,
6471 xbm_image_p,
6472 xbm_load,
6473 x_clear_image,
6474 NULL
6477 /* Tokens returned from xbm_scan. */
6479 enum xbm_token
6481 XBM_TK_IDENT = 256,
6482 XBM_TK_NUMBER
6486 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6487 A valid specification is a list starting with the symbol `image'
6488 The rest of the list is a property list which must contain an
6489 entry `:type xbm..
6491 If the specification specifies a file to load, it must contain
6492 an entry `:file FILENAME' where FILENAME is a string.
6494 If the specification is for a bitmap loaded from memory it must
6495 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6496 WIDTH and HEIGHT are integers > 0. DATA may be:
6498 1. a string large enough to hold the bitmap data, i.e. it must
6499 have a size >= (WIDTH + 7) / 8 * HEIGHT
6501 2. a bool-vector of size >= WIDTH * HEIGHT
6503 3. a vector of strings or bool-vectors, one for each line of the
6504 bitmap.
6506 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6507 may not be specified in this case because they are defined in the
6508 XBM file.
6510 Both the file and data forms may contain the additional entries
6511 `:background COLOR' and `:foreground COLOR'. If not present,
6512 foreground and background of the frame on which the image is
6513 displayed is used. */
6515 static int
6516 xbm_image_p (object)
6517 Lisp_Object object;
6519 struct image_keyword kw[XBM_LAST];
6521 bcopy (xbm_format, kw, sizeof kw);
6522 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6523 return 0;
6525 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6527 if (kw[XBM_FILE].count)
6529 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6530 return 0;
6532 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6534 /* In-memory XBM file. */
6535 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6536 return 0;
6538 else
6540 Lisp_Object data;
6541 int width, height;
6543 /* Entries for `:width', `:height' and `:data' must be present. */
6544 if (!kw[XBM_WIDTH].count
6545 || !kw[XBM_HEIGHT].count
6546 || !kw[XBM_DATA].count)
6547 return 0;
6549 data = kw[XBM_DATA].value;
6550 width = XFASTINT (kw[XBM_WIDTH].value);
6551 height = XFASTINT (kw[XBM_HEIGHT].value);
6553 /* Check type of data, and width and height against contents of
6554 data. */
6555 if (VECTORP (data))
6557 int i;
6559 /* Number of elements of the vector must be >= height. */
6560 if (XVECTOR (data)->size < height)
6561 return 0;
6563 /* Each string or bool-vector in data must be large enough
6564 for one line of the image. */
6565 for (i = 0; i < height; ++i)
6567 Lisp_Object elt = XVECTOR (data)->contents[i];
6569 if (STRINGP (elt))
6571 if (XSTRING (elt)->size
6572 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6573 return 0;
6575 else if (BOOL_VECTOR_P (elt))
6577 if (XBOOL_VECTOR (elt)->size < width)
6578 return 0;
6580 else
6581 return 0;
6584 else if (STRINGP (data))
6586 if (XSTRING (data)->size
6587 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6588 return 0;
6590 else if (BOOL_VECTOR_P (data))
6592 if (XBOOL_VECTOR (data)->size < width * height)
6593 return 0;
6595 else
6596 return 0;
6599 return 1;
6603 /* Scan a bitmap file. FP is the stream to read from. Value is
6604 either an enumerator from enum xbm_token, or a character for a
6605 single-character token, or 0 at end of file. If scanning an
6606 identifier, store the lexeme of the identifier in SVAL. If
6607 scanning a number, store its value in *IVAL. */
6609 static int
6610 xbm_scan (s, end, sval, ival)
6611 char **s, *end;
6612 char *sval;
6613 int *ival;
6615 int c;
6617 loop:
6619 /* Skip white space. */
6620 while (*s < end && (c = *(*s)++, isspace (c)))
6623 if (*s >= end)
6624 c = 0;
6625 else if (isdigit (c))
6627 int value = 0, digit;
6629 if (c == '0' && *s < end)
6631 c = *(*s)++;
6632 if (c == 'x' || c == 'X')
6634 while (*s < end)
6636 c = *(*s)++;
6637 if (isdigit (c))
6638 digit = c - '0';
6639 else if (c >= 'a' && c <= 'f')
6640 digit = c - 'a' + 10;
6641 else if (c >= 'A' && c <= 'F')
6642 digit = c - 'A' + 10;
6643 else
6644 break;
6645 value = 16 * value + digit;
6648 else if (isdigit (c))
6650 value = c - '0';
6651 while (*s < end
6652 && (c = *(*s)++, isdigit (c)))
6653 value = 8 * value + c - '0';
6656 else
6658 value = c - '0';
6659 while (*s < end
6660 && (c = *(*s)++, isdigit (c)))
6661 value = 10 * value + c - '0';
6664 if (*s < end)
6665 *s = *s - 1;
6666 *ival = value;
6667 c = XBM_TK_NUMBER;
6669 else if (isalpha (c) || c == '_')
6671 *sval++ = c;
6672 while (*s < end
6673 && (c = *(*s)++, (isalnum (c) || c == '_')))
6674 *sval++ = c;
6675 *sval = 0;
6676 if (*s < end)
6677 *s = *s - 1;
6678 c = XBM_TK_IDENT;
6680 else if (c == '/' && **s == '*')
6682 /* C-style comment. */
6683 ++*s;
6684 while (**s && (**s != '*' || *(*s + 1) != '/'))
6685 ++*s;
6686 if (**s)
6688 *s += 2;
6689 goto loop;
6693 return c;
6697 /* Replacement for XReadBitmapFileData which isn't available under old
6698 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6699 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6700 the image. Return in *DATA the bitmap data allocated with xmalloc.
6701 Value is non-zero if successful. DATA null means just test if
6702 CONTENTS looks like an in-memory XBM file. */
6704 static int
6705 xbm_read_bitmap_data (contents, end, width, height, data)
6706 char *contents, *end;
6707 int *width, *height;
6708 unsigned char **data;
6710 char *s = contents;
6711 char buffer[BUFSIZ];
6712 int padding_p = 0;
6713 int v10 = 0;
6714 int bytes_per_line, i, nbytes;
6715 unsigned char *p;
6716 int value;
6717 int LA1;
6719 #define match() \
6720 LA1 = xbm_scan (&s, end, buffer, &value)
6722 #define expect(TOKEN) \
6723 if (LA1 != (TOKEN)) \
6724 goto failure; \
6725 else \
6726 match ()
6728 #define expect_ident(IDENT) \
6729 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6730 match (); \
6731 else \
6732 goto failure
6734 *width = *height = -1;
6735 if (data)
6736 *data = NULL;
6737 LA1 = xbm_scan (&s, end, buffer, &value);
6739 /* Parse defines for width, height and hot-spots. */
6740 while (LA1 == '#')
6742 match ();
6743 expect_ident ("define");
6744 expect (XBM_TK_IDENT);
6746 if (LA1 == XBM_TK_NUMBER);
6748 char *p = strrchr (buffer, '_');
6749 p = p ? p + 1 : buffer;
6750 if (strcmp (p, "width") == 0)
6751 *width = value;
6752 else if (strcmp (p, "height") == 0)
6753 *height = value;
6755 expect (XBM_TK_NUMBER);
6758 if (*width < 0 || *height < 0)
6759 goto failure;
6760 else if (data == NULL)
6761 goto success;
6763 /* Parse bits. Must start with `static'. */
6764 expect_ident ("static");
6765 if (LA1 == XBM_TK_IDENT)
6767 if (strcmp (buffer, "unsigned") == 0)
6769 match ();
6770 expect_ident ("char");
6772 else if (strcmp (buffer, "short") == 0)
6774 match ();
6775 v10 = 1;
6776 if (*width % 16 && *width % 16 < 9)
6777 padding_p = 1;
6779 else if (strcmp (buffer, "char") == 0)
6780 match ();
6781 else
6782 goto failure;
6784 else
6785 goto failure;
6787 expect (XBM_TK_IDENT);
6788 expect ('[');
6789 expect (']');
6790 expect ('=');
6791 expect ('{');
6793 bytes_per_line = (*width + 7) / 8 + padding_p;
6794 nbytes = bytes_per_line * *height;
6795 p = *data = (char *) xmalloc (nbytes);
6797 if (v10)
6799 for (i = 0; i < nbytes; i += 2)
6801 int val = value;
6802 expect (XBM_TK_NUMBER);
6804 *p++ = val;
6805 if (!padding_p || ((i + 2) % bytes_per_line))
6806 *p++ = value >> 8;
6808 if (LA1 == ',' || LA1 == '}')
6809 match ();
6810 else
6811 goto failure;
6814 else
6816 for (i = 0; i < nbytes; ++i)
6818 int val = value;
6819 expect (XBM_TK_NUMBER);
6821 *p++ = val;
6823 if (LA1 == ',' || LA1 == '}')
6824 match ();
6825 else
6826 goto failure;
6830 success:
6831 return 1;
6833 failure:
6835 if (data && *data)
6837 xfree (*data);
6838 *data = NULL;
6840 return 0;
6842 #undef match
6843 #undef expect
6844 #undef expect_ident
6848 /* Load XBM image IMG which will be displayed on frame F from buffer
6849 CONTENTS. END is the end of the buffer. Value is non-zero if
6850 successful. */
6852 static int
6853 xbm_load_image (f, img, contents, end)
6854 struct frame *f;
6855 struct image *img;
6856 char *contents, *end;
6858 int rc;
6859 unsigned char *data;
6860 int success_p = 0;
6862 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6863 if (rc)
6865 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6866 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6867 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6868 Lisp_Object value;
6870 xassert (img->width > 0 && img->height > 0);
6872 /* Get foreground and background colors, maybe allocate colors. */
6873 value = image_spec_value (img->spec, QCforeground, NULL);
6874 if (!NILP (value))
6875 foreground = x_alloc_image_color (f, img, value, foreground);
6877 value = image_spec_value (img->spec, QCbackground, NULL);
6878 if (!NILP (value))
6879 background = x_alloc_image_color (f, img, value, background);
6881 img->pixmap
6882 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6883 FRAME_X_WINDOW (f),
6884 data,
6885 img->width, img->height,
6886 foreground, background,
6887 depth);
6888 xfree (data);
6890 if (img->pixmap == None)
6892 x_clear_image (f, img);
6893 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6895 else
6896 success_p = 1;
6898 else
6899 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6901 return success_p;
6905 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6907 static int
6908 xbm_file_p (data)
6909 Lisp_Object data;
6911 int w, h;
6912 return (STRINGP (data)
6913 && xbm_read_bitmap_data (XSTRING (data)->data,
6914 (XSTRING (data)->data
6915 + STRING_BYTES (XSTRING (data))),
6916 &w, &h, NULL));
6920 /* Fill image IMG which is used on frame F with pixmap data. Value is
6921 non-zero if successful. */
6923 static int
6924 xbm_load (f, img)
6925 struct frame *f;
6926 struct image *img;
6928 int success_p = 0;
6929 Lisp_Object file_name;
6931 xassert (xbm_image_p (img->spec));
6933 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6934 file_name = image_spec_value (img->spec, QCfile, NULL);
6935 if (STRINGP (file_name))
6937 Lisp_Object file;
6938 char *contents;
6939 int size;
6940 struct gcpro gcpro1;
6942 file = x_find_image_file (file_name);
6943 GCPRO1 (file);
6944 if (!STRINGP (file))
6946 image_error ("Cannot find image file `%s'", file_name, Qnil);
6947 UNGCPRO;
6948 return 0;
6951 contents = slurp_file (XSTRING (file)->data, &size);
6952 if (contents == NULL)
6954 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6955 UNGCPRO;
6956 return 0;
6959 success_p = xbm_load_image (f, img, contents, contents + size);
6960 UNGCPRO;
6962 else
6964 struct image_keyword fmt[XBM_LAST];
6965 Lisp_Object data;
6966 int depth;
6967 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6968 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6969 char *bits;
6970 int parsed_p;
6971 int in_memory_file_p = 0;
6973 /* See if data looks like an in-memory XBM file. */
6974 data = image_spec_value (img->spec, QCdata, NULL);
6975 in_memory_file_p = xbm_file_p (data);
6977 /* Parse the image specification. */
6978 bcopy (xbm_format, fmt, sizeof fmt);
6979 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6980 xassert (parsed_p);
6982 /* Get specified width, and height. */
6983 if (!in_memory_file_p)
6985 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6986 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6987 xassert (img->width > 0 && img->height > 0);
6990 /* Get foreground and background colors, maybe allocate colors. */
6991 if (fmt[XBM_FOREGROUND].count
6992 && STRINGP (fmt[XBM_FOREGROUND].value))
6993 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6994 foreground);
6995 if (fmt[XBM_BACKGROUND].count
6996 && STRINGP (fmt[XBM_BACKGROUND].value))
6997 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6998 background);
7000 if (in_memory_file_p)
7001 success_p = xbm_load_image (f, img, XSTRING (data)->data,
7002 (XSTRING (data)->data
7003 + STRING_BYTES (XSTRING (data))));
7004 else
7006 if (VECTORP (data))
7008 int i;
7009 char *p;
7010 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7012 p = bits = (char *) alloca (nbytes * img->height);
7013 for (i = 0; i < img->height; ++i, p += nbytes)
7015 Lisp_Object line = XVECTOR (data)->contents[i];
7016 if (STRINGP (line))
7017 bcopy (XSTRING (line)->data, p, nbytes);
7018 else
7019 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7022 else if (STRINGP (data))
7023 bits = XSTRING (data)->data;
7024 else
7025 bits = XBOOL_VECTOR (data)->data;
7027 /* Create the pixmap. */
7028 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7029 img->pixmap
7030 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7031 FRAME_X_WINDOW (f),
7032 bits,
7033 img->width, img->height,
7034 foreground, background,
7035 depth);
7036 if (img->pixmap)
7037 success_p = 1;
7038 else
7040 image_error ("Unable to create pixmap for XBM image `%s'",
7041 img->spec, Qnil);
7042 x_clear_image (f, img);
7047 return success_p;
7052 /***********************************************************************
7053 XPM images
7054 ***********************************************************************/
7056 #if HAVE_XPM
7058 static int xpm_image_p P_ ((Lisp_Object object));
7059 static int xpm_load P_ ((struct frame *f, struct image *img));
7060 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7062 #include "X11/xpm.h"
7064 /* The symbol `xpm' identifying XPM-format images. */
7066 Lisp_Object Qxpm;
7068 /* Indices of image specification fields in xpm_format, below. */
7070 enum xpm_keyword_index
7072 XPM_TYPE,
7073 XPM_FILE,
7074 XPM_DATA,
7075 XPM_ASCENT,
7076 XPM_MARGIN,
7077 XPM_RELIEF,
7078 XPM_ALGORITHM,
7079 XPM_HEURISTIC_MASK,
7080 XPM_MASK,
7081 XPM_COLOR_SYMBOLS,
7082 XPM_LAST
7085 /* Vector of image_keyword structures describing the format
7086 of valid XPM image specifications. */
7088 static struct image_keyword xpm_format[XPM_LAST] =
7090 {":type", IMAGE_SYMBOL_VALUE, 1},
7091 {":file", IMAGE_STRING_VALUE, 0},
7092 {":data", IMAGE_STRING_VALUE, 0},
7093 {":ascent", IMAGE_ASCENT_VALUE, 0},
7094 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7095 {":relief", IMAGE_INTEGER_VALUE, 0},
7096 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7097 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7098 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7099 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7102 /* Structure describing the image type XBM. */
7104 static struct image_type xpm_type =
7106 &Qxpm,
7107 xpm_image_p,
7108 xpm_load,
7109 x_clear_image,
7110 NULL
7114 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7115 functions for allocating image colors. Our own functions handle
7116 color allocation failures more gracefully than the ones on the XPM
7117 lib. */
7119 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7120 #define ALLOC_XPM_COLORS
7121 #endif
7123 #ifdef ALLOC_XPM_COLORS
7125 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7126 static void xpm_free_color_cache P_ ((void));
7127 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7128 static int xpm_color_bucket P_ ((char *));
7129 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7130 XColor *, int));
7132 /* An entry in a hash table used to cache color definitions of named
7133 colors. This cache is necessary to speed up XPM image loading in
7134 case we do color allocations ourselves. Without it, we would need
7135 a call to XParseColor per pixel in the image. */
7137 struct xpm_cached_color
7139 /* Next in collision chain. */
7140 struct xpm_cached_color *next;
7142 /* Color definition (RGB and pixel color). */
7143 XColor color;
7145 /* Color name. */
7146 char name[1];
7149 /* The hash table used for the color cache, and its bucket vector
7150 size. */
7152 #define XPM_COLOR_CACHE_BUCKETS 1001
7153 struct xpm_cached_color **xpm_color_cache;
7155 /* Initialize the color cache. */
7157 static void
7158 xpm_init_color_cache (f, attrs)
7159 struct frame *f;
7160 XpmAttributes *attrs;
7162 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7163 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7164 memset (xpm_color_cache, 0, nbytes);
7165 init_color_table ();
7167 if (attrs->valuemask & XpmColorSymbols)
7169 int i;
7170 XColor color;
7172 for (i = 0; i < attrs->numsymbols; ++i)
7173 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7174 attrs->colorsymbols[i].value, &color))
7176 color.pixel = lookup_rgb_color (f, color.red, color.green,
7177 color.blue);
7178 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7184 /* Free the color cache. */
7186 static void
7187 xpm_free_color_cache ()
7189 struct xpm_cached_color *p, *next;
7190 int i;
7192 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7193 for (p = xpm_color_cache[i]; p; p = next)
7195 next = p->next;
7196 xfree (p);
7199 xfree (xpm_color_cache);
7200 xpm_color_cache = NULL;
7201 free_color_table ();
7205 /* Return the bucket index for color named COLOR_NAME in the color
7206 cache. */
7208 static int
7209 xpm_color_bucket (color_name)
7210 char *color_name;
7212 unsigned h = 0;
7213 char *s;
7215 for (s = color_name; *s; ++s)
7216 h = (h << 2) ^ *s;
7217 return h %= XPM_COLOR_CACHE_BUCKETS;
7221 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7222 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7223 entry added. */
7225 static struct xpm_cached_color *
7226 xpm_cache_color (f, color_name, color, bucket)
7227 struct frame *f;
7228 char *color_name;
7229 XColor *color;
7230 int bucket;
7232 size_t nbytes;
7233 struct xpm_cached_color *p;
7235 if (bucket < 0)
7236 bucket = xpm_color_bucket (color_name);
7238 nbytes = sizeof *p + strlen (color_name);
7239 p = (struct xpm_cached_color *) xmalloc (nbytes);
7240 strcpy (p->name, color_name);
7241 p->color = *color;
7242 p->next = xpm_color_cache[bucket];
7243 xpm_color_cache[bucket] = p;
7244 return p;
7248 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7249 return the cached definition in *COLOR. Otherwise, make a new
7250 entry in the cache and allocate the color. Value is zero if color
7251 allocation failed. */
7253 static int
7254 xpm_lookup_color (f, color_name, color)
7255 struct frame *f;
7256 char *color_name;
7257 XColor *color;
7259 struct xpm_cached_color *p;
7260 int h = xpm_color_bucket (color_name);
7262 for (p = xpm_color_cache[h]; p; p = p->next)
7263 if (strcmp (p->name, color_name) == 0)
7264 break;
7266 if (p != NULL)
7267 *color = p->color;
7268 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7269 color_name, color))
7271 color->pixel = lookup_rgb_color (f, color->red, color->green,
7272 color->blue);
7273 p = xpm_cache_color (f, color_name, color, h);
7276 return p != NULL;
7280 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7281 CLOSURE is a pointer to the frame on which we allocate the
7282 color. Return in *COLOR the allocated color. Value is non-zero
7283 if successful. */
7285 static int
7286 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7287 Display *dpy;
7288 Colormap cmap;
7289 char *color_name;
7290 XColor *color;
7291 void *closure;
7293 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7297 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7298 is a pointer to the frame on which we allocate the color. Value is
7299 non-zero if successful. */
7301 static int
7302 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7303 Display *dpy;
7304 Colormap cmap;
7305 Pixel *pixels;
7306 int npixels;
7307 void *closure;
7309 return 1;
7312 #endif /* ALLOC_XPM_COLORS */
7315 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7316 for XPM images. Such a list must consist of conses whose car and
7317 cdr are strings. */
7319 static int
7320 xpm_valid_color_symbols_p (color_symbols)
7321 Lisp_Object color_symbols;
7323 while (CONSP (color_symbols))
7325 Lisp_Object sym = XCAR (color_symbols);
7326 if (!CONSP (sym)
7327 || !STRINGP (XCAR (sym))
7328 || !STRINGP (XCDR (sym)))
7329 break;
7330 color_symbols = XCDR (color_symbols);
7333 return NILP (color_symbols);
7337 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7339 static int
7340 xpm_image_p (object)
7341 Lisp_Object object;
7343 struct image_keyword fmt[XPM_LAST];
7344 bcopy (xpm_format, fmt, sizeof fmt);
7345 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7346 /* Either `:file' or `:data' must be present. */
7347 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7348 /* Either no `:color-symbols' or it's a list of conses
7349 whose car and cdr are strings. */
7350 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7351 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7355 /* Load image IMG which will be displayed on frame F. Value is
7356 non-zero if successful. */
7358 static int
7359 xpm_load (f, img)
7360 struct frame *f;
7361 struct image *img;
7363 int rc;
7364 XpmAttributes attrs;
7365 Lisp_Object specified_file, color_symbols;
7367 /* Configure the XPM lib. Use the visual of frame F. Allocate
7368 close colors. Return colors allocated. */
7369 bzero (&attrs, sizeof attrs);
7370 attrs.visual = FRAME_X_VISUAL (f);
7371 attrs.colormap = FRAME_X_COLORMAP (f);
7372 attrs.valuemask |= XpmVisual;
7373 attrs.valuemask |= XpmColormap;
7375 #ifdef ALLOC_XPM_COLORS
7376 /* Allocate colors with our own functions which handle
7377 failing color allocation more gracefully. */
7378 attrs.color_closure = f;
7379 attrs.alloc_color = xpm_alloc_color;
7380 attrs.free_colors = xpm_free_colors;
7381 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7382 #else /* not ALLOC_XPM_COLORS */
7383 /* Let the XPM lib allocate colors. */
7384 attrs.valuemask |= XpmReturnAllocPixels;
7385 #ifdef XpmAllocCloseColors
7386 attrs.alloc_close_colors = 1;
7387 attrs.valuemask |= XpmAllocCloseColors;
7388 #else /* not XpmAllocCloseColors */
7389 attrs.closeness = 600;
7390 attrs.valuemask |= XpmCloseness;
7391 #endif /* not XpmAllocCloseColors */
7392 #endif /* ALLOC_XPM_COLORS */
7394 /* If image specification contains symbolic color definitions, add
7395 these to `attrs'. */
7396 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7397 if (CONSP (color_symbols))
7399 Lisp_Object tail;
7400 XpmColorSymbol *xpm_syms;
7401 int i, size;
7403 attrs.valuemask |= XpmColorSymbols;
7405 /* Count number of symbols. */
7406 attrs.numsymbols = 0;
7407 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7408 ++attrs.numsymbols;
7410 /* Allocate an XpmColorSymbol array. */
7411 size = attrs.numsymbols * sizeof *xpm_syms;
7412 xpm_syms = (XpmColorSymbol *) alloca (size);
7413 bzero (xpm_syms, size);
7414 attrs.colorsymbols = xpm_syms;
7416 /* Fill the color symbol array. */
7417 for (tail = color_symbols, i = 0;
7418 CONSP (tail);
7419 ++i, tail = XCDR (tail))
7421 Lisp_Object name = XCAR (XCAR (tail));
7422 Lisp_Object color = XCDR (XCAR (tail));
7423 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7424 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7425 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7426 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7430 /* Create a pixmap for the image, either from a file, or from a
7431 string buffer containing data in the same format as an XPM file. */
7432 #ifdef ALLOC_XPM_COLORS
7433 xpm_init_color_cache (f, &attrs);
7434 #endif
7436 specified_file = image_spec_value (img->spec, QCfile, NULL);
7437 if (STRINGP (specified_file))
7439 Lisp_Object file = x_find_image_file (specified_file);
7440 if (!STRINGP (file))
7442 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7443 return 0;
7446 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7447 XSTRING (file)->data, &img->pixmap, &img->mask,
7448 &attrs);
7450 else
7452 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7453 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7454 XSTRING (buffer)->data,
7455 &img->pixmap, &img->mask,
7456 &attrs);
7459 if (rc == XpmSuccess)
7461 #ifdef ALLOC_XPM_COLORS
7462 img->colors = colors_in_color_table (&img->ncolors);
7463 #else /* not ALLOC_XPM_COLORS */
7464 int i;
7466 img->ncolors = attrs.nalloc_pixels;
7467 img->colors = (unsigned long *) xmalloc (img->ncolors
7468 * sizeof *img->colors);
7469 for (i = 0; i < attrs.nalloc_pixels; ++i)
7471 img->colors[i] = attrs.alloc_pixels[i];
7472 #ifdef DEBUG_X_COLORS
7473 register_color (img->colors[i]);
7474 #endif
7476 #endif /* not ALLOC_XPM_COLORS */
7478 img->width = attrs.width;
7479 img->height = attrs.height;
7480 xassert (img->width > 0 && img->height > 0);
7482 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7483 XpmFreeAttributes (&attrs);
7485 else
7487 switch (rc)
7489 case XpmOpenFailed:
7490 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7491 break;
7493 case XpmFileInvalid:
7494 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7495 break;
7497 case XpmNoMemory:
7498 image_error ("Out of memory (%s)", img->spec, Qnil);
7499 break;
7501 case XpmColorFailed:
7502 image_error ("Color allocation error (%s)", img->spec, Qnil);
7503 break;
7505 default:
7506 image_error ("Unknown error (%s)", img->spec, Qnil);
7507 break;
7511 #ifdef ALLOC_XPM_COLORS
7512 xpm_free_color_cache ();
7513 #endif
7514 return rc == XpmSuccess;
7517 #endif /* HAVE_XPM != 0 */
7520 /***********************************************************************
7521 Color table
7522 ***********************************************************************/
7524 /* An entry in the color table mapping an RGB color to a pixel color. */
7526 struct ct_color
7528 int r, g, b;
7529 unsigned long pixel;
7531 /* Next in color table collision list. */
7532 struct ct_color *next;
7535 /* The bucket vector size to use. Must be prime. */
7537 #define CT_SIZE 101
7539 /* Value is a hash of the RGB color given by R, G, and B. */
7541 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7543 /* The color hash table. */
7545 struct ct_color **ct_table;
7547 /* Number of entries in the color table. */
7549 int ct_colors_allocated;
7551 /* Initialize the color table. */
7553 static void
7554 init_color_table ()
7556 int size = CT_SIZE * sizeof (*ct_table);
7557 ct_table = (struct ct_color **) xmalloc (size);
7558 bzero (ct_table, size);
7559 ct_colors_allocated = 0;
7563 /* Free memory associated with the color table. */
7565 static void
7566 free_color_table ()
7568 int i;
7569 struct ct_color *p, *next;
7571 for (i = 0; i < CT_SIZE; ++i)
7572 for (p = ct_table[i]; p; p = next)
7574 next = p->next;
7575 xfree (p);
7578 xfree (ct_table);
7579 ct_table = NULL;
7583 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7584 entry for that color already is in the color table, return the
7585 pixel color of that entry. Otherwise, allocate a new color for R,
7586 G, B, and make an entry in the color table. */
7588 static unsigned long
7589 lookup_rgb_color (f, r, g, b)
7590 struct frame *f;
7591 int r, g, b;
7593 unsigned hash = CT_HASH_RGB (r, g, b);
7594 int i = hash % CT_SIZE;
7595 struct ct_color *p;
7597 for (p = ct_table[i]; p; p = p->next)
7598 if (p->r == r && p->g == g && p->b == b)
7599 break;
7601 if (p == NULL)
7603 XColor color;
7604 Colormap cmap;
7605 int rc;
7607 color.red = r;
7608 color.green = g;
7609 color.blue = b;
7611 cmap = FRAME_X_COLORMAP (f);
7612 rc = x_alloc_nearest_color (f, cmap, &color);
7614 if (rc)
7616 ++ct_colors_allocated;
7618 p = (struct ct_color *) xmalloc (sizeof *p);
7619 p->r = r;
7620 p->g = g;
7621 p->b = b;
7622 p->pixel = color.pixel;
7623 p->next = ct_table[i];
7624 ct_table[i] = p;
7626 else
7627 return FRAME_FOREGROUND_PIXEL (f);
7630 return p->pixel;
7634 /* Look up pixel color PIXEL which is used on frame F in the color
7635 table. If not already present, allocate it. Value is PIXEL. */
7637 static unsigned long
7638 lookup_pixel_color (f, pixel)
7639 struct frame *f;
7640 unsigned long pixel;
7642 int i = pixel % CT_SIZE;
7643 struct ct_color *p;
7645 for (p = ct_table[i]; p; p = p->next)
7646 if (p->pixel == pixel)
7647 break;
7649 if (p == NULL)
7651 XColor color;
7652 Colormap cmap;
7653 int rc;
7655 cmap = FRAME_X_COLORMAP (f);
7656 color.pixel = pixel;
7657 x_query_color (f, &color);
7658 rc = x_alloc_nearest_color (f, cmap, &color);
7660 if (rc)
7662 ++ct_colors_allocated;
7664 p = (struct ct_color *) xmalloc (sizeof *p);
7665 p->r = color.red;
7666 p->g = color.green;
7667 p->b = color.blue;
7668 p->pixel = pixel;
7669 p->next = ct_table[i];
7670 ct_table[i] = p;
7672 else
7673 return FRAME_FOREGROUND_PIXEL (f);
7676 return p->pixel;
7680 /* Value is a vector of all pixel colors contained in the color table,
7681 allocated via xmalloc. Set *N to the number of colors. */
7683 static unsigned long *
7684 colors_in_color_table (n)
7685 int *n;
7687 int i, j;
7688 struct ct_color *p;
7689 unsigned long *colors;
7691 if (ct_colors_allocated == 0)
7693 *n = 0;
7694 colors = NULL;
7696 else
7698 colors = (unsigned long *) xmalloc (ct_colors_allocated
7699 * sizeof *colors);
7700 *n = ct_colors_allocated;
7702 for (i = j = 0; i < CT_SIZE; ++i)
7703 for (p = ct_table[i]; p; p = p->next)
7704 colors[j++] = p->pixel;
7707 return colors;
7712 /***********************************************************************
7713 Algorithms
7714 ***********************************************************************/
7716 static void x_laplace_write_row P_ ((struct frame *, long *,
7717 int, XImage *, int));
7718 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7719 XColor *, int, XImage *, int));
7720 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7721 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7722 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7724 /* Non-zero means draw a cross on images having `:conversion
7725 disabled'. */
7727 int cross_disabled_images;
7729 /* Edge detection matrices for different edge-detection
7730 strategies. */
7732 static int emboss_matrix[9] = {
7733 /* x - 1 x x + 1 */
7734 2, -1, 0, /* y - 1 */
7735 -1, 0, 1, /* y */
7736 0, 1, -2 /* y + 1 */
7739 static int laplace_matrix[9] = {
7740 /* x - 1 x x + 1 */
7741 1, 0, 0, /* y - 1 */
7742 0, 0, 0, /* y */
7743 0, 0, -1 /* y + 1 */
7746 /* Value is the intensity of the color whose red/green/blue values
7747 are R, G, and B. */
7749 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7752 /* On frame F, return an array of XColor structures describing image
7753 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7754 non-zero means also fill the red/green/blue members of the XColor
7755 structures. Value is a pointer to the array of XColors structures,
7756 allocated with xmalloc; it must be freed by the caller. */
7758 static XColor *
7759 x_to_xcolors (f, img, rgb_p)
7760 struct frame *f;
7761 struct image *img;
7762 int rgb_p;
7764 int x, y;
7765 XColor *colors, *p;
7766 XImage *ximg;
7768 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7770 /* Get the X image IMG->pixmap. */
7771 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7772 0, 0, img->width, img->height, ~0, ZPixmap);
7774 /* Fill the `pixel' members of the XColor array. I wished there
7775 were an easy and portable way to circumvent XGetPixel. */
7776 p = colors;
7777 for (y = 0; y < img->height; ++y)
7779 XColor *row = p;
7781 for (x = 0; x < img->width; ++x, ++p)
7782 p->pixel = XGetPixel (ximg, x, y);
7784 if (rgb_p)
7785 x_query_colors (f, row, img->width);
7788 XDestroyImage (ximg);
7789 return colors;
7793 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7794 RGB members are set. F is the frame on which this all happens.
7795 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7797 static void
7798 x_from_xcolors (f, img, colors)
7799 struct frame *f;
7800 struct image *img;
7801 XColor *colors;
7803 int x, y;
7804 XImage *oimg;
7805 Pixmap pixmap;
7806 XColor *p;
7808 init_color_table ();
7810 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7811 &oimg, &pixmap);
7812 p = colors;
7813 for (y = 0; y < img->height; ++y)
7814 for (x = 0; x < img->width; ++x, ++p)
7816 unsigned long pixel;
7817 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7818 XPutPixel (oimg, x, y, pixel);
7821 xfree (colors);
7822 x_clear_image_1 (f, img, 1, 0, 1);
7824 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7825 x_destroy_x_image (oimg);
7826 img->pixmap = pixmap;
7827 img->colors = colors_in_color_table (&img->ncolors);
7828 free_color_table ();
7832 /* On frame F, perform edge-detection on image IMG.
7834 MATRIX is a nine-element array specifying the transformation
7835 matrix. See emboss_matrix for an example.
7837 COLOR_ADJUST is a color adjustment added to each pixel of the
7838 outgoing image. */
7840 static void
7841 x_detect_edges (f, img, matrix, color_adjust)
7842 struct frame *f;
7843 struct image *img;
7844 int matrix[9], color_adjust;
7846 XColor *colors = x_to_xcolors (f, img, 1);
7847 XColor *new, *p;
7848 int x, y, i, sum;
7850 for (i = sum = 0; i < 9; ++i)
7851 sum += abs (matrix[i]);
7853 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7855 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
7857 for (y = 0; y < img->height; ++y)
7859 p = COLOR (new, 0, y);
7860 p->red = p->green = p->blue = 0xffff/2;
7861 p = COLOR (new, img->width - 1, y);
7862 p->red = p->green = p->blue = 0xffff/2;
7865 for (x = 1; x < img->width - 1; ++x)
7867 p = COLOR (new, x, 0);
7868 p->red = p->green = p->blue = 0xffff/2;
7869 p = COLOR (new, x, img->height - 1);
7870 p->red = p->green = p->blue = 0xffff/2;
7873 for (y = 1; y < img->height - 1; ++y)
7875 p = COLOR (new, 1, y);
7877 for (x = 1; x < img->width - 1; ++x, ++p)
7879 int r, g, b, y1, x1;
7881 r = g = b = i = 0;
7882 for (y1 = y - 1; y1 < y + 2; ++y1)
7883 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7884 if (matrix[i])
7886 XColor *t = COLOR (colors, x1, y1);
7887 r += matrix[i] * t->red;
7888 g += matrix[i] * t->green;
7889 b += matrix[i] * t->blue;
7892 r = (r / sum + color_adjust) & 0xffff;
7893 g = (g / sum + color_adjust) & 0xffff;
7894 b = (b / sum + color_adjust) & 0xffff;
7895 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7899 xfree (colors);
7900 x_from_xcolors (f, img, new);
7902 #undef COLOR
7906 /* Perform the pre-defined `emboss' edge-detection on image IMG
7907 on frame F. */
7909 static void
7910 x_emboss (f, img)
7911 struct frame *f;
7912 struct image *img;
7914 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7918 /* Perform the pre-defined `laplace' edge-detection on image IMG
7919 on frame F. */
7921 static void
7922 x_laplace (f, img)
7923 struct frame *f;
7924 struct image *img;
7926 x_detect_edges (f, img, laplace_matrix, 45000);
7930 /* Perform edge-detection on image IMG on frame F, with specified
7931 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7933 MATRIX must be either
7935 - a list of at least 9 numbers in row-major form
7936 - a vector of at least 9 numbers
7938 COLOR_ADJUST nil means use a default; otherwise it must be a
7939 number. */
7941 static void
7942 x_edge_detection (f, img, matrix, color_adjust)
7943 struct frame *f;
7944 struct image *img;
7945 Lisp_Object matrix, color_adjust;
7947 int i = 0;
7948 int trans[9];
7950 if (CONSP (matrix))
7952 for (i = 0;
7953 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7954 ++i, matrix = XCDR (matrix))
7955 trans[i] = XFLOATINT (XCAR (matrix));
7957 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7959 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7960 trans[i] = XFLOATINT (AREF (matrix, i));
7963 if (NILP (color_adjust))
7964 color_adjust = make_number (0xffff / 2);
7966 if (i == 9 && NUMBERP (color_adjust))
7967 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7971 /* Transform image IMG on frame F so that it looks disabled. */
7973 static void
7974 x_disable_image (f, img)
7975 struct frame *f;
7976 struct image *img;
7978 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7980 if (dpyinfo->n_planes >= 2)
7982 /* Color (or grayscale). Convert to gray, and equalize. Just
7983 drawing such images with a stipple can look very odd, so
7984 we're using this method instead. */
7985 XColor *colors = x_to_xcolors (f, img, 1);
7986 XColor *p, *end;
7987 const int h = 15000;
7988 const int l = 30000;
7990 for (p = colors, end = colors + img->width * img->height;
7991 p < end;
7992 ++p)
7994 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7995 int i2 = (0xffff - h - l) * i / 0xffff + l;
7996 p->red = p->green = p->blue = i2;
7999 x_from_xcolors (f, img, colors);
8002 /* Draw a cross over the disabled image, if we must or if we
8003 should. */
8004 if (dpyinfo->n_planes < 2 || cross_disabled_images)
8006 Display *dpy = FRAME_X_DISPLAY (f);
8007 GC gc;
8009 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
8010 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
8011 XDrawLine (dpy, img->pixmap, gc, 0, 0,
8012 img->width - 1, img->height - 1);
8013 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
8014 img->width - 1, 0);
8015 XFreeGC (dpy, gc);
8017 if (img->mask)
8019 gc = XCreateGC (dpy, img->mask, 0, NULL);
8020 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8021 XDrawLine (dpy, img->mask, gc, 0, 0,
8022 img->width - 1, img->height - 1);
8023 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8024 img->width - 1, 0);
8025 XFreeGC (dpy, gc);
8031 /* Build a mask for image IMG which is used on frame F. FILE is the
8032 name of an image file, for error messages. HOW determines how to
8033 determine the background color of IMG. If it is a list '(R G B)',
8034 with R, G, and B being integers >= 0, take that as the color of the
8035 background. Otherwise, determine the background color of IMG
8036 heuristically. Value is non-zero if successful. */
8038 static int
8039 x_build_heuristic_mask (f, img, how)
8040 struct frame *f;
8041 struct image *img;
8042 Lisp_Object how;
8044 Display *dpy = FRAME_X_DISPLAY (f);
8045 XImage *ximg, *mask_img;
8046 int x, y, rc, look_at_corners_p;
8047 unsigned long bg = 0;
8049 if (img->mask)
8051 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8052 img->mask = None;
8055 /* Create an image and pixmap serving as mask. */
8056 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8057 &mask_img, &img->mask);
8058 if (!rc)
8059 return 0;
8061 /* Get the X image of IMG->pixmap. */
8062 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8063 ~0, ZPixmap);
8065 /* Determine the background color of ximg. If HOW is `(R G B)'
8066 take that as color. Otherwise, try to determine the color
8067 heuristically. */
8068 look_at_corners_p = 1;
8070 if (CONSP (how))
8072 int rgb[3], i;
8074 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
8076 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8077 how = XCDR (how);
8080 if (i == 3 && NILP (how))
8082 char color_name[30];
8083 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8084 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
8085 look_at_corners_p = 0;
8089 if (look_at_corners_p)
8091 unsigned long corners[4];
8092 int i, best_count;
8094 /* Get the colors at the corners of ximg. */
8095 corners[0] = XGetPixel (ximg, 0, 0);
8096 corners[1] = XGetPixel (ximg, img->width - 1, 0);
8097 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
8098 corners[3] = XGetPixel (ximg, 0, img->height - 1);
8100 /* Choose the most frequently found color as background. */
8101 for (i = best_count = 0; i < 4; ++i)
8103 int j, n;
8105 for (j = n = 0; j < 4; ++j)
8106 if (corners[i] == corners[j])
8107 ++n;
8109 if (n > best_count)
8110 bg = corners[i], best_count = n;
8114 /* Set all bits in mask_img to 1 whose color in ximg is different
8115 from the background color bg. */
8116 for (y = 0; y < img->height; ++y)
8117 for (x = 0; x < img->width; ++x)
8118 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8120 /* Put mask_img into img->mask. */
8121 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8122 x_destroy_x_image (mask_img);
8123 XDestroyImage (ximg);
8125 return 1;
8130 /***********************************************************************
8131 PBM (mono, gray, color)
8132 ***********************************************************************/
8134 static int pbm_image_p P_ ((Lisp_Object object));
8135 static int pbm_load P_ ((struct frame *f, struct image *img));
8136 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8138 /* The symbol `pbm' identifying images of this type. */
8140 Lisp_Object Qpbm;
8142 /* Indices of image specification fields in gs_format, below. */
8144 enum pbm_keyword_index
8146 PBM_TYPE,
8147 PBM_FILE,
8148 PBM_DATA,
8149 PBM_ASCENT,
8150 PBM_MARGIN,
8151 PBM_RELIEF,
8152 PBM_ALGORITHM,
8153 PBM_HEURISTIC_MASK,
8154 PBM_MASK,
8155 PBM_FOREGROUND,
8156 PBM_BACKGROUND,
8157 PBM_LAST
8160 /* Vector of image_keyword structures describing the format
8161 of valid user-defined image specifications. */
8163 static struct image_keyword pbm_format[PBM_LAST] =
8165 {":type", IMAGE_SYMBOL_VALUE, 1},
8166 {":file", IMAGE_STRING_VALUE, 0},
8167 {":data", IMAGE_STRING_VALUE, 0},
8168 {":ascent", IMAGE_ASCENT_VALUE, 0},
8169 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8170 {":relief", IMAGE_INTEGER_VALUE, 0},
8171 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8172 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8173 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8174 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8175 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8178 /* Structure describing the image type `pbm'. */
8180 static struct image_type pbm_type =
8182 &Qpbm,
8183 pbm_image_p,
8184 pbm_load,
8185 x_clear_image,
8186 NULL
8190 /* Return non-zero if OBJECT is a valid PBM image specification. */
8192 static int
8193 pbm_image_p (object)
8194 Lisp_Object object;
8196 struct image_keyword fmt[PBM_LAST];
8198 bcopy (pbm_format, fmt, sizeof fmt);
8200 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8201 return 0;
8203 /* Must specify either :data or :file. */
8204 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8208 /* Scan a decimal number from *S and return it. Advance *S while
8209 reading the number. END is the end of the string. Value is -1 at
8210 end of input. */
8212 static int
8213 pbm_scan_number (s, end)
8214 unsigned char **s, *end;
8216 int c = 0, val = -1;
8218 while (*s < end)
8220 /* Skip white-space. */
8221 while (*s < end && (c = *(*s)++, isspace (c)))
8224 if (c == '#')
8226 /* Skip comment to end of line. */
8227 while (*s < end && (c = *(*s)++, c != '\n'))
8230 else if (isdigit (c))
8232 /* Read decimal number. */
8233 val = c - '0';
8234 while (*s < end && (c = *(*s)++, isdigit (c)))
8235 val = 10 * val + c - '0';
8236 break;
8238 else
8239 break;
8242 return val;
8246 /* Load PBM image IMG for use on frame F. */
8248 static int
8249 pbm_load (f, img)
8250 struct frame *f;
8251 struct image *img;
8253 int raw_p, x, y;
8254 int width, height, max_color_idx = 0;
8255 XImage *ximg;
8256 Lisp_Object file, specified_file;
8257 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8258 struct gcpro gcpro1;
8259 unsigned char *contents = NULL;
8260 unsigned char *end, *p;
8261 int size;
8263 specified_file = image_spec_value (img->spec, QCfile, NULL);
8264 file = Qnil;
8265 GCPRO1 (file);
8267 if (STRINGP (specified_file))
8269 file = x_find_image_file (specified_file);
8270 if (!STRINGP (file))
8272 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8273 UNGCPRO;
8274 return 0;
8277 contents = slurp_file (XSTRING (file)->data, &size);
8278 if (contents == NULL)
8280 image_error ("Error reading `%s'", file, Qnil);
8281 UNGCPRO;
8282 return 0;
8285 p = contents;
8286 end = contents + size;
8288 else
8290 Lisp_Object data;
8291 data = image_spec_value (img->spec, QCdata, NULL);
8292 p = XSTRING (data)->data;
8293 end = p + STRING_BYTES (XSTRING (data));
8296 /* Check magic number. */
8297 if (end - p < 2 || *p++ != 'P')
8299 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8300 error:
8301 xfree (contents);
8302 UNGCPRO;
8303 return 0;
8306 switch (*p++)
8308 case '1':
8309 raw_p = 0, type = PBM_MONO;
8310 break;
8312 case '2':
8313 raw_p = 0, type = PBM_GRAY;
8314 break;
8316 case '3':
8317 raw_p = 0, type = PBM_COLOR;
8318 break;
8320 case '4':
8321 raw_p = 1, type = PBM_MONO;
8322 break;
8324 case '5':
8325 raw_p = 1, type = PBM_GRAY;
8326 break;
8328 case '6':
8329 raw_p = 1, type = PBM_COLOR;
8330 break;
8332 default:
8333 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8334 goto error;
8337 /* Read width, height, maximum color-component. Characters
8338 starting with `#' up to the end of a line are ignored. */
8339 width = pbm_scan_number (&p, end);
8340 height = pbm_scan_number (&p, end);
8342 if (type != PBM_MONO)
8344 max_color_idx = pbm_scan_number (&p, end);
8345 if (raw_p && max_color_idx > 255)
8346 max_color_idx = 255;
8349 if (width < 0
8350 || height < 0
8351 || (type != PBM_MONO && max_color_idx < 0))
8352 goto error;
8354 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8355 &ximg, &img->pixmap))
8356 goto error;
8358 /* Initialize the color hash table. */
8359 init_color_table ();
8361 if (type == PBM_MONO)
8363 int c = 0, g;
8364 struct image_keyword fmt[PBM_LAST];
8365 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8366 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8368 /* Parse the image specification. */
8369 bcopy (pbm_format, fmt, sizeof fmt);
8370 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8372 /* Get foreground and background colors, maybe allocate colors. */
8373 if (fmt[PBM_FOREGROUND].count
8374 && STRINGP (fmt[PBM_FOREGROUND].value))
8375 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8376 if (fmt[PBM_BACKGROUND].count
8377 && STRINGP (fmt[PBM_BACKGROUND].value))
8378 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8380 for (y = 0; y < height; ++y)
8381 for (x = 0; x < width; ++x)
8383 if (raw_p)
8385 if ((x & 7) == 0)
8386 c = *p++;
8387 g = c & 0x80;
8388 c <<= 1;
8390 else
8391 g = pbm_scan_number (&p, end);
8393 XPutPixel (ximg, x, y, g ? fg : bg);
8396 else
8398 for (y = 0; y < height; ++y)
8399 for (x = 0; x < width; ++x)
8401 int r, g, b;
8403 if (type == PBM_GRAY)
8404 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8405 else if (raw_p)
8407 r = *p++;
8408 g = *p++;
8409 b = *p++;
8411 else
8413 r = pbm_scan_number (&p, end);
8414 g = pbm_scan_number (&p, end);
8415 b = pbm_scan_number (&p, end);
8418 if (r < 0 || g < 0 || b < 0)
8420 xfree (ximg->data);
8421 ximg->data = NULL;
8422 XDestroyImage (ximg);
8423 image_error ("Invalid pixel value in image `%s'",
8424 img->spec, Qnil);
8425 goto error;
8428 /* RGB values are now in the range 0..max_color_idx.
8429 Scale this to the range 0..0xffff supported by X. */
8430 r = (double) r * 65535 / max_color_idx;
8431 g = (double) g * 65535 / max_color_idx;
8432 b = (double) b * 65535 / max_color_idx;
8433 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8437 /* Store in IMG->colors the colors allocated for the image, and
8438 free the color table. */
8439 img->colors = colors_in_color_table (&img->ncolors);
8440 free_color_table ();
8442 /* Put the image into a pixmap. */
8443 x_put_x_image (f, ximg, img->pixmap, width, height);
8444 x_destroy_x_image (ximg);
8446 img->width = width;
8447 img->height = height;
8449 UNGCPRO;
8450 xfree (contents);
8451 return 1;
8456 /***********************************************************************
8458 ***********************************************************************/
8460 #if HAVE_PNG
8462 #include <png.h>
8464 /* Function prototypes. */
8466 static int png_image_p P_ ((Lisp_Object object));
8467 static int png_load P_ ((struct frame *f, struct image *img));
8469 /* The symbol `png' identifying images of this type. */
8471 Lisp_Object Qpng;
8473 /* Indices of image specification fields in png_format, below. */
8475 enum png_keyword_index
8477 PNG_TYPE,
8478 PNG_DATA,
8479 PNG_FILE,
8480 PNG_ASCENT,
8481 PNG_MARGIN,
8482 PNG_RELIEF,
8483 PNG_ALGORITHM,
8484 PNG_HEURISTIC_MASK,
8485 PNG_MASK,
8486 PNG_LAST
8489 /* Vector of image_keyword structures describing the format
8490 of valid user-defined image specifications. */
8492 static struct image_keyword png_format[PNG_LAST] =
8494 {":type", IMAGE_SYMBOL_VALUE, 1},
8495 {":data", IMAGE_STRING_VALUE, 0},
8496 {":file", IMAGE_STRING_VALUE, 0},
8497 {":ascent", IMAGE_ASCENT_VALUE, 0},
8498 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8499 {":relief", IMAGE_INTEGER_VALUE, 0},
8500 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8501 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8502 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8505 /* Structure describing the image type `png'. */
8507 static struct image_type png_type =
8509 &Qpng,
8510 png_image_p,
8511 png_load,
8512 x_clear_image,
8513 NULL
8517 /* Return non-zero if OBJECT is a valid PNG image specification. */
8519 static int
8520 png_image_p (object)
8521 Lisp_Object object;
8523 struct image_keyword fmt[PNG_LAST];
8524 bcopy (png_format, fmt, sizeof fmt);
8526 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8527 return 0;
8529 /* Must specify either the :data or :file keyword. */
8530 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8534 /* Error and warning handlers installed when the PNG library
8535 is initialized. */
8537 static void
8538 my_png_error (png_ptr, msg)
8539 png_struct *png_ptr;
8540 char *msg;
8542 xassert (png_ptr != NULL);
8543 image_error ("PNG error: %s", build_string (msg), Qnil);
8544 longjmp (png_ptr->jmpbuf, 1);
8548 static void
8549 my_png_warning (png_ptr, msg)
8550 png_struct *png_ptr;
8551 char *msg;
8553 xassert (png_ptr != NULL);
8554 image_error ("PNG warning: %s", build_string (msg), Qnil);
8557 /* Memory source for PNG decoding. */
8559 struct png_memory_storage
8561 unsigned char *bytes; /* The data */
8562 size_t len; /* How big is it? */
8563 int index; /* Where are we? */
8567 /* Function set as reader function when reading PNG image from memory.
8568 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8569 bytes from the input to DATA. */
8571 static void
8572 png_read_from_memory (png_ptr, data, length)
8573 png_structp png_ptr;
8574 png_bytep data;
8575 png_size_t length;
8577 struct png_memory_storage *tbr
8578 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8580 if (length > tbr->len - tbr->index)
8581 png_error (png_ptr, "Read error");
8583 bcopy (tbr->bytes + tbr->index, data, length);
8584 tbr->index = tbr->index + length;
8587 /* Load PNG image IMG for use on frame F. Value is non-zero if
8588 successful. */
8590 static int
8591 png_load (f, img)
8592 struct frame *f;
8593 struct image *img;
8595 Lisp_Object file, specified_file;
8596 Lisp_Object specified_data;
8597 int x, y, i;
8598 XImage *ximg, *mask_img = NULL;
8599 struct gcpro gcpro1;
8600 png_struct *png_ptr = NULL;
8601 png_info *info_ptr = NULL, *end_info = NULL;
8602 FILE *volatile fp = NULL;
8603 png_byte sig[8];
8604 png_byte * volatile pixels = NULL;
8605 png_byte ** volatile rows = NULL;
8606 png_uint_32 width, height;
8607 int bit_depth, color_type, interlace_type;
8608 png_byte channels;
8609 png_uint_32 row_bytes;
8610 int transparent_p;
8611 char *gamma_str;
8612 double screen_gamma, image_gamma;
8613 int intent;
8614 struct png_memory_storage tbr; /* Data to be read */
8616 /* Find out what file to load. */
8617 specified_file = image_spec_value (img->spec, QCfile, NULL);
8618 specified_data = image_spec_value (img->spec, QCdata, NULL);
8619 file = Qnil;
8620 GCPRO1 (file);
8622 if (NILP (specified_data))
8624 file = x_find_image_file (specified_file);
8625 if (!STRINGP (file))
8627 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8628 UNGCPRO;
8629 return 0;
8632 /* Open the image file. */
8633 fp = fopen (XSTRING (file)->data, "rb");
8634 if (!fp)
8636 image_error ("Cannot open image file `%s'", file, Qnil);
8637 UNGCPRO;
8638 fclose (fp);
8639 return 0;
8642 /* Check PNG signature. */
8643 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8644 || !png_check_sig (sig, sizeof sig))
8646 image_error ("Not a PNG file: `%s'", file, Qnil);
8647 UNGCPRO;
8648 fclose (fp);
8649 return 0;
8652 else
8654 /* Read from memory. */
8655 tbr.bytes = XSTRING (specified_data)->data;
8656 tbr.len = STRING_BYTES (XSTRING (specified_data));
8657 tbr.index = 0;
8659 /* Check PNG signature. */
8660 if (tbr.len < sizeof sig
8661 || !png_check_sig (tbr.bytes, sizeof sig))
8663 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8664 UNGCPRO;
8665 return 0;
8668 /* Need to skip past the signature. */
8669 tbr.bytes += sizeof (sig);
8672 /* Initialize read and info structs for PNG lib. */
8673 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8674 my_png_error, my_png_warning);
8675 if (!png_ptr)
8677 if (fp) fclose (fp);
8678 UNGCPRO;
8679 return 0;
8682 info_ptr = png_create_info_struct (png_ptr);
8683 if (!info_ptr)
8685 png_destroy_read_struct (&png_ptr, NULL, NULL);
8686 if (fp) fclose (fp);
8687 UNGCPRO;
8688 return 0;
8691 end_info = png_create_info_struct (png_ptr);
8692 if (!end_info)
8694 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8695 if (fp) fclose (fp);
8696 UNGCPRO;
8697 return 0;
8700 /* Set error jump-back. We come back here when the PNG library
8701 detects an error. */
8702 if (setjmp (png_ptr->jmpbuf))
8704 error:
8705 if (png_ptr)
8706 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8707 xfree (pixels);
8708 xfree (rows);
8709 if (fp) fclose (fp);
8710 UNGCPRO;
8711 return 0;
8714 /* Read image info. */
8715 if (!NILP (specified_data))
8716 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8717 else
8718 png_init_io (png_ptr, fp);
8720 png_set_sig_bytes (png_ptr, sizeof sig);
8721 png_read_info (png_ptr, info_ptr);
8722 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8723 &interlace_type, NULL, NULL);
8725 /* If image contains simply transparency data, we prefer to
8726 construct a clipping mask. */
8727 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8728 transparent_p = 1;
8729 else
8730 transparent_p = 0;
8732 /* This function is easier to write if we only have to handle
8733 one data format: RGB or RGBA with 8 bits per channel. Let's
8734 transform other formats into that format. */
8736 /* Strip more than 8 bits per channel. */
8737 if (bit_depth == 16)
8738 png_set_strip_16 (png_ptr);
8740 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8741 if available. */
8742 png_set_expand (png_ptr);
8744 /* Convert grayscale images to RGB. */
8745 if (color_type == PNG_COLOR_TYPE_GRAY
8746 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8747 png_set_gray_to_rgb (png_ptr);
8749 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8750 gamma_str = getenv ("SCREEN_GAMMA");
8751 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8753 /* Tell the PNG lib to handle gamma correction for us. */
8755 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8756 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8757 /* There is a special chunk in the image specifying the gamma. */
8758 png_set_sRGB (png_ptr, info_ptr, intent);
8759 else
8760 #endif
8761 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8762 /* Image contains gamma information. */
8763 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8764 else
8765 /* Use a default of 0.5 for the image gamma. */
8766 png_set_gamma (png_ptr, screen_gamma, 0.5);
8768 /* Handle alpha channel by combining the image with a background
8769 color. Do this only if a real alpha channel is supplied. For
8770 simple transparency, we prefer a clipping mask. */
8771 if (!transparent_p)
8773 png_color_16 *image_background;
8775 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8776 /* Image contains a background color with which to
8777 combine the image. */
8778 png_set_background (png_ptr, image_background,
8779 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8780 else
8782 /* Image does not contain a background color with which
8783 to combine the image data via an alpha channel. Use
8784 the frame's background instead. */
8785 XColor color;
8786 Colormap cmap;
8787 png_color_16 frame_background;
8789 cmap = FRAME_X_COLORMAP (f);
8790 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8791 x_query_color (f, &color);
8793 bzero (&frame_background, sizeof frame_background);
8794 frame_background.red = color.red;
8795 frame_background.green = color.green;
8796 frame_background.blue = color.blue;
8798 png_set_background (png_ptr, &frame_background,
8799 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8803 /* Update info structure. */
8804 png_read_update_info (png_ptr, info_ptr);
8806 /* Get number of channels. Valid values are 1 for grayscale images
8807 and images with a palette, 2 for grayscale images with transparency
8808 information (alpha channel), 3 for RGB images, and 4 for RGB
8809 images with alpha channel, i.e. RGBA. If conversions above were
8810 sufficient we should only have 3 or 4 channels here. */
8811 channels = png_get_channels (png_ptr, info_ptr);
8812 xassert (channels == 3 || channels == 4);
8814 /* Number of bytes needed for one row of the image. */
8815 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8817 /* Allocate memory for the image. */
8818 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8819 rows = (png_byte **) xmalloc (height * sizeof *rows);
8820 for (i = 0; i < height; ++i)
8821 rows[i] = pixels + i * row_bytes;
8823 /* Read the entire image. */
8824 png_read_image (png_ptr, rows);
8825 png_read_end (png_ptr, info_ptr);
8826 if (fp)
8828 fclose (fp);
8829 fp = NULL;
8832 /* Create the X image and pixmap. */
8833 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8834 &img->pixmap))
8835 goto error;
8837 /* Create an image and pixmap serving as mask if the PNG image
8838 contains an alpha channel. */
8839 if (channels == 4
8840 && !transparent_p
8841 && !x_create_x_image_and_pixmap (f, width, height, 1,
8842 &mask_img, &img->mask))
8844 x_destroy_x_image (ximg);
8845 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8846 img->pixmap = None;
8847 goto error;
8850 /* Fill the X image and mask from PNG data. */
8851 init_color_table ();
8853 for (y = 0; y < height; ++y)
8855 png_byte *p = rows[y];
8857 for (x = 0; x < width; ++x)
8859 unsigned r, g, b;
8861 r = *p++ << 8;
8862 g = *p++ << 8;
8863 b = *p++ << 8;
8864 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8866 /* An alpha channel, aka mask channel, associates variable
8867 transparency with an image. Where other image formats
8868 support binary transparency---fully transparent or fully
8869 opaque---PNG allows up to 254 levels of partial transparency.
8870 The PNG library implements partial transparency by combining
8871 the image with a specified background color.
8873 I'm not sure how to handle this here nicely: because the
8874 background on which the image is displayed may change, for
8875 real alpha channel support, it would be necessary to create
8876 a new image for each possible background.
8878 What I'm doing now is that a mask is created if we have
8879 boolean transparency information. Otherwise I'm using
8880 the frame's background color to combine the image with. */
8882 if (channels == 4)
8884 if (mask_img)
8885 XPutPixel (mask_img, x, y, *p > 0);
8886 ++p;
8891 /* Remember colors allocated for this image. */
8892 img->colors = colors_in_color_table (&img->ncolors);
8893 free_color_table ();
8895 /* Clean up. */
8896 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8897 xfree (rows);
8898 xfree (pixels);
8900 img->width = width;
8901 img->height = height;
8903 /* Put the image into the pixmap, then free the X image and its buffer. */
8904 x_put_x_image (f, ximg, img->pixmap, width, height);
8905 x_destroy_x_image (ximg);
8907 /* Same for the mask. */
8908 if (mask_img)
8910 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8911 x_destroy_x_image (mask_img);
8914 UNGCPRO;
8915 return 1;
8918 #endif /* HAVE_PNG != 0 */
8922 /***********************************************************************
8923 JPEG
8924 ***********************************************************************/
8926 #if HAVE_JPEG
8928 /* Work around a warning about HAVE_STDLIB_H being redefined in
8929 jconfig.h. */
8930 #ifdef HAVE_STDLIB_H
8931 #define HAVE_STDLIB_H_1
8932 #undef HAVE_STDLIB_H
8933 #endif /* HAVE_STLIB_H */
8935 #include <jpeglib.h>
8936 #include <jerror.h>
8937 #include <setjmp.h>
8939 #ifdef HAVE_STLIB_H_1
8940 #define HAVE_STDLIB_H 1
8941 #endif
8943 static int jpeg_image_p P_ ((Lisp_Object object));
8944 static int jpeg_load P_ ((struct frame *f, struct image *img));
8946 /* The symbol `jpeg' identifying images of this type. */
8948 Lisp_Object Qjpeg;
8950 /* Indices of image specification fields in gs_format, below. */
8952 enum jpeg_keyword_index
8954 JPEG_TYPE,
8955 JPEG_DATA,
8956 JPEG_FILE,
8957 JPEG_ASCENT,
8958 JPEG_MARGIN,
8959 JPEG_RELIEF,
8960 JPEG_ALGORITHM,
8961 JPEG_HEURISTIC_MASK,
8962 JPEG_MASK,
8963 JPEG_LAST
8966 /* Vector of image_keyword structures describing the format
8967 of valid user-defined image specifications. */
8969 static struct image_keyword jpeg_format[JPEG_LAST] =
8971 {":type", IMAGE_SYMBOL_VALUE, 1},
8972 {":data", IMAGE_STRING_VALUE, 0},
8973 {":file", IMAGE_STRING_VALUE, 0},
8974 {":ascent", IMAGE_ASCENT_VALUE, 0},
8975 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8976 {":relief", IMAGE_INTEGER_VALUE, 0},
8977 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8978 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8979 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8982 /* Structure describing the image type `jpeg'. */
8984 static struct image_type jpeg_type =
8986 &Qjpeg,
8987 jpeg_image_p,
8988 jpeg_load,
8989 x_clear_image,
8990 NULL
8994 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8996 static int
8997 jpeg_image_p (object)
8998 Lisp_Object object;
9000 struct image_keyword fmt[JPEG_LAST];
9002 bcopy (jpeg_format, fmt, sizeof fmt);
9004 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
9005 return 0;
9007 /* Must specify either the :data or :file keyword. */
9008 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9012 struct my_jpeg_error_mgr
9014 struct jpeg_error_mgr pub;
9015 jmp_buf setjmp_buffer;
9019 static void
9020 my_error_exit (cinfo)
9021 j_common_ptr cinfo;
9023 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9024 longjmp (mgr->setjmp_buffer, 1);
9028 /* Init source method for JPEG data source manager. Called by
9029 jpeg_read_header() before any data is actually read. See
9030 libjpeg.doc from the JPEG lib distribution. */
9032 static void
9033 our_init_source (cinfo)
9034 j_decompress_ptr cinfo;
9039 /* Fill input buffer method for JPEG data source manager. Called
9040 whenever more data is needed. We read the whole image in one step,
9041 so this only adds a fake end of input marker at the end. */
9043 static boolean
9044 our_fill_input_buffer (cinfo)
9045 j_decompress_ptr cinfo;
9047 /* Insert a fake EOI marker. */
9048 struct jpeg_source_mgr *src = cinfo->src;
9049 static JOCTET buffer[2];
9051 buffer[0] = (JOCTET) 0xFF;
9052 buffer[1] = (JOCTET) JPEG_EOI;
9054 src->next_input_byte = buffer;
9055 src->bytes_in_buffer = 2;
9056 return TRUE;
9060 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9061 is the JPEG data source manager. */
9063 static void
9064 our_skip_input_data (cinfo, num_bytes)
9065 j_decompress_ptr cinfo;
9066 long num_bytes;
9068 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9070 if (src)
9072 if (num_bytes > src->bytes_in_buffer)
9073 ERREXIT (cinfo, JERR_INPUT_EOF);
9075 src->bytes_in_buffer -= num_bytes;
9076 src->next_input_byte += num_bytes;
9081 /* Method to terminate data source. Called by
9082 jpeg_finish_decompress() after all data has been processed. */
9084 static void
9085 our_term_source (cinfo)
9086 j_decompress_ptr cinfo;
9091 /* Set up the JPEG lib for reading an image from DATA which contains
9092 LEN bytes. CINFO is the decompression info structure created for
9093 reading the image. */
9095 static void
9096 jpeg_memory_src (cinfo, data, len)
9097 j_decompress_ptr cinfo;
9098 JOCTET *data;
9099 unsigned int len;
9101 struct jpeg_source_mgr *src;
9103 if (cinfo->src == NULL)
9105 /* First time for this JPEG object? */
9106 cinfo->src = (struct jpeg_source_mgr *)
9107 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9108 sizeof (struct jpeg_source_mgr));
9109 src = (struct jpeg_source_mgr *) cinfo->src;
9110 src->next_input_byte = data;
9113 src = (struct jpeg_source_mgr *) cinfo->src;
9114 src->init_source = our_init_source;
9115 src->fill_input_buffer = our_fill_input_buffer;
9116 src->skip_input_data = our_skip_input_data;
9117 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9118 src->term_source = our_term_source;
9119 src->bytes_in_buffer = len;
9120 src->next_input_byte = data;
9124 /* Load image IMG for use on frame F. Patterned after example.c
9125 from the JPEG lib. */
9127 static int
9128 jpeg_load (f, img)
9129 struct frame *f;
9130 struct image *img;
9132 struct jpeg_decompress_struct cinfo;
9133 struct my_jpeg_error_mgr mgr;
9134 Lisp_Object file, specified_file;
9135 Lisp_Object specified_data;
9136 FILE * volatile fp = NULL;
9137 JSAMPARRAY buffer;
9138 int row_stride, x, y;
9139 XImage *ximg = NULL;
9140 int rc;
9141 unsigned long *colors;
9142 int width, height;
9143 struct gcpro gcpro1;
9145 /* Open the JPEG file. */
9146 specified_file = image_spec_value (img->spec, QCfile, NULL);
9147 specified_data = image_spec_value (img->spec, QCdata, NULL);
9148 file = Qnil;
9149 GCPRO1 (file);
9151 if (NILP (specified_data))
9153 file = x_find_image_file (specified_file);
9154 if (!STRINGP (file))
9156 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9157 UNGCPRO;
9158 return 0;
9161 fp = fopen (XSTRING (file)->data, "r");
9162 if (fp == NULL)
9164 image_error ("Cannot open `%s'", file, Qnil);
9165 UNGCPRO;
9166 return 0;
9170 /* Customize libjpeg's error handling to call my_error_exit when an
9171 error is detected. This function will perform a longjmp. */
9172 cinfo.err = jpeg_std_error (&mgr.pub);
9173 mgr.pub.error_exit = my_error_exit;
9175 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9177 if (rc == 1)
9179 /* Called from my_error_exit. Display a JPEG error. */
9180 char buffer[JMSG_LENGTH_MAX];
9181 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9182 image_error ("Error reading JPEG image `%s': %s", img->spec,
9183 build_string (buffer));
9186 /* Close the input file and destroy the JPEG object. */
9187 if (fp)
9188 fclose ((FILE *) fp);
9189 jpeg_destroy_decompress (&cinfo);
9191 /* If we already have an XImage, free that. */
9192 x_destroy_x_image (ximg);
9194 /* Free pixmap and colors. */
9195 x_clear_image (f, img);
9197 UNGCPRO;
9198 return 0;
9201 /* Create the JPEG decompression object. Let it read from fp.
9202 Read the JPEG image header. */
9203 jpeg_create_decompress (&cinfo);
9205 if (NILP (specified_data))
9206 jpeg_stdio_src (&cinfo, (FILE *) fp);
9207 else
9208 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
9209 STRING_BYTES (XSTRING (specified_data)));
9211 jpeg_read_header (&cinfo, TRUE);
9213 /* Customize decompression so that color quantization will be used.
9214 Start decompression. */
9215 cinfo.quantize_colors = TRUE;
9216 jpeg_start_decompress (&cinfo);
9217 width = img->width = cinfo.output_width;
9218 height = img->height = cinfo.output_height;
9220 /* Create X image and pixmap. */
9221 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9222 longjmp (mgr.setjmp_buffer, 2);
9224 /* Allocate colors. When color quantization is used,
9225 cinfo.actual_number_of_colors has been set with the number of
9226 colors generated, and cinfo.colormap is a two-dimensional array
9227 of color indices in the range 0..cinfo.actual_number_of_colors.
9228 No more than 255 colors will be generated. */
9230 int i, ir, ig, ib;
9232 if (cinfo.out_color_components > 2)
9233 ir = 0, ig = 1, ib = 2;
9234 else if (cinfo.out_color_components > 1)
9235 ir = 0, ig = 1, ib = 0;
9236 else
9237 ir = 0, ig = 0, ib = 0;
9239 /* Use the color table mechanism because it handles colors that
9240 cannot be allocated nicely. Such colors will be replaced with
9241 a default color, and we don't have to care about which colors
9242 can be freed safely, and which can't. */
9243 init_color_table ();
9244 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9245 * sizeof *colors);
9247 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9249 /* Multiply RGB values with 255 because X expects RGB values
9250 in the range 0..0xffff. */
9251 int r = cinfo.colormap[ir][i] << 8;
9252 int g = cinfo.colormap[ig][i] << 8;
9253 int b = cinfo.colormap[ib][i] << 8;
9254 colors[i] = lookup_rgb_color (f, r, g, b);
9257 /* Remember those colors actually allocated. */
9258 img->colors = colors_in_color_table (&img->ncolors);
9259 free_color_table ();
9262 /* Read pixels. */
9263 row_stride = width * cinfo.output_components;
9264 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9265 row_stride, 1);
9266 for (y = 0; y < height; ++y)
9268 jpeg_read_scanlines (&cinfo, buffer, 1);
9269 for (x = 0; x < cinfo.output_width; ++x)
9270 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9273 /* Clean up. */
9274 jpeg_finish_decompress (&cinfo);
9275 jpeg_destroy_decompress (&cinfo);
9276 if (fp)
9277 fclose ((FILE *) fp);
9279 /* Put the image into the pixmap. */
9280 x_put_x_image (f, ximg, img->pixmap, width, height);
9281 x_destroy_x_image (ximg);
9282 UNGCPRO;
9283 return 1;
9286 #endif /* HAVE_JPEG */
9290 /***********************************************************************
9291 TIFF
9292 ***********************************************************************/
9294 #if HAVE_TIFF
9296 #include <tiffio.h>
9298 static int tiff_image_p P_ ((Lisp_Object object));
9299 static int tiff_load P_ ((struct frame *f, struct image *img));
9301 /* The symbol `tiff' identifying images of this type. */
9303 Lisp_Object Qtiff;
9305 /* Indices of image specification fields in tiff_format, below. */
9307 enum tiff_keyword_index
9309 TIFF_TYPE,
9310 TIFF_DATA,
9311 TIFF_FILE,
9312 TIFF_ASCENT,
9313 TIFF_MARGIN,
9314 TIFF_RELIEF,
9315 TIFF_ALGORITHM,
9316 TIFF_HEURISTIC_MASK,
9317 TIFF_MASK,
9318 TIFF_LAST
9321 /* Vector of image_keyword structures describing the format
9322 of valid user-defined image specifications. */
9324 static struct image_keyword tiff_format[TIFF_LAST] =
9326 {":type", IMAGE_SYMBOL_VALUE, 1},
9327 {":data", IMAGE_STRING_VALUE, 0},
9328 {":file", IMAGE_STRING_VALUE, 0},
9329 {":ascent", IMAGE_ASCENT_VALUE, 0},
9330 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9331 {":relief", IMAGE_INTEGER_VALUE, 0},
9332 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9333 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9334 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9337 /* Structure describing the image type `tiff'. */
9339 static struct image_type tiff_type =
9341 &Qtiff,
9342 tiff_image_p,
9343 tiff_load,
9344 x_clear_image,
9345 NULL
9349 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9351 static int
9352 tiff_image_p (object)
9353 Lisp_Object object;
9355 struct image_keyword fmt[TIFF_LAST];
9356 bcopy (tiff_format, fmt, sizeof fmt);
9358 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9359 return 0;
9361 /* Must specify either the :data or :file keyword. */
9362 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9366 /* Reading from a memory buffer for TIFF images Based on the PNG
9367 memory source, but we have to provide a lot of extra functions.
9368 Blah.
9370 We really only need to implement read and seek, but I am not
9371 convinced that the TIFF library is smart enough not to destroy
9372 itself if we only hand it the function pointers we need to
9373 override. */
9375 typedef struct
9377 unsigned char *bytes;
9378 size_t len;
9379 int index;
9381 tiff_memory_source;
9384 static size_t
9385 tiff_read_from_memory (data, buf, size)
9386 thandle_t data;
9387 tdata_t buf;
9388 tsize_t size;
9390 tiff_memory_source *src = (tiff_memory_source *) data;
9392 if (size > src->len - src->index)
9393 return (size_t) -1;
9394 bcopy (src->bytes + src->index, buf, size);
9395 src->index += size;
9396 return size;
9400 static size_t
9401 tiff_write_from_memory (data, buf, size)
9402 thandle_t data;
9403 tdata_t buf;
9404 tsize_t size;
9406 return (size_t) -1;
9410 static toff_t
9411 tiff_seek_in_memory (data, off, whence)
9412 thandle_t data;
9413 toff_t off;
9414 int whence;
9416 tiff_memory_source *src = (tiff_memory_source *) data;
9417 int idx;
9419 switch (whence)
9421 case SEEK_SET: /* Go from beginning of source. */
9422 idx = off;
9423 break;
9425 case SEEK_END: /* Go from end of source. */
9426 idx = src->len + off;
9427 break;
9429 case SEEK_CUR: /* Go from current position. */
9430 idx = src->index + off;
9431 break;
9433 default: /* Invalid `whence'. */
9434 return -1;
9437 if (idx > src->len || idx < 0)
9438 return -1;
9440 src->index = idx;
9441 return src->index;
9445 static int
9446 tiff_close_memory (data)
9447 thandle_t data;
9449 /* NOOP */
9450 return 0;
9454 static int
9455 tiff_mmap_memory (data, pbase, psize)
9456 thandle_t data;
9457 tdata_t *pbase;
9458 toff_t *psize;
9460 /* It is already _IN_ memory. */
9461 return 0;
9465 static void
9466 tiff_unmap_memory (data, base, size)
9467 thandle_t data;
9468 tdata_t base;
9469 toff_t size;
9471 /* We don't need to do this. */
9475 static toff_t
9476 tiff_size_of_memory (data)
9477 thandle_t data;
9479 return ((tiff_memory_source *) data)->len;
9483 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9484 successful. */
9486 static int
9487 tiff_load (f, img)
9488 struct frame *f;
9489 struct image *img;
9491 Lisp_Object file, specified_file;
9492 Lisp_Object specified_data;
9493 TIFF *tiff;
9494 int width, height, x, y;
9495 uint32 *buf;
9496 int rc;
9497 XImage *ximg;
9498 struct gcpro gcpro1;
9499 tiff_memory_source memsrc;
9501 specified_file = image_spec_value (img->spec, QCfile, NULL);
9502 specified_data = image_spec_value (img->spec, QCdata, NULL);
9503 file = Qnil;
9504 GCPRO1 (file);
9506 if (NILP (specified_data))
9508 /* Read from a file */
9509 file = x_find_image_file (specified_file);
9510 if (!STRINGP (file))
9512 image_error ("Cannot find image file `%s'", file, Qnil);
9513 UNGCPRO;
9514 return 0;
9517 /* Try to open the image file. */
9518 tiff = TIFFOpen (XSTRING (file)->data, "r");
9519 if (tiff == NULL)
9521 image_error ("Cannot open `%s'", file, Qnil);
9522 UNGCPRO;
9523 return 0;
9526 else
9528 /* Memory source! */
9529 memsrc.bytes = XSTRING (specified_data)->data;
9530 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9531 memsrc.index = 0;
9533 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9534 (TIFFReadWriteProc) tiff_read_from_memory,
9535 (TIFFReadWriteProc) tiff_write_from_memory,
9536 tiff_seek_in_memory,
9537 tiff_close_memory,
9538 tiff_size_of_memory,
9539 tiff_mmap_memory,
9540 tiff_unmap_memory);
9542 if (!tiff)
9544 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9545 UNGCPRO;
9546 return 0;
9550 /* Get width and height of the image, and allocate a raster buffer
9551 of width x height 32-bit values. */
9552 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9553 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9554 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9556 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9557 TIFFClose (tiff);
9558 if (!rc)
9560 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9561 xfree (buf);
9562 UNGCPRO;
9563 return 0;
9566 /* Create the X image and pixmap. */
9567 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9569 xfree (buf);
9570 UNGCPRO;
9571 return 0;
9574 /* Initialize the color table. */
9575 init_color_table ();
9577 /* Process the pixel raster. Origin is in the lower-left corner. */
9578 for (y = 0; y < height; ++y)
9580 uint32 *row = buf + y * width;
9582 for (x = 0; x < width; ++x)
9584 uint32 abgr = row[x];
9585 int r = TIFFGetR (abgr) << 8;
9586 int g = TIFFGetG (abgr) << 8;
9587 int b = TIFFGetB (abgr) << 8;
9588 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9592 /* Remember the colors allocated for the image. Free the color table. */
9593 img->colors = colors_in_color_table (&img->ncolors);
9594 free_color_table ();
9596 /* Put the image into the pixmap, then free the X image and its buffer. */
9597 x_put_x_image (f, ximg, img->pixmap, width, height);
9598 x_destroy_x_image (ximg);
9599 xfree (buf);
9601 img->width = width;
9602 img->height = height;
9604 UNGCPRO;
9605 return 1;
9608 #endif /* HAVE_TIFF != 0 */
9612 /***********************************************************************
9614 ***********************************************************************/
9616 #if HAVE_GIF
9618 #include <gif_lib.h>
9620 static int gif_image_p P_ ((Lisp_Object object));
9621 static int gif_load P_ ((struct frame *f, struct image *img));
9623 /* The symbol `gif' identifying images of this type. */
9625 Lisp_Object Qgif;
9627 /* Indices of image specification fields in gif_format, below. */
9629 enum gif_keyword_index
9631 GIF_TYPE,
9632 GIF_DATA,
9633 GIF_FILE,
9634 GIF_ASCENT,
9635 GIF_MARGIN,
9636 GIF_RELIEF,
9637 GIF_ALGORITHM,
9638 GIF_HEURISTIC_MASK,
9639 GIF_MASK,
9640 GIF_IMAGE,
9641 GIF_LAST
9644 /* Vector of image_keyword structures describing the format
9645 of valid user-defined image specifications. */
9647 static struct image_keyword gif_format[GIF_LAST] =
9649 {":type", IMAGE_SYMBOL_VALUE, 1},
9650 {":data", IMAGE_STRING_VALUE, 0},
9651 {":file", IMAGE_STRING_VALUE, 0},
9652 {":ascent", IMAGE_ASCENT_VALUE, 0},
9653 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9654 {":relief", IMAGE_INTEGER_VALUE, 0},
9655 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9656 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9657 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9658 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9661 /* Structure describing the image type `gif'. */
9663 static struct image_type gif_type =
9665 &Qgif,
9666 gif_image_p,
9667 gif_load,
9668 x_clear_image,
9669 NULL
9673 /* Return non-zero if OBJECT is a valid GIF image specification. */
9675 static int
9676 gif_image_p (object)
9677 Lisp_Object object;
9679 struct image_keyword fmt[GIF_LAST];
9680 bcopy (gif_format, fmt, sizeof fmt);
9682 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9683 return 0;
9685 /* Must specify either the :data or :file keyword. */
9686 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9690 /* Reading a GIF image from memory
9691 Based on the PNG memory stuff to a certain extent. */
9693 typedef struct
9695 unsigned char *bytes;
9696 size_t len;
9697 int index;
9699 gif_memory_source;
9702 /* Make the current memory source available to gif_read_from_memory.
9703 It's done this way because not all versions of libungif support
9704 a UserData field in the GifFileType structure. */
9705 static gif_memory_source *current_gif_memory_src;
9707 static int
9708 gif_read_from_memory (file, buf, len)
9709 GifFileType *file;
9710 GifByteType *buf;
9711 int len;
9713 gif_memory_source *src = current_gif_memory_src;
9715 if (len > src->len - src->index)
9716 return -1;
9718 bcopy (src->bytes + src->index, buf, len);
9719 src->index += len;
9720 return len;
9724 /* Load GIF image IMG for use on frame F. Value is non-zero if
9725 successful. */
9727 static int
9728 gif_load (f, img)
9729 struct frame *f;
9730 struct image *img;
9732 Lisp_Object file, specified_file;
9733 Lisp_Object specified_data;
9734 int rc, width, height, x, y, i;
9735 XImage *ximg;
9736 ColorMapObject *gif_color_map;
9737 unsigned long pixel_colors[256];
9738 GifFileType *gif;
9739 struct gcpro gcpro1;
9740 Lisp_Object image;
9741 int ino, image_left, image_top, image_width, image_height;
9742 gif_memory_source memsrc;
9743 unsigned char *raster;
9745 specified_file = image_spec_value (img->spec, QCfile, NULL);
9746 specified_data = image_spec_value (img->spec, QCdata, NULL);
9747 file = Qnil;
9748 GCPRO1 (file);
9750 if (NILP (specified_data))
9752 file = x_find_image_file (specified_file);
9753 if (!STRINGP (file))
9755 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9756 UNGCPRO;
9757 return 0;
9760 /* Open the GIF file. */
9761 gif = DGifOpenFileName (XSTRING (file)->data);
9762 if (gif == NULL)
9764 image_error ("Cannot open `%s'", file, Qnil);
9765 UNGCPRO;
9766 return 0;
9769 else
9771 /* Read from memory! */
9772 current_gif_memory_src = &memsrc;
9773 memsrc.bytes = XSTRING (specified_data)->data;
9774 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9775 memsrc.index = 0;
9777 gif = DGifOpen(&memsrc, gif_read_from_memory);
9778 if (!gif)
9780 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9781 UNGCPRO;
9782 return 0;
9786 /* Read entire contents. */
9787 rc = DGifSlurp (gif);
9788 if (rc == GIF_ERROR)
9790 image_error ("Error reading `%s'", img->spec, Qnil);
9791 DGifCloseFile (gif);
9792 UNGCPRO;
9793 return 0;
9796 image = image_spec_value (img->spec, QCindex, NULL);
9797 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9798 if (ino >= gif->ImageCount)
9800 image_error ("Invalid image number `%s' in image `%s'",
9801 image, img->spec);
9802 DGifCloseFile (gif);
9803 UNGCPRO;
9804 return 0;
9807 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
9808 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
9810 /* Create the X image and pixmap. */
9811 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9813 DGifCloseFile (gif);
9814 UNGCPRO;
9815 return 0;
9818 /* Allocate colors. */
9819 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9820 if (!gif_color_map)
9821 gif_color_map = gif->SColorMap;
9822 init_color_table ();
9823 bzero (pixel_colors, sizeof pixel_colors);
9825 for (i = 0; i < gif_color_map->ColorCount; ++i)
9827 int r = gif_color_map->Colors[i].Red << 8;
9828 int g = gif_color_map->Colors[i].Green << 8;
9829 int b = gif_color_map->Colors[i].Blue << 8;
9830 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9833 img->colors = colors_in_color_table (&img->ncolors);
9834 free_color_table ();
9836 /* Clear the part of the screen image that are not covered by
9837 the image from the GIF file. Full animated GIF support
9838 requires more than can be done here (see the gif89 spec,
9839 disposal methods). Let's simply assume that the part
9840 not covered by a sub-image is in the frame's background color. */
9841 image_top = gif->SavedImages[ino].ImageDesc.Top;
9842 image_left = gif->SavedImages[ino].ImageDesc.Left;
9843 image_width = gif->SavedImages[ino].ImageDesc.Width;
9844 image_height = gif->SavedImages[ino].ImageDesc.Height;
9846 for (y = 0; y < image_top; ++y)
9847 for (x = 0; x < width; ++x)
9848 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9850 for (y = image_top + image_height; y < height; ++y)
9851 for (x = 0; x < width; ++x)
9852 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9854 for (y = image_top; y < image_top + image_height; ++y)
9856 for (x = 0; x < image_left; ++x)
9857 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9858 for (x = image_left + image_width; x < width; ++x)
9859 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9862 /* Read the GIF image into the X image. We use a local variable
9863 `raster' here because RasterBits below is a char *, and invites
9864 problems with bytes >= 0x80. */
9865 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9867 if (gif->SavedImages[ino].ImageDesc.Interlace)
9869 static int interlace_start[] = {0, 4, 2, 1};
9870 static int interlace_increment[] = {8, 8, 4, 2};
9871 int pass;
9872 int row = interlace_start[0];
9874 pass = 0;
9876 for (y = 0; y < image_height; y++)
9878 if (row >= image_height)
9880 row = interlace_start[++pass];
9881 while (row >= image_height)
9882 row = interlace_start[++pass];
9885 for (x = 0; x < image_width; x++)
9887 int i = raster[(y * image_width) + x];
9888 XPutPixel (ximg, x + image_left, row + image_top,
9889 pixel_colors[i]);
9892 row += interlace_increment[pass];
9895 else
9897 for (y = 0; y < image_height; ++y)
9898 for (x = 0; x < image_width; ++x)
9900 int i = raster[y * image_width + x];
9901 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9905 DGifCloseFile (gif);
9907 /* Put the image into the pixmap, then free the X image and its buffer. */
9908 x_put_x_image (f, ximg, img->pixmap, width, height);
9909 x_destroy_x_image (ximg);
9911 UNGCPRO;
9912 return 1;
9915 #endif /* HAVE_GIF != 0 */
9919 /***********************************************************************
9920 Ghostscript
9921 ***********************************************************************/
9923 static int gs_image_p P_ ((Lisp_Object object));
9924 static int gs_load P_ ((struct frame *f, struct image *img));
9925 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9927 /* The symbol `postscript' identifying images of this type. */
9929 Lisp_Object Qpostscript;
9931 /* Keyword symbols. */
9933 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9935 /* Indices of image specification fields in gs_format, below. */
9937 enum gs_keyword_index
9939 GS_TYPE,
9940 GS_PT_WIDTH,
9941 GS_PT_HEIGHT,
9942 GS_FILE,
9943 GS_LOADER,
9944 GS_BOUNDING_BOX,
9945 GS_ASCENT,
9946 GS_MARGIN,
9947 GS_RELIEF,
9948 GS_ALGORITHM,
9949 GS_HEURISTIC_MASK,
9950 GS_MASK,
9951 GS_LAST
9954 /* Vector of image_keyword structures describing the format
9955 of valid user-defined image specifications. */
9957 static struct image_keyword gs_format[GS_LAST] =
9959 {":type", IMAGE_SYMBOL_VALUE, 1},
9960 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9961 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9962 {":file", IMAGE_STRING_VALUE, 1},
9963 {":loader", IMAGE_FUNCTION_VALUE, 0},
9964 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9965 {":ascent", IMAGE_ASCENT_VALUE, 0},
9966 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9967 {":relief", IMAGE_INTEGER_VALUE, 0},
9968 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9969 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9970 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9973 /* Structure describing the image type `ghostscript'. */
9975 static struct image_type gs_type =
9977 &Qpostscript,
9978 gs_image_p,
9979 gs_load,
9980 gs_clear_image,
9981 NULL
9985 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9987 static void
9988 gs_clear_image (f, img)
9989 struct frame *f;
9990 struct image *img;
9992 /* IMG->data.ptr_val may contain a recorded colormap. */
9993 xfree (img->data.ptr_val);
9994 x_clear_image (f, img);
9998 /* Return non-zero if OBJECT is a valid Ghostscript image
9999 specification. */
10001 static int
10002 gs_image_p (object)
10003 Lisp_Object object;
10005 struct image_keyword fmt[GS_LAST];
10006 Lisp_Object tem;
10007 int i;
10009 bcopy (gs_format, fmt, sizeof fmt);
10011 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10012 return 0;
10014 /* Bounding box must be a list or vector containing 4 integers. */
10015 tem = fmt[GS_BOUNDING_BOX].value;
10016 if (CONSP (tem))
10018 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10019 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10020 return 0;
10021 if (!NILP (tem))
10022 return 0;
10024 else if (VECTORP (tem))
10026 if (XVECTOR (tem)->size != 4)
10027 return 0;
10028 for (i = 0; i < 4; ++i)
10029 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10030 return 0;
10032 else
10033 return 0;
10035 return 1;
10039 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10040 if successful. */
10042 static int
10043 gs_load (f, img)
10044 struct frame *f;
10045 struct image *img;
10047 char buffer[100];
10048 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10049 struct gcpro gcpro1, gcpro2;
10050 Lisp_Object frame;
10051 double in_width, in_height;
10052 Lisp_Object pixel_colors = Qnil;
10054 /* Compute pixel size of pixmap needed from the given size in the
10055 image specification. Sizes in the specification are in pt. 1 pt
10056 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10057 info. */
10058 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10059 in_width = XFASTINT (pt_width) / 72.0;
10060 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10061 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10062 in_height = XFASTINT (pt_height) / 72.0;
10063 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10065 /* Create the pixmap. */
10066 xassert (img->pixmap == None);
10067 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10068 img->width, img->height,
10069 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10071 if (!img->pixmap)
10073 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10074 return 0;
10077 /* Call the loader to fill the pixmap. It returns a process object
10078 if successful. We do not record_unwind_protect here because
10079 other places in redisplay like calling window scroll functions
10080 don't either. Let the Lisp loader use `unwind-protect' instead. */
10081 GCPRO2 (window_and_pixmap_id, pixel_colors);
10083 sprintf (buffer, "%lu %lu",
10084 (unsigned long) FRAME_X_WINDOW (f),
10085 (unsigned long) img->pixmap);
10086 window_and_pixmap_id = build_string (buffer);
10088 sprintf (buffer, "%lu %lu",
10089 FRAME_FOREGROUND_PIXEL (f),
10090 FRAME_BACKGROUND_PIXEL (f));
10091 pixel_colors = build_string (buffer);
10093 XSETFRAME (frame, f);
10094 loader = image_spec_value (img->spec, QCloader, NULL);
10095 if (NILP (loader))
10096 loader = intern ("gs-load-image");
10098 img->data.lisp_val = call6 (loader, frame, img->spec,
10099 make_number (img->width),
10100 make_number (img->height),
10101 window_and_pixmap_id,
10102 pixel_colors);
10103 UNGCPRO;
10104 return PROCESSP (img->data.lisp_val);
10108 /* Kill the Ghostscript process that was started to fill PIXMAP on
10109 frame F. Called from XTread_socket when receiving an event
10110 telling Emacs that Ghostscript has finished drawing. */
10112 void
10113 x_kill_gs_process (pixmap, f)
10114 Pixmap pixmap;
10115 struct frame *f;
10117 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10118 int class, i;
10119 struct image *img;
10121 /* Find the image containing PIXMAP. */
10122 for (i = 0; i < c->used; ++i)
10123 if (c->images[i]->pixmap == pixmap)
10124 break;
10126 /* Should someone in between have cleared the image cache, for
10127 instance, give up. */
10128 if (i == c->used)
10129 return;
10131 /* Kill the GS process. We should have found PIXMAP in the image
10132 cache and its image should contain a process object. */
10133 img = c->images[i];
10134 xassert (PROCESSP (img->data.lisp_val));
10135 Fkill_process (img->data.lisp_val, Qnil);
10136 img->data.lisp_val = Qnil;
10138 /* On displays with a mutable colormap, figure out the colors
10139 allocated for the image by looking at the pixels of an XImage for
10140 img->pixmap. */
10141 class = FRAME_X_VISUAL (f)->class;
10142 if (class != StaticColor && class != StaticGray && class != TrueColor)
10144 XImage *ximg;
10146 BLOCK_INPUT;
10148 /* Try to get an XImage for img->pixmep. */
10149 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10150 0, 0, img->width, img->height, ~0, ZPixmap);
10151 if (ximg)
10153 int x, y;
10155 /* Initialize the color table. */
10156 init_color_table ();
10158 /* For each pixel of the image, look its color up in the
10159 color table. After having done so, the color table will
10160 contain an entry for each color used by the image. */
10161 for (y = 0; y < img->height; ++y)
10162 for (x = 0; x < img->width; ++x)
10164 unsigned long pixel = XGetPixel (ximg, x, y);
10165 lookup_pixel_color (f, pixel);
10168 /* Record colors in the image. Free color table and XImage. */
10169 img->colors = colors_in_color_table (&img->ncolors);
10170 free_color_table ();
10171 XDestroyImage (ximg);
10173 #if 0 /* This doesn't seem to be the case. If we free the colors
10174 here, we get a BadAccess later in x_clear_image when
10175 freeing the colors. */
10176 /* We have allocated colors once, but Ghostscript has also
10177 allocated colors on behalf of us. So, to get the
10178 reference counts right, free them once. */
10179 if (img->ncolors)
10180 x_free_colors (f, img->colors, img->ncolors);
10181 #endif
10183 else
10184 image_error ("Cannot get X image of `%s'; colors will not be freed",
10185 img->spec, Qnil);
10187 UNBLOCK_INPUT;
10190 /* Now that we have the pixmap, compute mask and transform the
10191 image if requested. */
10192 BLOCK_INPUT;
10193 postprocess_image (f, img);
10194 UNBLOCK_INPUT;
10199 /***********************************************************************
10200 Window properties
10201 ***********************************************************************/
10203 DEFUN ("x-change-window-property", Fx_change_window_property,
10204 Sx_change_window_property, 2, 3, 0,
10205 "Change window property PROP to VALUE on the X window of FRAME.\n\
10206 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
10207 selected frame. Value is VALUE.")
10208 (prop, value, frame)
10209 Lisp_Object frame, prop, value;
10211 struct frame *f = check_x_frame (frame);
10212 Atom prop_atom;
10214 CHECK_STRING (prop, 1);
10215 CHECK_STRING (value, 2);
10217 BLOCK_INPUT;
10218 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10219 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10220 prop_atom, XA_STRING, 8, PropModeReplace,
10221 XSTRING (value)->data, XSTRING (value)->size);
10223 /* Make sure the property is set when we return. */
10224 XFlush (FRAME_X_DISPLAY (f));
10225 UNBLOCK_INPUT;
10227 return value;
10231 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10232 Sx_delete_window_property, 1, 2, 0,
10233 "Remove window property PROP from X window of FRAME.\n\
10234 FRAME nil or omitted means use the selected frame. Value is PROP.")
10235 (prop, frame)
10236 Lisp_Object prop, frame;
10238 struct frame *f = check_x_frame (frame);
10239 Atom prop_atom;
10241 CHECK_STRING (prop, 1);
10242 BLOCK_INPUT;
10243 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10244 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10246 /* Make sure the property is removed when we return. */
10247 XFlush (FRAME_X_DISPLAY (f));
10248 UNBLOCK_INPUT;
10250 return prop;
10254 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10255 1, 2, 0,
10256 "Value is the value of window property PROP on FRAME.\n\
10257 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10258 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10259 value.")
10260 (prop, frame)
10261 Lisp_Object prop, frame;
10263 struct frame *f = check_x_frame (frame);
10264 Atom prop_atom;
10265 int rc;
10266 Lisp_Object prop_value = Qnil;
10267 char *tmp_data = NULL;
10268 Atom actual_type;
10269 int actual_format;
10270 unsigned long actual_size, bytes_remaining;
10272 CHECK_STRING (prop, 1);
10273 BLOCK_INPUT;
10274 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10275 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10276 prop_atom, 0, 0, False, XA_STRING,
10277 &actual_type, &actual_format, &actual_size,
10278 &bytes_remaining, (unsigned char **) &tmp_data);
10279 if (rc == Success)
10281 int size = bytes_remaining;
10283 XFree (tmp_data);
10284 tmp_data = NULL;
10286 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10287 prop_atom, 0, bytes_remaining,
10288 False, XA_STRING,
10289 &actual_type, &actual_format,
10290 &actual_size, &bytes_remaining,
10291 (unsigned char **) &tmp_data);
10292 if (rc == Success && tmp_data)
10293 prop_value = make_string (tmp_data, size);
10295 XFree (tmp_data);
10298 UNBLOCK_INPUT;
10299 return prop_value;
10304 /***********************************************************************
10305 Busy cursor
10306 ***********************************************************************/
10308 /* If non-null, an asynchronous timer that, when it expires, displays
10309 an hourglass cursor on all frames. */
10311 static struct atimer *hourglass_atimer;
10313 /* Non-zero means an hourglass cursor is currently shown. */
10315 static int hourglass_shown_p;
10317 /* Number of seconds to wait before displaying an hourglass cursor. */
10319 static Lisp_Object Vhourglass_delay;
10321 /* Default number of seconds to wait before displaying an hourglass
10322 cursor. */
10324 #define DEFAULT_HOURGLASS_DELAY 1
10326 /* Function prototypes. */
10328 static void show_hourglass P_ ((struct atimer *));
10329 static void hide_hourglass P_ ((void));
10332 /* Cancel a currently active hourglass timer, and start a new one. */
10334 void
10335 start_hourglass ()
10337 EMACS_TIME delay;
10338 int secs, usecs = 0;
10340 cancel_hourglass ();
10342 if (INTEGERP (Vhourglass_delay)
10343 && XINT (Vhourglass_delay) > 0)
10344 secs = XFASTINT (Vhourglass_delay);
10345 else if (FLOATP (Vhourglass_delay)
10346 && XFLOAT_DATA (Vhourglass_delay) > 0)
10348 Lisp_Object tem;
10349 tem = Ftruncate (Vhourglass_delay, Qnil);
10350 secs = XFASTINT (tem);
10351 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10353 else
10354 secs = DEFAULT_HOURGLASS_DELAY;
10356 EMACS_SET_SECS_USECS (delay, secs, usecs);
10357 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10358 show_hourglass, NULL);
10362 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10363 shown. */
10365 void
10366 cancel_hourglass ()
10368 if (hourglass_atimer)
10370 cancel_atimer (hourglass_atimer);
10371 hourglass_atimer = NULL;
10374 if (hourglass_shown_p)
10375 hide_hourglass ();
10379 /* Timer function of hourglass_atimer. TIMER is equal to
10380 hourglass_atimer.
10382 Display an hourglass pointer on all frames by mapping the frames'
10383 hourglass_window. Set the hourglass_p flag in the frames'
10384 output_data.x structure to indicate that an hourglass cursor is
10385 shown on the frames. */
10387 static void
10388 show_hourglass (timer)
10389 struct atimer *timer;
10391 /* The timer implementation will cancel this timer automatically
10392 after this function has run. Set hourglass_atimer to null
10393 so that we know the timer doesn't have to be canceled. */
10394 hourglass_atimer = NULL;
10396 if (!hourglass_shown_p)
10398 Lisp_Object rest, frame;
10400 BLOCK_INPUT;
10402 FOR_EACH_FRAME (rest, frame)
10404 struct frame *f = XFRAME (frame);
10406 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10408 Display *dpy = FRAME_X_DISPLAY (f);
10410 #ifdef USE_X_TOOLKIT
10411 if (f->output_data.x->widget)
10412 #else
10413 if (FRAME_OUTER_WINDOW (f))
10414 #endif
10416 f->output_data.x->hourglass_p = 1;
10418 if (!f->output_data.x->hourglass_window)
10420 unsigned long mask = CWCursor;
10421 XSetWindowAttributes attrs;
10423 attrs.cursor = f->output_data.x->hourglass_cursor;
10425 f->output_data.x->hourglass_window
10426 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10427 0, 0, 32000, 32000, 0, 0,
10428 InputOnly,
10429 CopyFromParent,
10430 mask, &attrs);
10433 XMapRaised (dpy, f->output_data.x->hourglass_window);
10434 XFlush (dpy);
10439 hourglass_shown_p = 1;
10440 UNBLOCK_INPUT;
10445 /* Hide the hourglass pointer on all frames, if it is currently
10446 shown. */
10448 static void
10449 hide_hourglass ()
10451 if (hourglass_shown_p)
10453 Lisp_Object rest, frame;
10455 BLOCK_INPUT;
10456 FOR_EACH_FRAME (rest, frame)
10458 struct frame *f = XFRAME (frame);
10460 if (FRAME_X_P (f)
10461 /* Watch out for newly created frames. */
10462 && f->output_data.x->hourglass_window)
10464 XUnmapWindow (FRAME_X_DISPLAY (f),
10465 f->output_data.x->hourglass_window);
10466 /* Sync here because XTread_socket looks at the
10467 hourglass_p flag that is reset to zero below. */
10468 XSync (FRAME_X_DISPLAY (f), False);
10469 f->output_data.x->hourglass_p = 0;
10473 hourglass_shown_p = 0;
10474 UNBLOCK_INPUT;
10480 /***********************************************************************
10481 Tool tips
10482 ***********************************************************************/
10484 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10485 Lisp_Object, Lisp_Object));
10486 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10487 Lisp_Object, int, int, int *, int *));
10489 /* The frame of a currently visible tooltip. */
10491 Lisp_Object tip_frame;
10493 /* If non-nil, a timer started that hides the last tooltip when it
10494 fires. */
10496 Lisp_Object tip_timer;
10497 Window tip_window;
10499 /* If non-nil, a vector of 3 elements containing the last args
10500 with which x-show-tip was called. See there. */
10502 Lisp_Object last_show_tip_args;
10504 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10506 Lisp_Object Vx_max_tooltip_size;
10509 static Lisp_Object
10510 unwind_create_tip_frame (frame)
10511 Lisp_Object frame;
10513 Lisp_Object deleted;
10515 deleted = unwind_create_frame (frame);
10516 if (EQ (deleted, Qt))
10518 tip_window = None;
10519 tip_frame = Qnil;
10522 return deleted;
10526 /* Create a frame for a tooltip on the display described by DPYINFO.
10527 PARMS is a list of frame parameters. TEXT is the string to
10528 display in the tip frame. Value is the frame.
10530 Note that functions called here, esp. x_default_parameter can
10531 signal errors, for instance when a specified color name is
10532 undefined. We have to make sure that we're in a consistent state
10533 when this happens. */
10535 static Lisp_Object
10536 x_create_tip_frame (dpyinfo, parms, text)
10537 struct x_display_info *dpyinfo;
10538 Lisp_Object parms, text;
10540 struct frame *f;
10541 Lisp_Object frame, tem;
10542 Lisp_Object name;
10543 long window_prompting = 0;
10544 int width, height;
10545 int count = BINDING_STACK_SIZE ();
10546 struct gcpro gcpro1, gcpro2, gcpro3;
10547 struct kboard *kb;
10548 int face_change_count_before = face_change_count;
10549 Lisp_Object buffer;
10550 struct buffer *old_buffer;
10552 check_x ();
10554 /* Use this general default value to start with until we know if
10555 this frame has a specified name. */
10556 Vx_resource_name = Vinvocation_name;
10558 #ifdef MULTI_KBOARD
10559 kb = dpyinfo->kboard;
10560 #else
10561 kb = &the_only_kboard;
10562 #endif
10564 /* Get the name of the frame to use for resource lookup. */
10565 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10566 if (!STRINGP (name)
10567 && !EQ (name, Qunbound)
10568 && !NILP (name))
10569 error ("Invalid frame name--not a string or nil");
10570 Vx_resource_name = name;
10572 frame = Qnil;
10573 GCPRO3 (parms, name, frame);
10574 f = make_frame (1);
10575 XSETFRAME (frame, f);
10577 buffer = Fget_buffer_create (build_string (" *tip*"));
10578 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10579 old_buffer = current_buffer;
10580 set_buffer_internal_1 (XBUFFER (buffer));
10581 current_buffer->truncate_lines = Qnil;
10582 Ferase_buffer ();
10583 Finsert (1, &text);
10584 set_buffer_internal_1 (old_buffer);
10586 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10587 record_unwind_protect (unwind_create_tip_frame, frame);
10589 /* By setting the output method, we're essentially saying that
10590 the frame is live, as per FRAME_LIVE_P. If we get a signal
10591 from this point on, x_destroy_window might screw up reference
10592 counts etc. */
10593 f->output_method = output_x_window;
10594 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10595 bzero (f->output_data.x, sizeof (struct x_output));
10596 f->output_data.x->icon_bitmap = -1;
10597 f->output_data.x->fontset = -1;
10598 f->output_data.x->scroll_bar_foreground_pixel = -1;
10599 f->output_data.x->scroll_bar_background_pixel = -1;
10600 f->icon_name = Qnil;
10601 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10602 #if GLYPH_DEBUG
10603 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
10604 dpyinfo_refcount = dpyinfo->reference_count;
10605 #endif /* GLYPH_DEBUG */
10606 #ifdef MULTI_KBOARD
10607 FRAME_KBOARD (f) = kb;
10608 #endif
10609 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10610 f->output_data.x->explicit_parent = 0;
10612 /* These colors will be set anyway later, but it's important
10613 to get the color reference counts right, so initialize them! */
10615 Lisp_Object black;
10616 struct gcpro gcpro1;
10618 black = build_string ("black");
10619 GCPRO1 (black);
10620 f->output_data.x->foreground_pixel
10621 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10622 f->output_data.x->background_pixel
10623 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10624 f->output_data.x->cursor_pixel
10625 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10626 f->output_data.x->cursor_foreground_pixel
10627 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10628 f->output_data.x->border_pixel
10629 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10630 f->output_data.x->mouse_pixel
10631 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10632 UNGCPRO;
10635 /* Set the name; the functions to which we pass f expect the name to
10636 be set. */
10637 if (EQ (name, Qunbound) || NILP (name))
10639 f->name = build_string (dpyinfo->x_id_name);
10640 f->explicit_name = 0;
10642 else
10644 f->name = name;
10645 f->explicit_name = 1;
10646 /* use the frame's title when getting resources for this frame. */
10647 specbind (Qx_resource_name, name);
10650 /* Extract the window parameters from the supplied values that are
10651 needed to determine window geometry. */
10653 Lisp_Object font;
10655 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10657 BLOCK_INPUT;
10658 /* First, try whatever font the caller has specified. */
10659 if (STRINGP (font))
10661 tem = Fquery_fontset (font, Qnil);
10662 if (STRINGP (tem))
10663 font = x_new_fontset (f, XSTRING (tem)->data);
10664 else
10665 font = x_new_font (f, XSTRING (font)->data);
10668 /* Try out a font which we hope has bold and italic variations. */
10669 if (!STRINGP (font))
10670 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10671 if (!STRINGP (font))
10672 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10673 if (! STRINGP (font))
10674 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10675 if (! STRINGP (font))
10676 /* This was formerly the first thing tried, but it finds too many fonts
10677 and takes too long. */
10678 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10679 /* If those didn't work, look for something which will at least work. */
10680 if (! STRINGP (font))
10681 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10682 UNBLOCK_INPUT;
10683 if (! STRINGP (font))
10684 font = build_string ("fixed");
10686 x_default_parameter (f, parms, Qfont, font,
10687 "font", "Font", RES_TYPE_STRING);
10690 x_default_parameter (f, parms, Qborder_width, make_number (2),
10691 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10693 /* This defaults to 2 in order to match xterm. We recognize either
10694 internalBorderWidth or internalBorder (which is what xterm calls
10695 it). */
10696 if (NILP (Fassq (Qinternal_border_width, parms)))
10698 Lisp_Object value;
10700 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10701 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10702 if (! EQ (value, Qunbound))
10703 parms = Fcons (Fcons (Qinternal_border_width, value),
10704 parms);
10707 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10708 "internalBorderWidth", "internalBorderWidth",
10709 RES_TYPE_NUMBER);
10711 /* Also do the stuff which must be set before the window exists. */
10712 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10713 "foreground", "Foreground", RES_TYPE_STRING);
10714 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10715 "background", "Background", RES_TYPE_STRING);
10716 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10717 "pointerColor", "Foreground", RES_TYPE_STRING);
10718 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10719 "cursorColor", "Foreground", RES_TYPE_STRING);
10720 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10721 "borderColor", "BorderColor", RES_TYPE_STRING);
10723 /* Init faces before x_default_parameter is called for scroll-bar
10724 parameters because that function calls x_set_scroll_bar_width,
10725 which calls change_frame_size, which calls Fset_window_buffer,
10726 which runs hooks, which call Fvertical_motion. At the end, we
10727 end up in init_iterator with a null face cache, which should not
10728 happen. */
10729 init_frame_faces (f);
10731 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10732 window_prompting = x_figure_window_size (f, parms);
10734 if (window_prompting & XNegative)
10736 if (window_prompting & YNegative)
10737 f->output_data.x->win_gravity = SouthEastGravity;
10738 else
10739 f->output_data.x->win_gravity = NorthEastGravity;
10741 else
10743 if (window_prompting & YNegative)
10744 f->output_data.x->win_gravity = SouthWestGravity;
10745 else
10746 f->output_data.x->win_gravity = NorthWestGravity;
10749 f->output_data.x->size_hint_flags = window_prompting;
10751 XSetWindowAttributes attrs;
10752 unsigned long mask;
10754 BLOCK_INPUT;
10755 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
10756 if (DoesSaveUnders (dpyinfo->screen))
10757 mask |= CWSaveUnder;
10759 /* Window managers look at the override-redirect flag to determine
10760 whether or net to give windows a decoration (Xlib spec, chapter
10761 3.2.8). */
10762 attrs.override_redirect = True;
10763 attrs.save_under = True;
10764 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10765 /* Arrange for getting MapNotify and UnmapNotify events. */
10766 attrs.event_mask = StructureNotifyMask;
10767 tip_window
10768 = FRAME_X_WINDOW (f)
10769 = XCreateWindow (FRAME_X_DISPLAY (f),
10770 FRAME_X_DISPLAY_INFO (f)->root_window,
10771 /* x, y, width, height */
10772 0, 0, 1, 1,
10773 /* Border. */
10775 CopyFromParent, InputOutput, CopyFromParent,
10776 mask, &attrs);
10777 UNBLOCK_INPUT;
10780 x_make_gc (f);
10782 x_default_parameter (f, parms, Qauto_raise, Qnil,
10783 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10784 x_default_parameter (f, parms, Qauto_lower, Qnil,
10785 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10786 x_default_parameter (f, parms, Qcursor_type, Qbox,
10787 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10789 /* Dimensions, especially f->height, must be done via change_frame_size.
10790 Change will not be effected unless different from the current
10791 f->height. */
10792 width = f->width;
10793 height = f->height;
10794 f->height = 0;
10795 SET_FRAME_WIDTH (f, 0);
10796 change_frame_size (f, height, width, 1, 0, 0);
10798 /* Set up faces after all frame parameters are known. This call
10799 also merges in face attributes specified for new frames.
10801 Frame parameters may be changed if .Xdefaults contains
10802 specifications for the default font. For example, if there is an
10803 `Emacs.default.attributeBackground: pink', the `background-color'
10804 attribute of the frame get's set, which let's the internal border
10805 of the tooltip frame appear in pink. Prevent this. */
10807 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
10809 /* Set tip_frame here, so that */
10810 tip_frame = frame;
10811 call1 (Qface_set_after_frame_default, frame);
10813 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
10814 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
10815 Qnil));
10818 f->no_split = 1;
10820 UNGCPRO;
10822 /* It is now ok to make the frame official even if we get an error
10823 below. And the frame needs to be on Vframe_list or making it
10824 visible won't work. */
10825 Vframe_list = Fcons (frame, Vframe_list);
10827 /* Now that the frame is official, it counts as a reference to
10828 its display. */
10829 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10831 /* Setting attributes of faces of the tooltip frame from resources
10832 and similar will increment face_change_count, which leads to the
10833 clearing of all current matrices. Since this isn't necessary
10834 here, avoid it by resetting face_change_count to the value it
10835 had before we created the tip frame. */
10836 face_change_count = face_change_count_before;
10838 /* Discard the unwind_protect. */
10839 return unbind_to (count, frame);
10843 /* Compute where to display tip frame F. PARMS is the list of frame
10844 parameters for F. DX and DY are specified offsets from the current
10845 location of the mouse. WIDTH and HEIGHT are the width and height
10846 of the tooltip. Return coordinates relative to the root window of
10847 the display in *ROOT_X, and *ROOT_Y. */
10849 static void
10850 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
10851 struct frame *f;
10852 Lisp_Object parms, dx, dy;
10853 int width, height;
10854 int *root_x, *root_y;
10856 Lisp_Object left, top;
10857 int win_x, win_y;
10858 Window root, child;
10859 unsigned pmask;
10861 /* User-specified position? */
10862 left = Fcdr (Fassq (Qleft, parms));
10863 top = Fcdr (Fassq (Qtop, parms));
10865 /* Move the tooltip window where the mouse pointer is. Resize and
10866 show it. */
10867 if (!INTEGERP (left) && !INTEGERP (top))
10869 BLOCK_INPUT;
10870 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10871 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
10872 UNBLOCK_INPUT;
10875 if (INTEGERP (top))
10876 *root_y = XINT (top);
10877 else if (*root_y + XINT (dy) - height < 0)
10878 *root_y -= XINT (dy);
10879 else
10881 *root_y -= height;
10882 *root_y += XINT (dy);
10885 if (INTEGERP (left))
10886 *root_x = XINT (left);
10887 else if (*root_x + XINT (dx) + width > FRAME_X_DISPLAY_INFO (f)->width)
10888 *root_x -= width + XINT (dx);
10889 else
10890 *root_x += XINT (dx);
10894 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10895 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10896 A tooltip window is a small X window displaying a string.\n\
10898 FRAME nil or omitted means use the selected frame.\n\
10900 PARMS is an optional list of frame parameters which can be\n\
10901 used to change the tooltip's appearance.\n\
10903 Automatically hide the tooltip after TIMEOUT seconds.\n\
10904 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10906 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10907 the tooltip is displayed at that x-position. Otherwise it is\n\
10908 displayed at the mouse position, with offset DX added (default is 5 if\n\
10909 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10910 parameter is specified, it determines the y-position of the tooltip\n\
10911 window, otherwise it is displayed at the mouse position, with offset\n\
10912 DY added (default is -10).\n\
10914 A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
10915 Text larger than the specified size is clipped.")
10916 (string, frame, parms, timeout, dx, dy)
10917 Lisp_Object string, frame, parms, timeout, dx, dy;
10919 struct frame *f;
10920 struct window *w;
10921 Lisp_Object buffer, top, left, max_width, max_height;
10922 int root_x, root_y;
10923 struct buffer *old_buffer;
10924 struct text_pos pos;
10925 int i, width, height;
10926 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10927 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10928 int count = BINDING_STACK_SIZE ();
10930 specbind (Qinhibit_redisplay, Qt);
10932 GCPRO4 (string, parms, frame, timeout);
10934 CHECK_STRING (string, 0);
10935 f = check_x_frame (frame);
10936 if (NILP (timeout))
10937 timeout = make_number (5);
10938 else
10939 CHECK_NATNUM (timeout, 2);
10941 if (NILP (dx))
10942 dx = make_number (5);
10943 else
10944 CHECK_NUMBER (dx, 5);
10946 if (NILP (dy))
10947 dy = make_number (-10);
10948 else
10949 CHECK_NUMBER (dy, 6);
10951 if (NILP (last_show_tip_args))
10952 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
10954 if (!NILP (tip_frame))
10956 Lisp_Object last_string = AREF (last_show_tip_args, 0);
10957 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
10958 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
10960 if (EQ (frame, last_frame)
10961 && !NILP (Fequal (last_string, string))
10962 && !NILP (Fequal (last_parms, parms)))
10964 struct frame *f = XFRAME (tip_frame);
10966 /* Only DX and DY have changed. */
10967 if (!NILP (tip_timer))
10969 Lisp_Object timer = tip_timer;
10970 tip_timer = Qnil;
10971 call1 (Qcancel_timer, timer);
10974 BLOCK_INPUT;
10975 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
10976 PIXEL_HEIGHT (f), &root_x, &root_y);
10977 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10978 root_x, root_y);
10979 UNBLOCK_INPUT;
10980 goto start_timer;
10984 /* Hide a previous tip, if any. */
10985 Fx_hide_tip ();
10987 ASET (last_show_tip_args, 0, string);
10988 ASET (last_show_tip_args, 1, frame);
10989 ASET (last_show_tip_args, 2, parms);
10991 /* Add default values to frame parameters. */
10992 if (NILP (Fassq (Qname, parms)))
10993 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10994 if (NILP (Fassq (Qinternal_border_width, parms)))
10995 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10996 if (NILP (Fassq (Qborder_width, parms)))
10997 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10998 if (NILP (Fassq (Qborder_color, parms)))
10999 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
11000 if (NILP (Fassq (Qbackground_color, parms)))
11001 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
11002 parms);
11004 /* Create a frame for the tooltip, and record it in the global
11005 variable tip_frame. */
11006 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
11007 f = XFRAME (frame);
11009 /* Set up the frame's root window. */
11010 w = XWINDOW (FRAME_ROOT_WINDOW (f));
11011 w->left = w->top = make_number (0);
11013 if (CONSP (Vx_max_tooltip_size)
11014 && INTEGERP (XCAR (Vx_max_tooltip_size))
11015 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11016 && INTEGERP (XCDR (Vx_max_tooltip_size))
11017 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11019 w->width = XCAR (Vx_max_tooltip_size);
11020 w->height = XCDR (Vx_max_tooltip_size);
11022 else
11024 w->width = make_number (80);
11025 w->height = make_number (40);
11028 f->window_width = XINT (w->width);
11029 adjust_glyphs (f);
11030 w->pseudo_window_p = 1;
11032 /* Display the tooltip text in a temporary buffer. */
11033 old_buffer = current_buffer;
11034 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11035 current_buffer->truncate_lines = Qnil;
11036 clear_glyph_matrix (w->desired_matrix);
11037 clear_glyph_matrix (w->current_matrix);
11038 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11039 try_window (FRAME_ROOT_WINDOW (f), pos);
11041 /* Compute width and height of the tooltip. */
11042 width = height = 0;
11043 for (i = 0; i < w->desired_matrix->nrows; ++i)
11045 struct glyph_row *row = &w->desired_matrix->rows[i];
11046 struct glyph *last;
11047 int row_width;
11049 /* Stop at the first empty row at the end. */
11050 if (!row->enabled_p || !row->displays_text_p)
11051 break;
11053 /* Let the row go over the full width of the frame. */
11054 row->full_width_p = 1;
11056 /* There's a glyph at the end of rows that is used to place
11057 the cursor there. Don't include the width of this glyph. */
11058 if (row->used[TEXT_AREA])
11060 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
11061 row_width = row->pixel_width - last->pixel_width;
11063 else
11064 row_width = row->pixel_width;
11066 height += row->height;
11067 width = max (width, row_width);
11070 /* Add the frame's internal border to the width and height the X
11071 window should have. */
11072 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11073 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11075 /* Move the tooltip window where the mouse pointer is. Resize and
11076 show it. */
11077 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
11079 BLOCK_INPUT;
11080 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11081 root_x, root_y, width, height);
11082 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11083 UNBLOCK_INPUT;
11085 /* Draw into the window. */
11086 w->must_be_updated_p = 1;
11087 update_single_window (w, 1);
11089 /* Restore original current buffer. */
11090 set_buffer_internal_1 (old_buffer);
11091 windows_or_buffers_changed = old_windows_or_buffers_changed;
11093 start_timer:
11094 /* Let the tip disappear after timeout seconds. */
11095 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11096 intern ("x-hide-tip"));
11098 UNGCPRO;
11099 return unbind_to (count, Qnil);
11103 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11104 "Hide the current tooltip window, if there is any.\n\
11105 Value is t is tooltip was open, nil otherwise.")
11108 int count;
11109 Lisp_Object deleted, frame, timer;
11110 struct gcpro gcpro1, gcpro2;
11112 /* Return quickly if nothing to do. */
11113 if (NILP (tip_timer) && NILP (tip_frame))
11114 return Qnil;
11116 frame = tip_frame;
11117 timer = tip_timer;
11118 GCPRO2 (frame, timer);
11119 tip_frame = tip_timer = deleted = Qnil;
11121 count = BINDING_STACK_SIZE ();
11122 specbind (Qinhibit_redisplay, Qt);
11123 specbind (Qinhibit_quit, Qt);
11125 if (!NILP (timer))
11126 call1 (Qcancel_timer, timer);
11128 if (FRAMEP (frame))
11130 Fdelete_frame (frame, Qnil);
11131 deleted = Qt;
11133 #ifdef USE_LUCID
11134 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11135 redisplay procedure is not called when a tip frame over menu
11136 items is unmapped. Redisplay the menu manually... */
11138 struct frame *f = SELECTED_FRAME ();
11139 Widget w = f->output_data.x->menubar_widget;
11140 extern void xlwmenu_redisplay P_ ((Widget));
11142 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11143 && w != NULL)
11145 BLOCK_INPUT;
11146 xlwmenu_redisplay (w);
11147 UNBLOCK_INPUT;
11150 #endif /* USE_LUCID */
11153 UNGCPRO;
11154 return unbind_to (count, deleted);
11159 /***********************************************************************
11160 File selection dialog
11161 ***********************************************************************/
11163 #ifdef USE_MOTIF
11165 /* Callback for "OK" and "Cancel" on file selection dialog. */
11167 static void
11168 file_dialog_cb (widget, client_data, call_data)
11169 Widget widget;
11170 XtPointer call_data, client_data;
11172 int *result = (int *) client_data;
11173 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11174 *result = cb->reason;
11178 /* Callback for unmapping a file selection dialog. This is used to
11179 capture the case where a dialog is closed via a window manager's
11180 closer button, for example. Using a XmNdestroyCallback didn't work
11181 in this case. */
11183 static void
11184 file_dialog_unmap_cb (widget, client_data, call_data)
11185 Widget widget;
11186 XtPointer call_data, client_data;
11188 int *result = (int *) client_data;
11189 *result = XmCR_CANCEL;
11193 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11194 "Read file name, prompting with PROMPT in directory DIR.\n\
11195 Use a file selection dialog.\n\
11196 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
11197 specified. Don't let the user enter a file name in the file\n\
11198 selection dialog's entry field, if MUSTMATCH is non-nil.")
11199 (prompt, dir, default_filename, mustmatch)
11200 Lisp_Object prompt, dir, default_filename, mustmatch;
11202 int result;
11203 struct frame *f = SELECTED_FRAME ();
11204 Lisp_Object file = Qnil;
11205 Widget dialog, text, list, help;
11206 Arg al[10];
11207 int ac = 0;
11208 extern XtAppContext Xt_app_con;
11209 char *title;
11210 XmString dir_xmstring, pattern_xmstring;
11211 int popup_activated_flag;
11212 int count = specpdl_ptr - specpdl;
11213 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11215 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11216 CHECK_STRING (prompt, 0);
11217 CHECK_STRING (dir, 1);
11219 /* Prevent redisplay. */
11220 specbind (Qinhibit_redisplay, Qt);
11222 BLOCK_INPUT;
11224 /* Create the dialog with PROMPT as title, using DIR as initial
11225 directory and using "*" as pattern. */
11226 dir = Fexpand_file_name (dir, Qnil);
11227 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
11228 pattern_xmstring = XmStringCreateLocalized ("*");
11230 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
11231 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11232 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11233 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11234 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11235 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11236 "fsb", al, ac);
11237 XmStringFree (dir_xmstring);
11238 XmStringFree (pattern_xmstring);
11240 /* Add callbacks for OK and Cancel. */
11241 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11242 (XtPointer) &result);
11243 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11244 (XtPointer) &result);
11245 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11246 (XtPointer) &result);
11248 /* Disable the help button since we can't display help. */
11249 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11250 XtSetSensitive (help, False);
11252 /* Mark OK button as default. */
11253 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11254 XmNshowAsDefault, True, NULL);
11256 /* If MUSTMATCH is non-nil, disable the file entry field of the
11257 dialog, so that the user must select a file from the files list
11258 box. We can't remove it because we wouldn't have a way to get at
11259 the result file name, then. */
11260 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11261 if (!NILP (mustmatch))
11263 Widget label;
11264 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11265 XtSetSensitive (text, False);
11266 XtSetSensitive (label, False);
11269 /* Manage the dialog, so that list boxes get filled. */
11270 XtManageChild (dialog);
11272 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11273 must include the path for this to work. */
11274 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11275 if (STRINGP (default_filename))
11277 XmString default_xmstring;
11278 int item_pos;
11280 default_xmstring
11281 = XmStringCreateLocalized (XSTRING (default_filename)->data);
11283 if (!XmListItemExists (list, default_xmstring))
11285 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11286 XmListAddItem (list, default_xmstring, 0);
11287 item_pos = 0;
11289 else
11290 item_pos = XmListItemPos (list, default_xmstring);
11291 XmStringFree (default_xmstring);
11293 /* Select the item and scroll it into view. */
11294 XmListSelectPos (list, item_pos, True);
11295 XmListSetPos (list, item_pos);
11298 /* Process events until the user presses Cancel or OK. Block
11299 and unblock input here so that we get a chance of processing
11300 expose events. */
11301 UNBLOCK_INPUT;
11302 result = 0;
11303 while (result == 0)
11305 BLOCK_INPUT;
11306 XtAppProcessEvent (Xt_app_con, XtIMAll);
11307 UNBLOCK_INPUT;
11309 BLOCK_INPUT;
11311 /* Get the result. */
11312 if (result == XmCR_OK)
11314 XmString text;
11315 String data;
11317 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11318 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11319 XmStringFree (text);
11320 file = build_string (data);
11321 XtFree (data);
11323 else
11324 file = Qnil;
11326 /* Clean up. */
11327 XtUnmanageChild (dialog);
11328 XtDestroyWidget (dialog);
11329 UNBLOCK_INPUT;
11330 UNGCPRO;
11332 /* Make "Cancel" equivalent to C-g. */
11333 if (NILP (file))
11334 Fsignal (Qquit, Qnil);
11336 return unbind_to (count, file);
11339 #endif /* USE_MOTIF */
11343 /***********************************************************************
11344 Keyboard
11345 ***********************************************************************/
11347 #ifdef HAVE_XKBGETKEYBOARD
11348 #include <X11/XKBlib.h>
11349 #include <X11/keysym.h>
11350 #endif
11352 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11353 Sx_backspace_delete_keys_p, 0, 1, 0,
11354 "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
11355 FRAME nil means use the selected frame.\n\
11356 Value is t if we know that both keys are present, and are mapped to the\n\
11357 usual X keysyms.")
11358 (frame)
11359 Lisp_Object frame;
11361 #ifdef HAVE_XKBGETKEYBOARD
11362 XkbDescPtr kb;
11363 struct frame *f = check_x_frame (frame);
11364 Display *dpy = FRAME_X_DISPLAY (f);
11365 Lisp_Object have_keys;
11366 int major, minor, op, event, error;
11368 BLOCK_INPUT;
11370 /* Check library version in case we're dynamically linked. */
11371 major = XkbMajorVersion;
11372 minor = XkbMinorVersion;
11373 if (!XkbLibraryVersion (&major, &minor))
11375 UNBLOCK_INPUT;
11376 return Qnil;
11379 /* Check that the server supports XKB. */
11380 major = XkbMajorVersion;
11381 minor = XkbMinorVersion;
11382 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11384 UNBLOCK_INPUT;
11385 return Qnil;
11388 have_keys = Qnil;
11389 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11390 if (kb)
11392 int delete_keycode = 0, backspace_keycode = 0, i;
11394 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11396 for (i = kb->min_key_code;
11397 (i < kb->max_key_code
11398 && (delete_keycode == 0 || backspace_keycode == 0));
11399 ++i)
11401 /* The XKB symbolic key names can be seen most easily in
11402 the PS file generated by `xkbprint -label name
11403 $DISPLAY'. */
11404 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11405 delete_keycode = i;
11406 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11407 backspace_keycode = i;
11410 XkbFreeNames (kb, 0, True);
11413 XkbFreeClientMap (kb, 0, True);
11415 if (delete_keycode
11416 && backspace_keycode
11417 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11418 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11419 have_keys = Qt;
11421 UNBLOCK_INPUT;
11422 return have_keys;
11423 #else /* not HAVE_XKBGETKEYBOARD */
11424 return Qnil;
11425 #endif /* not HAVE_XKBGETKEYBOARD */
11430 /***********************************************************************
11431 Initialization
11432 ***********************************************************************/
11434 void
11435 syms_of_xfns ()
11437 /* This is zero if not using X windows. */
11438 x_in_use = 0;
11440 /* The section below is built by the lisp expression at the top of the file,
11441 just above where these variables are declared. */
11442 /*&&& init symbols here &&&*/
11443 Qauto_raise = intern ("auto-raise");
11444 staticpro (&Qauto_raise);
11445 Qauto_lower = intern ("auto-lower");
11446 staticpro (&Qauto_lower);
11447 Qbar = intern ("bar");
11448 staticpro (&Qbar);
11449 Qborder_color = intern ("border-color");
11450 staticpro (&Qborder_color);
11451 Qborder_width = intern ("border-width");
11452 staticpro (&Qborder_width);
11453 Qbox = intern ("box");
11454 staticpro (&Qbox);
11455 Qcursor_color = intern ("cursor-color");
11456 staticpro (&Qcursor_color);
11457 Qcursor_type = intern ("cursor-type");
11458 staticpro (&Qcursor_type);
11459 Qgeometry = intern ("geometry");
11460 staticpro (&Qgeometry);
11461 Qicon_left = intern ("icon-left");
11462 staticpro (&Qicon_left);
11463 Qicon_top = intern ("icon-top");
11464 staticpro (&Qicon_top);
11465 Qicon_type = intern ("icon-type");
11466 staticpro (&Qicon_type);
11467 Qicon_name = intern ("icon-name");
11468 staticpro (&Qicon_name);
11469 Qinternal_border_width = intern ("internal-border-width");
11470 staticpro (&Qinternal_border_width);
11471 Qleft = intern ("left");
11472 staticpro (&Qleft);
11473 Qright = intern ("right");
11474 staticpro (&Qright);
11475 Qmouse_color = intern ("mouse-color");
11476 staticpro (&Qmouse_color);
11477 Qnone = intern ("none");
11478 staticpro (&Qnone);
11479 Qparent_id = intern ("parent-id");
11480 staticpro (&Qparent_id);
11481 Qscroll_bar_width = intern ("scroll-bar-width");
11482 staticpro (&Qscroll_bar_width);
11483 Qsuppress_icon = intern ("suppress-icon");
11484 staticpro (&Qsuppress_icon);
11485 Qundefined_color = intern ("undefined-color");
11486 staticpro (&Qundefined_color);
11487 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11488 staticpro (&Qvertical_scroll_bars);
11489 Qvisibility = intern ("visibility");
11490 staticpro (&Qvisibility);
11491 Qwindow_id = intern ("window-id");
11492 staticpro (&Qwindow_id);
11493 Qouter_window_id = intern ("outer-window-id");
11494 staticpro (&Qouter_window_id);
11495 Qx_frame_parameter = intern ("x-frame-parameter");
11496 staticpro (&Qx_frame_parameter);
11497 Qx_resource_name = intern ("x-resource-name");
11498 staticpro (&Qx_resource_name);
11499 Quser_position = intern ("user-position");
11500 staticpro (&Quser_position);
11501 Quser_size = intern ("user-size");
11502 staticpro (&Quser_size);
11503 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11504 staticpro (&Qscroll_bar_foreground);
11505 Qscroll_bar_background = intern ("scroll-bar-background");
11506 staticpro (&Qscroll_bar_background);
11507 Qscreen_gamma = intern ("screen-gamma");
11508 staticpro (&Qscreen_gamma);
11509 Qline_spacing = intern ("line-spacing");
11510 staticpro (&Qline_spacing);
11511 Qcenter = intern ("center");
11512 staticpro (&Qcenter);
11513 Qcompound_text = intern ("compound-text");
11514 staticpro (&Qcompound_text);
11515 Qcancel_timer = intern ("cancel-timer");
11516 staticpro (&Qcancel_timer);
11517 Qwait_for_wm = intern ("wait-for-wm");
11518 staticpro (&Qwait_for_wm);
11519 /* This is the end of symbol initialization. */
11521 /* Text property `display' should be nonsticky by default. */
11522 Vtext_property_default_nonsticky
11523 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11526 Qlaplace = intern ("laplace");
11527 staticpro (&Qlaplace);
11528 Qemboss = intern ("emboss");
11529 staticpro (&Qemboss);
11530 Qedge_detection = intern ("edge-detection");
11531 staticpro (&Qedge_detection);
11532 Qheuristic = intern ("heuristic");
11533 staticpro (&Qheuristic);
11534 QCmatrix = intern (":matrix");
11535 staticpro (&QCmatrix);
11536 QCcolor_adjustment = intern (":color-adjustment");
11537 staticpro (&QCcolor_adjustment);
11538 QCmask = intern (":mask");
11539 staticpro (&QCmask);
11541 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11542 staticpro (&Qface_set_after_frame_default);
11544 Fput (Qundefined_color, Qerror_conditions,
11545 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11546 Fput (Qundefined_color, Qerror_message,
11547 build_string ("Undefined color"));
11549 init_x_parm_symbols ();
11551 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11552 "Non-nil means always draw a cross over disabled images.\n\
11553 Disabled images are those having an `:conversion disabled' property.\n\
11554 A cross is always drawn on black & white displays.");
11555 cross_disabled_images = 0;
11557 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11558 "List of directories to search for bitmap files for X.");
11559 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11561 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11562 "The shape of the pointer when over text.\n\
11563 Changing the value does not affect existing frames\n\
11564 unless you set the mouse color.");
11565 Vx_pointer_shape = Qnil;
11567 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11568 "The name Emacs uses to look up X resources.\n\
11569 `x-get-resource' uses this as the first component of the instance name\n\
11570 when requesting resource values.\n\
11571 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11572 was invoked, or to the value specified with the `-name' or `-rn'\n\
11573 switches, if present.\n\
11575 It may be useful to bind this variable locally around a call\n\
11576 to `x-get-resource'. See also the variable `x-resource-class'.");
11577 Vx_resource_name = Qnil;
11579 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11580 "The class Emacs uses to look up X resources.\n\
11581 `x-get-resource' uses this as the first component of the instance class\n\
11582 when requesting resource values.\n\
11583 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11585 Setting this variable permanently is not a reasonable thing to do,\n\
11586 but binding this variable locally around a call to `x-get-resource'\n\
11587 is a reasonable practice. See also the variable `x-resource-name'.");
11588 Vx_resource_class = build_string (EMACS_CLASS);
11590 #if 0 /* This doesn't really do anything. */
11591 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11592 "The shape of the pointer when not over text.\n\
11593 This variable takes effect when you create a new frame\n\
11594 or when you set the mouse color.");
11595 #endif
11596 Vx_nontext_pointer_shape = Qnil;
11598 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
11599 "The shape of the pointer when Emacs is busy.\n\
11600 This variable takes effect when you create a new frame\n\
11601 or when you set the mouse color.");
11602 Vx_hourglass_pointer_shape = Qnil;
11604 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
11605 "Non-zero means Emacs displays an hourglass pointer on window systems.");
11606 display_hourglass_p = 1;
11608 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
11609 "*Seconds to wait before displaying an hourglass pointer.\n\
11610 Value must be an integer or float.");
11611 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
11613 #if 0 /* This doesn't really do anything. */
11614 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11615 "The shape of the pointer when over the mode line.\n\
11616 This variable takes effect when you create a new frame\n\
11617 or when you set the mouse color.");
11618 #endif
11619 Vx_mode_pointer_shape = Qnil;
11621 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11622 &Vx_sensitive_text_pointer_shape,
11623 "The shape of the pointer when over mouse-sensitive text.\n\
11624 This variable takes effect when you create a new frame\n\
11625 or when you set the mouse color.");
11626 Vx_sensitive_text_pointer_shape = Qnil;
11628 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11629 &Vx_window_horizontal_drag_shape,
11630 "Pointer shape to use for indicating a window can be dragged horizontally.\n\
11631 This variable takes effect when you create a new frame\n\
11632 or when you set the mouse color.");
11633 Vx_window_horizontal_drag_shape = Qnil;
11635 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11636 "A string indicating the foreground color of the cursor box.");
11637 Vx_cursor_fore_pixel = Qnil;
11639 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
11640 "Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).\n\
11641 Text larger than this is clipped.");
11642 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
11644 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11645 "Non-nil if no X window manager is in use.\n\
11646 Emacs doesn't try to figure this out; this is always nil\n\
11647 unless you set it to something else.");
11648 /* We don't have any way to find this out, so set it to nil
11649 and maybe the user would like to set it to t. */
11650 Vx_no_window_manager = Qnil;
11652 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11653 &Vx_pixel_size_width_font_regexp,
11654 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11656 Since Emacs gets width of a font matching with this regexp from\n\
11657 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11658 such a font. This is especially effective for such large fonts as\n\
11659 Chinese, Japanese, and Korean.");
11660 Vx_pixel_size_width_font_regexp = Qnil;
11662 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11663 "Time after which cached images are removed from the cache.\n\
11664 When an image has not been displayed this many seconds, remove it\n\
11665 from the image cache. Value must be an integer or nil with nil\n\
11666 meaning don't clear the cache.");
11667 Vimage_cache_eviction_delay = make_number (30 * 60);
11669 #ifdef USE_X_TOOLKIT
11670 Fprovide (intern ("x-toolkit"));
11672 #ifdef USE_MOTIF
11673 Fprovide (intern ("motif"));
11675 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
11676 "Version info for LessTif/Motif.");
11677 Vmotif_version_string = build_string (XmVERSION_STRING);
11678 #endif /* USE_MOTIF */
11679 #endif /* USE_X_TOOLKIT */
11681 defsubr (&Sx_get_resource);
11683 /* X window properties. */
11684 defsubr (&Sx_change_window_property);
11685 defsubr (&Sx_delete_window_property);
11686 defsubr (&Sx_window_property);
11688 defsubr (&Sxw_display_color_p);
11689 defsubr (&Sx_display_grayscale_p);
11690 defsubr (&Sxw_color_defined_p);
11691 defsubr (&Sxw_color_values);
11692 defsubr (&Sx_server_max_request_size);
11693 defsubr (&Sx_server_vendor);
11694 defsubr (&Sx_server_version);
11695 defsubr (&Sx_display_pixel_width);
11696 defsubr (&Sx_display_pixel_height);
11697 defsubr (&Sx_display_mm_width);
11698 defsubr (&Sx_display_mm_height);
11699 defsubr (&Sx_display_screens);
11700 defsubr (&Sx_display_planes);
11701 defsubr (&Sx_display_color_cells);
11702 defsubr (&Sx_display_visual_class);
11703 defsubr (&Sx_display_backing_store);
11704 defsubr (&Sx_display_save_under);
11705 defsubr (&Sx_parse_geometry);
11706 defsubr (&Sx_create_frame);
11707 defsubr (&Sx_open_connection);
11708 defsubr (&Sx_close_connection);
11709 defsubr (&Sx_display_list);
11710 defsubr (&Sx_synchronize);
11711 defsubr (&Sx_focus_frame);
11712 defsubr (&Sx_backspace_delete_keys_p);
11714 /* Setting callback functions for fontset handler. */
11715 get_font_info_func = x_get_font_info;
11717 #if 0 /* This function pointer doesn't seem to be used anywhere.
11718 And the pointer assigned has the wrong type, anyway. */
11719 list_fonts_func = x_list_fonts;
11720 #endif
11722 load_font_func = x_load_font;
11723 find_ccl_program_func = x_find_ccl_program;
11724 query_font_func = x_query_font;
11725 set_frame_fontset_func = x_set_font;
11726 check_window_system_func = check_x;
11728 /* Images. */
11729 Qxbm = intern ("xbm");
11730 staticpro (&Qxbm);
11731 QCtype = intern (":type");
11732 staticpro (&QCtype);
11733 QCconversion = intern (":conversion");
11734 staticpro (&QCconversion);
11735 QCheuristic_mask = intern (":heuristic-mask");
11736 staticpro (&QCheuristic_mask);
11737 QCcolor_symbols = intern (":color-symbols");
11738 staticpro (&QCcolor_symbols);
11739 QCascent = intern (":ascent");
11740 staticpro (&QCascent);
11741 QCmargin = intern (":margin");
11742 staticpro (&QCmargin);
11743 QCrelief = intern (":relief");
11744 staticpro (&QCrelief);
11745 Qpostscript = intern ("postscript");
11746 staticpro (&Qpostscript);
11747 QCloader = intern (":loader");
11748 staticpro (&QCloader);
11749 QCbounding_box = intern (":bounding-box");
11750 staticpro (&QCbounding_box);
11751 QCpt_width = intern (":pt-width");
11752 staticpro (&QCpt_width);
11753 QCpt_height = intern (":pt-height");
11754 staticpro (&QCpt_height);
11755 QCindex = intern (":index");
11756 staticpro (&QCindex);
11757 Qpbm = intern ("pbm");
11758 staticpro (&Qpbm);
11760 #if HAVE_XPM
11761 Qxpm = intern ("xpm");
11762 staticpro (&Qxpm);
11763 #endif
11765 #if HAVE_JPEG
11766 Qjpeg = intern ("jpeg");
11767 staticpro (&Qjpeg);
11768 #endif
11770 #if HAVE_TIFF
11771 Qtiff = intern ("tiff");
11772 staticpro (&Qtiff);
11773 #endif
11775 #if HAVE_GIF
11776 Qgif = intern ("gif");
11777 staticpro (&Qgif);
11778 #endif
11780 #if HAVE_PNG
11781 Qpng = intern ("png");
11782 staticpro (&Qpng);
11783 #endif
11785 defsubr (&Sclear_image_cache);
11786 defsubr (&Simage_size);
11787 defsubr (&Simage_mask_p);
11789 hourglass_atimer = NULL;
11790 hourglass_shown_p = 0;
11792 defsubr (&Sx_show_tip);
11793 defsubr (&Sx_hide_tip);
11794 tip_timer = Qnil;
11795 staticpro (&tip_timer);
11796 tip_frame = Qnil;
11797 staticpro (&tip_frame);
11799 last_show_tip_args = Qnil;
11800 staticpro (&last_show_tip_args);
11802 #ifdef USE_MOTIF
11803 defsubr (&Sx_file_dialog);
11804 #endif
11808 void
11809 init_xfns ()
11811 image_types = NULL;
11812 Vimage_types = Qnil;
11814 define_image_type (&xbm_type);
11815 define_image_type (&gs_type);
11816 define_image_type (&pbm_type);
11818 #if HAVE_XPM
11819 define_image_type (&xpm_type);
11820 #endif
11822 #if HAVE_JPEG
11823 define_image_type (&jpeg_type);
11824 #endif
11826 #if HAVE_TIFF
11827 define_image_type (&tiff_type);
11828 #endif
11830 #if HAVE_GIF
11831 define_image_type (&gif_type);
11832 #endif
11834 #if HAVE_PNG
11835 define_image_type (&png_type);
11836 #endif
11839 #endif /* HAVE_X_WINDOWS */