Add the latest changes to etags behaviour.
[emacs/old-mirror.git] / src / xfns.c
blob485a2f9b4c72555f6ebd208455a97387b4c8f56b
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include <epaths.h>
41 #include "charset.h"
42 #include "coding.h"
43 #include "fontset.h"
44 #include "systime.h"
45 #include "termhooks.h"
46 #include "atimer.h"
48 #ifdef HAVE_X_WINDOWS
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
54 #ifndef VMS
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
57 #else
58 #include <X11/bitmaps/gray>
59 #endif
60 #else
61 #include "[.bitmaps]gray.xbm"
62 #endif
64 #ifdef USE_X_TOOLKIT
65 #include <X11/Shell.h>
67 #ifndef USE_MOTIF
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
72 #ifdef USG
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
74 #include <X11/Xos.h>
75 #define USG
76 #else
77 #include <X11/Xos.h>
78 #endif
80 #include "widget.h"
82 #include "../lwlib/lwlib.h"
84 #ifdef USE_MOTIF
85 #include <Xm/Xm.h>
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
88 #endif
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
94 #define HACK_EDITRES
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick;
102 #ifdef USE_LUCID
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct *xlwmenu_default_font;
105 #endif
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #ifdef USE_MOTIF
112 /* LessTif/Motif version info. */
114 static Lisp_Object Vmotif_version_string;
116 #endif /* USE_MOTIF */
118 #endif /* USE_X_TOOLKIT */
120 #define min(a,b) ((a) < (b) ? (a) : (b))
121 #define max(a,b) ((a) > (b) ? (a) : (b))
123 #ifdef HAVE_X11R4
124 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
125 #else
126 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
127 #endif
129 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
130 it, and including `bitmaps/gray' more than once is a problem when
131 config.h defines `static' as an empty replacement string. */
133 int gray_bitmap_width = gray_width;
134 int gray_bitmap_height = gray_height;
135 char *gray_bitmap_bits = gray_bits;
137 /* The name we're using in resource queries. Most often "emacs". */
139 Lisp_Object Vx_resource_name;
141 /* The application class we're using in resource queries.
142 Normally "Emacs". */
144 Lisp_Object Vx_resource_class;
146 /* Non-zero means we're allowed to display an hourglass cursor. */
148 int display_hourglass_p;
150 /* The background and shape of the mouse pointer, and shape when not
151 over text or in the modeline. */
153 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
154 Lisp_Object Vx_hourglass_pointer_shape;
156 /* The shape when over mouse-sensitive text. */
158 Lisp_Object Vx_sensitive_text_pointer_shape;
160 /* If non-nil, the pointer shape to indicate that windows can be
161 dragged horizontally. */
163 Lisp_Object Vx_window_horizontal_drag_shape;
165 /* Color of chars displayed in cursor box. */
167 Lisp_Object Vx_cursor_fore_pixel;
169 /* Nonzero if using X. */
171 static int x_in_use;
173 /* Non nil if no window manager is in use. */
175 Lisp_Object Vx_no_window_manager;
177 /* Search path for bitmap files. */
179 Lisp_Object Vx_bitmap_file_path;
181 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
183 Lisp_Object Vx_pixel_size_width_font_regexp;
185 Lisp_Object Qauto_raise;
186 Lisp_Object Qauto_lower;
187 Lisp_Object Qbar;
188 Lisp_Object Qborder_color;
189 Lisp_Object Qborder_width;
190 Lisp_Object Qbox;
191 Lisp_Object Qcursor_color;
192 Lisp_Object Qcursor_type;
193 Lisp_Object Qgeometry;
194 Lisp_Object Qicon_left;
195 Lisp_Object Qicon_top;
196 Lisp_Object Qicon_type;
197 Lisp_Object Qicon_name;
198 Lisp_Object Qinternal_border_width;
199 Lisp_Object Qleft;
200 Lisp_Object Qright;
201 Lisp_Object Qmouse_color;
202 Lisp_Object Qnone;
203 Lisp_Object Qouter_window_id;
204 Lisp_Object Qparent_id;
205 Lisp_Object Qscroll_bar_width;
206 Lisp_Object Qsuppress_icon;
207 extern Lisp_Object Qtop;
208 Lisp_Object Qundefined_color;
209 Lisp_Object Qvertical_scroll_bars;
210 Lisp_Object Qvisibility;
211 Lisp_Object Qwindow_id;
212 Lisp_Object Qx_frame_parameter;
213 Lisp_Object Qx_resource_name;
214 Lisp_Object Quser_position;
215 Lisp_Object Quser_size;
216 extern Lisp_Object Qdisplay;
217 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
218 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
219 Lisp_Object Qcompound_text, Qcancel_timer;
221 /* The below are defined in frame.c. */
223 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
224 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
225 extern Lisp_Object Qtool_bar_lines;
227 extern Lisp_Object Vwindow_system_version;
229 Lisp_Object Qface_set_after_frame_default;
231 #if GLYPH_DEBUG
232 int image_cache_refcount, dpyinfo_refcount;
233 #endif
237 /* Error if we are not connected to X. */
239 void
240 check_x ()
242 if (! x_in_use)
243 error ("X windows are not in use or not initialized");
246 /* Nonzero if we can use mouse menus.
247 You should not call this unless HAVE_MENUS is defined. */
250 have_menus_p ()
252 return x_in_use;
255 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
256 and checking validity for X. */
258 FRAME_PTR
259 check_x_frame (frame)
260 Lisp_Object frame;
262 FRAME_PTR f;
264 if (NILP (frame))
265 frame = selected_frame;
266 CHECK_LIVE_FRAME (frame, 0);
267 f = XFRAME (frame);
268 if (! FRAME_X_P (f))
269 error ("Non-X frame used");
270 return f;
273 /* Let the user specify an X display with a frame.
274 nil stands for the selected frame--or, if that is not an X frame,
275 the first X display on the list. */
277 static struct x_display_info *
278 check_x_display_info (frame)
279 Lisp_Object frame;
281 struct x_display_info *dpyinfo = NULL;
283 if (NILP (frame))
285 struct frame *sf = XFRAME (selected_frame);
287 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
288 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
289 else if (x_display_list != 0)
290 dpyinfo = x_display_list;
291 else
292 error ("X windows are not in use or not initialized");
294 else if (STRINGP (frame))
295 dpyinfo = x_display_info_for_name (frame);
296 else
298 FRAME_PTR f;
300 CHECK_LIVE_FRAME (frame, 0);
301 f = XFRAME (frame);
302 if (! FRAME_X_P (f))
303 error ("Non-X frame used");
304 dpyinfo = FRAME_X_DISPLAY_INFO (f);
307 return dpyinfo;
311 /* Return the Emacs frame-object corresponding to an X window.
312 It could be the frame's main window or an icon window. */
314 /* This function can be called during GC, so use GC_xxx type test macros. */
316 struct frame *
317 x_window_to_frame (dpyinfo, wdesc)
318 struct x_display_info *dpyinfo;
319 int wdesc;
321 Lisp_Object tail, frame;
322 struct frame *f;
324 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
326 frame = XCAR (tail);
327 if (!GC_FRAMEP (frame))
328 continue;
329 f = XFRAME (frame);
330 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
331 continue;
332 if (f->output_data.x->hourglass_window == wdesc)
333 return f;
334 #ifdef USE_X_TOOLKIT
335 if ((f->output_data.x->edit_widget
336 && XtWindow (f->output_data.x->edit_widget) == wdesc)
337 /* A tooltip frame? */
338 || (!f->output_data.x->edit_widget
339 && FRAME_X_WINDOW (f) == wdesc)
340 || f->output_data.x->icon_desc == wdesc)
341 return f;
342 #else /* not USE_X_TOOLKIT */
343 if (FRAME_X_WINDOW (f) == wdesc
344 || f->output_data.x->icon_desc == wdesc)
345 return f;
346 #endif /* not USE_X_TOOLKIT */
348 return 0;
351 #ifdef USE_X_TOOLKIT
352 /* Like x_window_to_frame but also compares the window with the widget's
353 windows. */
355 struct frame *
356 x_any_window_to_frame (dpyinfo, wdesc)
357 struct x_display_info *dpyinfo;
358 int wdesc;
360 Lisp_Object tail, frame;
361 struct frame *f, *found;
362 struct x_output *x;
364 found = NULL;
365 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
367 frame = XCAR (tail);
368 if (!GC_FRAMEP (frame))
369 continue;
371 f = XFRAME (frame);
372 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
374 /* This frame matches if the window is any of its widgets. */
375 x = f->output_data.x;
376 if (x->hourglass_window == wdesc)
377 found = f;
378 else if (x->widget)
380 if (wdesc == XtWindow (x->widget)
381 || wdesc == XtWindow (x->column_widget)
382 || wdesc == XtWindow (x->edit_widget))
383 found = f;
384 /* Match if the window is this frame's menubar. */
385 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
386 found = f;
388 else if (FRAME_X_WINDOW (f) == wdesc)
389 /* A tooltip frame. */
390 found = f;
394 return found;
397 /* Likewise, but exclude the menu bar widget. */
399 struct frame *
400 x_non_menubar_window_to_frame (dpyinfo, wdesc)
401 struct x_display_info *dpyinfo;
402 int wdesc;
404 Lisp_Object tail, frame;
405 struct frame *f;
406 struct x_output *x;
408 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
410 frame = XCAR (tail);
411 if (!GC_FRAMEP (frame))
412 continue;
413 f = XFRAME (frame);
414 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
415 continue;
416 x = f->output_data.x;
417 /* This frame matches if the window is any of its widgets. */
418 if (x->hourglass_window == wdesc)
419 return f;
420 else if (x->widget)
422 if (wdesc == XtWindow (x->widget)
423 || wdesc == XtWindow (x->column_widget)
424 || wdesc == XtWindow (x->edit_widget))
425 return f;
427 else if (FRAME_X_WINDOW (f) == wdesc)
428 /* A tooltip frame. */
429 return f;
431 return 0;
434 /* Likewise, but consider only the menu bar widget. */
436 struct frame *
437 x_menubar_window_to_frame (dpyinfo, wdesc)
438 struct x_display_info *dpyinfo;
439 int wdesc;
441 Lisp_Object tail, frame;
442 struct frame *f;
443 struct x_output *x;
445 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
447 frame = XCAR (tail);
448 if (!GC_FRAMEP (frame))
449 continue;
450 f = XFRAME (frame);
451 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
452 continue;
453 x = f->output_data.x;
454 /* Match if the window is this frame's menubar. */
455 if (x->menubar_widget
456 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
457 return f;
459 return 0;
462 /* Return the frame whose principal (outermost) window is WDESC.
463 If WDESC is some other (smaller) window, we return 0. */
465 struct frame *
466 x_top_window_to_frame (dpyinfo, wdesc)
467 struct x_display_info *dpyinfo;
468 int wdesc;
470 Lisp_Object tail, frame;
471 struct frame *f;
472 struct x_output *x;
474 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
476 frame = XCAR (tail);
477 if (!GC_FRAMEP (frame))
478 continue;
479 f = XFRAME (frame);
480 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
481 continue;
482 x = f->output_data.x;
484 if (x->widget)
486 /* This frame matches if the window is its topmost widget. */
487 if (wdesc == XtWindow (x->widget))
488 return f;
489 #if 0 /* I don't know why it did this,
490 but it seems logically wrong,
491 and it causes trouble for MapNotify events. */
492 /* Match if the window is this frame's menubar. */
493 if (x->menubar_widget
494 && wdesc == XtWindow (x->menubar_widget))
495 return f;
496 #endif
498 else if (FRAME_X_WINDOW (f) == wdesc)
499 /* Tooltip frame. */
500 return f;
502 return 0;
504 #endif /* USE_X_TOOLKIT */
508 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
509 id, which is just an int that this section returns. Bitmaps are
510 reference counted so they can be shared among frames.
512 Bitmap indices are guaranteed to be > 0, so a negative number can
513 be used to indicate no bitmap.
515 If you use x_create_bitmap_from_data, then you must keep track of
516 the bitmaps yourself. That is, creating a bitmap from the same
517 data more than once will not be caught. */
520 /* Functions to access the contents of a bitmap, given an id. */
523 x_bitmap_height (f, id)
524 FRAME_PTR f;
525 int id;
527 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
531 x_bitmap_width (f, id)
532 FRAME_PTR f;
533 int id;
535 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
539 x_bitmap_pixmap (f, id)
540 FRAME_PTR f;
541 int id;
543 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
547 /* Allocate a new bitmap record. Returns index of new record. */
549 static int
550 x_allocate_bitmap_record (f)
551 FRAME_PTR f;
553 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
554 int i;
556 if (dpyinfo->bitmaps == NULL)
558 dpyinfo->bitmaps_size = 10;
559 dpyinfo->bitmaps
560 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
561 dpyinfo->bitmaps_last = 1;
562 return 1;
565 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
566 return ++dpyinfo->bitmaps_last;
568 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
569 if (dpyinfo->bitmaps[i].refcount == 0)
570 return i + 1;
572 dpyinfo->bitmaps_size *= 2;
573 dpyinfo->bitmaps
574 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
575 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
576 return ++dpyinfo->bitmaps_last;
579 /* Add one reference to the reference count of the bitmap with id ID. */
581 void
582 x_reference_bitmap (f, id)
583 FRAME_PTR f;
584 int id;
586 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
589 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
592 x_create_bitmap_from_data (f, bits, width, height)
593 struct frame *f;
594 char *bits;
595 unsigned int width, height;
597 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
598 Pixmap bitmap;
599 int id;
601 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
602 bits, width, height);
604 if (! bitmap)
605 return -1;
607 id = x_allocate_bitmap_record (f);
608 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
609 dpyinfo->bitmaps[id - 1].file = NULL;
610 dpyinfo->bitmaps[id - 1].refcount = 1;
611 dpyinfo->bitmaps[id - 1].depth = 1;
612 dpyinfo->bitmaps[id - 1].height = height;
613 dpyinfo->bitmaps[id - 1].width = width;
615 return id;
618 /* Create bitmap from file FILE for frame F. */
621 x_create_bitmap_from_file (f, file)
622 struct frame *f;
623 Lisp_Object file;
625 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
626 unsigned int width, height;
627 Pixmap bitmap;
628 int xhot, yhot, result, id;
629 Lisp_Object found;
630 int fd;
631 char *filename;
633 /* Look for an existing bitmap with the same name. */
634 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
636 if (dpyinfo->bitmaps[id].refcount
637 && dpyinfo->bitmaps[id].file
638 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
640 ++dpyinfo->bitmaps[id].refcount;
641 return id + 1;
645 /* Search bitmap-file-path for the file, if appropriate. */
646 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
647 if (fd < 0)
648 return -1;
649 emacs_close (fd);
651 filename = (char *) XSTRING (found)->data;
653 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
654 filename, &width, &height, &bitmap, &xhot, &yhot);
655 if (result != BitmapSuccess)
656 return -1;
658 id = x_allocate_bitmap_record (f);
659 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
660 dpyinfo->bitmaps[id - 1].refcount = 1;
661 dpyinfo->bitmaps[id - 1].file
662 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
663 dpyinfo->bitmaps[id - 1].depth = 1;
664 dpyinfo->bitmaps[id - 1].height = height;
665 dpyinfo->bitmaps[id - 1].width = width;
666 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
668 return id;
671 /* Remove reference to bitmap with id number ID. */
673 void
674 x_destroy_bitmap (f, id)
675 FRAME_PTR f;
676 int id;
678 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
680 if (id > 0)
682 --dpyinfo->bitmaps[id - 1].refcount;
683 if (dpyinfo->bitmaps[id - 1].refcount == 0)
685 BLOCK_INPUT;
686 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
687 if (dpyinfo->bitmaps[id - 1].file)
689 xfree (dpyinfo->bitmaps[id - 1].file);
690 dpyinfo->bitmaps[id - 1].file = NULL;
692 UNBLOCK_INPUT;
697 /* Free all the bitmaps for the display specified by DPYINFO. */
699 static void
700 x_destroy_all_bitmaps (dpyinfo)
701 struct x_display_info *dpyinfo;
703 int i;
704 for (i = 0; i < dpyinfo->bitmaps_last; i++)
705 if (dpyinfo->bitmaps[i].refcount > 0)
707 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
708 if (dpyinfo->bitmaps[i].file)
709 xfree (dpyinfo->bitmaps[i].file);
711 dpyinfo->bitmaps_last = 0;
714 /* Connect the frame-parameter names for X frames
715 to the ways of passing the parameter values to the window system.
717 The name of a parameter, as a Lisp symbol,
718 has an `x-frame-parameter' property which is an integer in Lisp
719 that is an index in this table. */
721 struct x_frame_parm_table
723 char *name;
724 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
727 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
728 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
729 static void x_change_window_heights P_ ((Lisp_Object, int));
730 static void x_disable_image P_ ((struct frame *, struct image *));
731 static void x_create_im P_ ((struct frame *));
732 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
733 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
734 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
735 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
736 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
744 Lisp_Object));
745 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
746 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
749 Lisp_Object));
750 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
757 Lisp_Object));
758 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
759 Lisp_Object));
760 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
761 Lisp_Object,
762 Lisp_Object,
763 char *, char *,
764 int));
765 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
766 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
767 Lisp_Object));
768 static void init_color_table P_ ((void));
769 static void free_color_table P_ ((void));
770 static unsigned long *colors_in_color_table P_ ((int *n));
771 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
772 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
776 static struct x_frame_parm_table x_frame_parms[] =
778 "auto-raise", x_set_autoraise,
779 "auto-lower", x_set_autolower,
780 "background-color", x_set_background_color,
781 "border-color", x_set_border_color,
782 "border-width", x_set_border_width,
783 "cursor-color", x_set_cursor_color,
784 "cursor-type", x_set_cursor_type,
785 "font", x_set_font,
786 "foreground-color", x_set_foreground_color,
787 "icon-name", x_set_icon_name,
788 "icon-type", x_set_icon_type,
789 "internal-border-width", x_set_internal_border_width,
790 "menu-bar-lines", x_set_menu_bar_lines,
791 "mouse-color", x_set_mouse_color,
792 "name", x_explicitly_set_name,
793 "scroll-bar-width", x_set_scroll_bar_width,
794 "title", x_set_title,
795 "unsplittable", x_set_unsplittable,
796 "vertical-scroll-bars", x_set_vertical_scroll_bars,
797 "visibility", x_set_visibility,
798 "tool-bar-lines", x_set_tool_bar_lines,
799 "scroll-bar-foreground", x_set_scroll_bar_foreground,
800 "scroll-bar-background", x_set_scroll_bar_background,
801 "screen-gamma", x_set_screen_gamma,
802 "line-spacing", x_set_line_spacing
805 /* Attach the `x-frame-parameter' properties to
806 the Lisp symbol names of parameters relevant to X. */
808 void
809 init_x_parm_symbols ()
811 int i;
813 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
814 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
815 make_number (i));
818 /* Change the parameters of frame F as specified by ALIST.
819 If a parameter is not specially recognized, do nothing special;
820 otherwise call the `x_set_...' function for that parameter.
821 Except for certain geometry properties, always call store_frame_param
822 to store the new value in the parameter alist. */
824 void
825 x_set_frame_parameters (f, alist)
826 FRAME_PTR f;
827 Lisp_Object alist;
829 Lisp_Object tail;
831 /* If both of these parameters are present, it's more efficient to
832 set them both at once. So we wait until we've looked at the
833 entire list before we set them. */
834 int width, height;
836 /* Same here. */
837 Lisp_Object left, top;
839 /* Same with these. */
840 Lisp_Object icon_left, icon_top;
842 /* Record in these vectors all the parms specified. */
843 Lisp_Object *parms;
844 Lisp_Object *values;
845 int i, p;
846 int left_no_change = 0, top_no_change = 0;
847 int icon_left_no_change = 0, icon_top_no_change = 0;
849 struct gcpro gcpro1, gcpro2;
851 i = 0;
852 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
853 i++;
855 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
856 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
858 /* Extract parm names and values into those vectors. */
860 i = 0;
861 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
863 Lisp_Object elt;
865 elt = Fcar (tail);
866 parms[i] = Fcar (elt);
867 values[i] = Fcdr (elt);
868 i++;
870 /* TAIL and ALIST are not used again below here. */
871 alist = tail = Qnil;
873 GCPRO2 (*parms, *values);
874 gcpro1.nvars = i;
875 gcpro2.nvars = i;
877 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
878 because their values appear in VALUES and strings are not valid. */
879 top = left = Qunbound;
880 icon_left = icon_top = Qunbound;
882 /* Provide default values for HEIGHT and WIDTH. */
883 if (FRAME_NEW_WIDTH (f))
884 width = FRAME_NEW_WIDTH (f);
885 else
886 width = FRAME_WIDTH (f);
888 if (FRAME_NEW_HEIGHT (f))
889 height = FRAME_NEW_HEIGHT (f);
890 else
891 height = FRAME_HEIGHT (f);
893 /* Process foreground_color and background_color before anything else.
894 They are independent of other properties, but other properties (e.g.,
895 cursor_color) are dependent upon them. */
896 for (p = 0; p < i; p++)
898 Lisp_Object prop, val;
900 prop = parms[p];
901 val = values[p];
902 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
904 register Lisp_Object param_index, old_value;
906 param_index = Fget (prop, Qx_frame_parameter);
907 old_value = get_frame_param (f, prop);
908 store_frame_param (f, prop, val);
909 if (NATNUMP (param_index)
910 && (XFASTINT (param_index)
911 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
912 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
916 /* Now process them in reverse of specified order. */
917 for (i--; i >= 0; i--)
919 Lisp_Object prop, val;
921 prop = parms[i];
922 val = values[i];
924 if (EQ (prop, Qwidth) && NUMBERP (val))
925 width = XFASTINT (val);
926 else if (EQ (prop, Qheight) && NUMBERP (val))
927 height = XFASTINT (val);
928 else if (EQ (prop, Qtop))
929 top = val;
930 else if (EQ (prop, Qleft))
931 left = val;
932 else if (EQ (prop, Qicon_top))
933 icon_top = val;
934 else if (EQ (prop, Qicon_left))
935 icon_left = val;
936 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
937 /* Processed above. */
938 continue;
939 else
941 register Lisp_Object param_index, old_value;
943 param_index = Fget (prop, Qx_frame_parameter);
944 old_value = get_frame_param (f, prop);
945 store_frame_param (f, prop, val);
946 if (NATNUMP (param_index)
947 && (XFASTINT (param_index)
948 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
949 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
953 /* Don't die if just one of these was set. */
954 if (EQ (left, Qunbound))
956 left_no_change = 1;
957 if (f->output_data.x->left_pos < 0)
958 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
959 else
960 XSETINT (left, f->output_data.x->left_pos);
962 if (EQ (top, Qunbound))
964 top_no_change = 1;
965 if (f->output_data.x->top_pos < 0)
966 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
967 else
968 XSETINT (top, f->output_data.x->top_pos);
971 /* If one of the icon positions was not set, preserve or default it. */
972 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
974 icon_left_no_change = 1;
975 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
976 if (NILP (icon_left))
977 XSETINT (icon_left, 0);
979 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
981 icon_top_no_change = 1;
982 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
983 if (NILP (icon_top))
984 XSETINT (icon_top, 0);
987 /* Don't set these parameters unless they've been explicitly
988 specified. The window might be mapped or resized while we're in
989 this function, and we don't want to override that unless the lisp
990 code has asked for it.
992 Don't set these parameters unless they actually differ from the
993 window's current parameters; the window may not actually exist
994 yet. */
996 Lisp_Object frame;
998 check_frame_size (f, &height, &width);
1000 XSETFRAME (frame, f);
1002 if (width != FRAME_WIDTH (f)
1003 || height != FRAME_HEIGHT (f)
1004 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1005 Fset_frame_size (frame, make_number (width), make_number (height));
1007 if ((!NILP (left) || !NILP (top))
1008 && ! (left_no_change && top_no_change)
1009 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1010 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1012 int leftpos = 0;
1013 int toppos = 0;
1015 /* Record the signs. */
1016 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1017 if (EQ (left, Qminus))
1018 f->output_data.x->size_hint_flags |= XNegative;
1019 else if (INTEGERP (left))
1021 leftpos = XINT (left);
1022 if (leftpos < 0)
1023 f->output_data.x->size_hint_flags |= XNegative;
1025 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1026 && CONSP (XCDR (left))
1027 && INTEGERP (XCAR (XCDR (left))))
1029 leftpos = - XINT (XCAR (XCDR (left)));
1030 f->output_data.x->size_hint_flags |= XNegative;
1032 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1033 && CONSP (XCDR (left))
1034 && INTEGERP (XCAR (XCDR (left))))
1036 leftpos = XINT (XCAR (XCDR (left)));
1039 if (EQ (top, Qminus))
1040 f->output_data.x->size_hint_flags |= YNegative;
1041 else if (INTEGERP (top))
1043 toppos = XINT (top);
1044 if (toppos < 0)
1045 f->output_data.x->size_hint_flags |= YNegative;
1047 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1048 && CONSP (XCDR (top))
1049 && INTEGERP (XCAR (XCDR (top))))
1051 toppos = - XINT (XCAR (XCDR (top)));
1052 f->output_data.x->size_hint_flags |= YNegative;
1054 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1055 && CONSP (XCDR (top))
1056 && INTEGERP (XCAR (XCDR (top))))
1058 toppos = XINT (XCAR (XCDR (top)));
1062 /* Store the numeric value of the position. */
1063 f->output_data.x->top_pos = toppos;
1064 f->output_data.x->left_pos = leftpos;
1066 f->output_data.x->win_gravity = NorthWestGravity;
1068 /* Actually set that position, and convert to absolute. */
1069 x_set_offset (f, leftpos, toppos, -1);
1072 if ((!NILP (icon_left) || !NILP (icon_top))
1073 && ! (icon_left_no_change && icon_top_no_change))
1074 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1077 UNGCPRO;
1080 /* Store the screen positions of frame F into XPTR and YPTR.
1081 These are the positions of the containing window manager window,
1082 not Emacs's own window. */
1084 void
1085 x_real_positions (f, xptr, yptr)
1086 FRAME_PTR f;
1087 int *xptr, *yptr;
1089 int win_x, win_y;
1090 Window child;
1092 /* This is pretty gross, but seems to be the easiest way out of
1093 the problem that arises when restarting window-managers. */
1095 #ifdef USE_X_TOOLKIT
1096 Window outer = (f->output_data.x->widget
1097 ? XtWindow (f->output_data.x->widget)
1098 : FRAME_X_WINDOW (f));
1099 #else
1100 Window outer = f->output_data.x->window_desc;
1101 #endif
1102 Window tmp_root_window;
1103 Window *tmp_children;
1104 unsigned int tmp_nchildren;
1106 while (1)
1108 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1109 Window outer_window;
1111 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1112 &f->output_data.x->parent_desc,
1113 &tmp_children, &tmp_nchildren);
1114 XFree ((char *) tmp_children);
1116 win_x = win_y = 0;
1118 /* Find the position of the outside upper-left corner of
1119 the inner window, with respect to the outer window. */
1120 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1121 outer_window = f->output_data.x->parent_desc;
1122 else
1123 outer_window = outer;
1125 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1127 /* From-window, to-window. */
1128 outer_window,
1129 FRAME_X_DISPLAY_INFO (f)->root_window,
1131 /* From-position, to-position. */
1132 0, 0, &win_x, &win_y,
1134 /* Child of win. */
1135 &child);
1137 /* It is possible for the window returned by the XQueryNotify
1138 to become invalid by the time we call XTranslateCoordinates.
1139 That can happen when you restart some window managers.
1140 If so, we get an error in XTranslateCoordinates.
1141 Detect that and try the whole thing over. */
1142 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1144 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1145 break;
1148 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1151 *xptr = win_x;
1152 *yptr = win_y;
1155 /* Insert a description of internally-recorded parameters of frame X
1156 into the parameter alist *ALISTPTR that is to be given to the user.
1157 Only parameters that are specific to the X window system
1158 and whose values are not correctly recorded in the frame's
1159 param_alist need to be considered here. */
1161 void
1162 x_report_frame_params (f, alistptr)
1163 struct frame *f;
1164 Lisp_Object *alistptr;
1166 char buf[16];
1167 Lisp_Object tem;
1169 /* Represent negative positions (off the top or left screen edge)
1170 in a way that Fmodify_frame_parameters will understand correctly. */
1171 XSETINT (tem, f->output_data.x->left_pos);
1172 if (f->output_data.x->left_pos >= 0)
1173 store_in_alist (alistptr, Qleft, tem);
1174 else
1175 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1177 XSETINT (tem, f->output_data.x->top_pos);
1178 if (f->output_data.x->top_pos >= 0)
1179 store_in_alist (alistptr, Qtop, tem);
1180 else
1181 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1183 store_in_alist (alistptr, Qborder_width,
1184 make_number (f->output_data.x->border_width));
1185 store_in_alist (alistptr, Qinternal_border_width,
1186 make_number (f->output_data.x->internal_border_width));
1187 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1188 store_in_alist (alistptr, Qwindow_id,
1189 build_string (buf));
1190 #ifdef USE_X_TOOLKIT
1191 /* Tooltip frame may not have this widget. */
1192 if (f->output_data.x->widget)
1193 #endif
1194 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1195 store_in_alist (alistptr, Qouter_window_id,
1196 build_string (buf));
1197 store_in_alist (alistptr, Qicon_name, f->icon_name);
1198 FRAME_SAMPLE_VISIBILITY (f);
1199 store_in_alist (alistptr, Qvisibility,
1200 (FRAME_VISIBLE_P (f) ? Qt
1201 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1202 store_in_alist (alistptr, Qdisplay,
1203 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1205 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1206 tem = Qnil;
1207 else
1208 XSETFASTINT (tem, f->output_data.x->parent_desc);
1209 store_in_alist (alistptr, Qparent_id, tem);
1214 /* Gamma-correct COLOR on frame F. */
1216 void
1217 gamma_correct (f, color)
1218 struct frame *f;
1219 XColor *color;
1221 if (f->gamma)
1223 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1224 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1225 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1230 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1231 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1232 allocate the color. Value is zero if COLOR_NAME is invalid, or
1233 no color could be allocated. */
1236 x_defined_color (f, color_name, color, alloc_p)
1237 struct frame *f;
1238 char *color_name;
1239 XColor *color;
1240 int alloc_p;
1242 int success_p;
1243 Display *dpy = FRAME_X_DISPLAY (f);
1244 Colormap cmap = FRAME_X_COLORMAP (f);
1246 BLOCK_INPUT;
1247 success_p = XParseColor (dpy, cmap, color_name, color);
1248 if (success_p && alloc_p)
1249 success_p = x_alloc_nearest_color (f, cmap, color);
1250 UNBLOCK_INPUT;
1252 return success_p;
1256 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1257 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1258 Signal an error if color can't be allocated. */
1261 x_decode_color (f, color_name, mono_color)
1262 FRAME_PTR f;
1263 Lisp_Object color_name;
1264 int mono_color;
1266 XColor cdef;
1268 CHECK_STRING (color_name, 0);
1270 #if 0 /* Don't do this. It's wrong when we're not using the default
1271 colormap, it makes freeing difficult, and it's probably not
1272 an important optimization. */
1273 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1274 return BLACK_PIX_DEFAULT (f);
1275 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1276 return WHITE_PIX_DEFAULT (f);
1277 #endif
1279 /* Return MONO_COLOR for monochrome frames. */
1280 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1281 return mono_color;
1283 /* x_defined_color is responsible for coping with failures
1284 by looking for a near-miss. */
1285 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1286 return cdef.pixel;
1288 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1289 Fcons (color_name, Qnil)));
1290 return 0;
1295 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1296 the previous value of that parameter, NEW_VALUE is the new value. */
1298 static void
1299 x_set_line_spacing (f, new_value, old_value)
1300 struct frame *f;
1301 Lisp_Object new_value, old_value;
1303 if (NILP (new_value))
1304 f->extra_line_spacing = 0;
1305 else if (NATNUMP (new_value))
1306 f->extra_line_spacing = XFASTINT (new_value);
1307 else
1308 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1309 Fcons (new_value, Qnil)));
1310 if (FRAME_VISIBLE_P (f))
1311 redraw_frame (f);
1315 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1316 the previous value of that parameter, NEW_VALUE is the new value. */
1318 static void
1319 x_set_screen_gamma (f, new_value, old_value)
1320 struct frame *f;
1321 Lisp_Object new_value, old_value;
1323 if (NILP (new_value))
1324 f->gamma = 0;
1325 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1326 /* The value 0.4545 is the normal viewing gamma. */
1327 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1328 else
1329 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1330 Fcons (new_value, Qnil)));
1332 clear_face_cache (0);
1336 /* Functions called only from `x_set_frame_param'
1337 to set individual parameters.
1339 If FRAME_X_WINDOW (f) is 0,
1340 the frame is being created and its X-window does not exist yet.
1341 In that case, just record the parameter's new value
1342 in the standard place; do not attempt to change the window. */
1344 void
1345 x_set_foreground_color (f, arg, oldval)
1346 struct frame *f;
1347 Lisp_Object arg, oldval;
1349 struct x_output *x = f->output_data.x;
1350 unsigned long fg, old_fg;
1352 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1353 old_fg = x->foreground_pixel;
1354 x->foreground_pixel = fg;
1356 if (FRAME_X_WINDOW (f) != 0)
1358 Display *dpy = FRAME_X_DISPLAY (f);
1360 BLOCK_INPUT;
1361 XSetForeground (dpy, x->normal_gc, fg);
1362 XSetBackground (dpy, x->reverse_gc, fg);
1364 if (x->cursor_pixel == old_fg)
1366 unload_color (f, x->cursor_pixel);
1367 x->cursor_pixel = x_copy_color (f, fg);
1368 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1371 UNBLOCK_INPUT;
1373 update_face_from_frame_parameter (f, Qforeground_color, arg);
1375 if (FRAME_VISIBLE_P (f))
1376 redraw_frame (f);
1379 unload_color (f, old_fg);
1382 void
1383 x_set_background_color (f, arg, oldval)
1384 struct frame *f;
1385 Lisp_Object arg, oldval;
1387 struct x_output *x = f->output_data.x;
1388 unsigned long bg;
1390 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1391 unload_color (f, x->background_pixel);
1392 x->background_pixel = bg;
1394 if (FRAME_X_WINDOW (f) != 0)
1396 Display *dpy = FRAME_X_DISPLAY (f);
1397 Lisp_Object bar;
1399 BLOCK_INPUT;
1400 XSetBackground (dpy, x->normal_gc, bg);
1401 XSetForeground (dpy, x->reverse_gc, bg);
1402 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1403 XSetForeground (dpy, x->cursor_gc, bg);
1405 for (bar = FRAME_SCROLL_BARS (f);
1406 !NILP (bar);
1407 bar = XSCROLL_BAR (bar)->next)
1409 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1410 XSetWindowBackground (dpy, window, bg);
1413 UNBLOCK_INPUT;
1414 update_face_from_frame_parameter (f, Qbackground_color, arg);
1416 if (FRAME_VISIBLE_P (f))
1417 redraw_frame (f);
1421 void
1422 x_set_mouse_color (f, arg, oldval)
1423 struct frame *f;
1424 Lisp_Object arg, oldval;
1426 struct x_output *x = f->output_data.x;
1427 Display *dpy = FRAME_X_DISPLAY (f);
1428 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1429 Cursor hourglass_cursor, horizontal_drag_cursor;
1430 int count;
1431 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1432 unsigned long mask_color = x->background_pixel;
1434 /* Don't let pointers be invisible. */
1435 if (mask_color == pixel)
1437 x_free_colors (f, &pixel, 1);
1438 pixel = x_copy_color (f, x->foreground_pixel);
1441 unload_color (f, x->mouse_pixel);
1442 x->mouse_pixel = pixel;
1444 BLOCK_INPUT;
1446 /* It's not okay to crash if the user selects a screwy cursor. */
1447 count = x_catch_errors (dpy);
1449 if (!NILP (Vx_pointer_shape))
1451 CHECK_NUMBER (Vx_pointer_shape, 0);
1452 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1454 else
1455 cursor = XCreateFontCursor (dpy, XC_xterm);
1456 x_check_errors (dpy, "bad text pointer cursor: %s");
1458 if (!NILP (Vx_nontext_pointer_shape))
1460 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1461 nontext_cursor
1462 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1464 else
1465 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1466 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1468 if (!NILP (Vx_hourglass_pointer_shape))
1470 CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
1471 hourglass_cursor
1472 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1474 else
1475 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1476 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1478 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1479 if (!NILP (Vx_mode_pointer_shape))
1481 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1482 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1484 else
1485 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1486 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1488 if (!NILP (Vx_sensitive_text_pointer_shape))
1490 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1491 cross_cursor
1492 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1494 else
1495 cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
1497 if (!NILP (Vx_window_horizontal_drag_shape))
1499 CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
1500 horizontal_drag_cursor
1501 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1503 else
1504 horizontal_drag_cursor
1505 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1507 /* Check and report errors with the above calls. */
1508 x_check_errors (dpy, "can't set cursor shape: %s");
1509 x_uncatch_errors (dpy, count);
1512 XColor fore_color, back_color;
1514 fore_color.pixel = x->mouse_pixel;
1515 x_query_color (f, &fore_color);
1516 back_color.pixel = mask_color;
1517 x_query_color (f, &back_color);
1519 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1520 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1521 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1522 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1523 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1524 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1527 if (FRAME_X_WINDOW (f) != 0)
1528 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1530 if (cursor != x->text_cursor
1531 && x->text_cursor != 0)
1532 XFreeCursor (dpy, x->text_cursor);
1533 x->text_cursor = cursor;
1535 if (nontext_cursor != x->nontext_cursor
1536 && x->nontext_cursor != 0)
1537 XFreeCursor (dpy, x->nontext_cursor);
1538 x->nontext_cursor = nontext_cursor;
1540 if (hourglass_cursor != x->hourglass_cursor
1541 && x->hourglass_cursor != 0)
1542 XFreeCursor (dpy, x->hourglass_cursor);
1543 x->hourglass_cursor = hourglass_cursor;
1545 if (mode_cursor != x->modeline_cursor
1546 && x->modeline_cursor != 0)
1547 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1548 x->modeline_cursor = mode_cursor;
1550 if (cross_cursor != x->cross_cursor
1551 && x->cross_cursor != 0)
1552 XFreeCursor (dpy, x->cross_cursor);
1553 x->cross_cursor = cross_cursor;
1555 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1556 && x->horizontal_drag_cursor != 0)
1557 XFreeCursor (dpy, x->horizontal_drag_cursor);
1558 x->horizontal_drag_cursor = horizontal_drag_cursor;
1560 XFlush (dpy);
1561 UNBLOCK_INPUT;
1563 update_face_from_frame_parameter (f, Qmouse_color, arg);
1566 void
1567 x_set_cursor_color (f, arg, oldval)
1568 struct frame *f;
1569 Lisp_Object arg, oldval;
1571 unsigned long fore_pixel, pixel;
1572 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1573 struct x_output *x = f->output_data.x;
1575 if (!NILP (Vx_cursor_fore_pixel))
1577 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1578 WHITE_PIX_DEFAULT (f));
1579 fore_pixel_allocated_p = 1;
1581 else
1582 fore_pixel = x->background_pixel;
1584 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1585 pixel_allocated_p = 1;
1587 /* Make sure that the cursor color differs from the background color. */
1588 if (pixel == x->background_pixel)
1590 if (pixel_allocated_p)
1592 x_free_colors (f, &pixel, 1);
1593 pixel_allocated_p = 0;
1596 pixel = x->mouse_pixel;
1597 if (pixel == fore_pixel)
1599 if (fore_pixel_allocated_p)
1601 x_free_colors (f, &fore_pixel, 1);
1602 fore_pixel_allocated_p = 0;
1604 fore_pixel = x->background_pixel;
1608 unload_color (f, x->cursor_foreground_pixel);
1609 if (!fore_pixel_allocated_p)
1610 fore_pixel = x_copy_color (f, fore_pixel);
1611 x->cursor_foreground_pixel = fore_pixel;
1613 unload_color (f, x->cursor_pixel);
1614 if (!pixel_allocated_p)
1615 pixel = x_copy_color (f, pixel);
1616 x->cursor_pixel = pixel;
1618 if (FRAME_X_WINDOW (f) != 0)
1620 BLOCK_INPUT;
1621 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1622 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1623 UNBLOCK_INPUT;
1625 if (FRAME_VISIBLE_P (f))
1627 x_update_cursor (f, 0);
1628 x_update_cursor (f, 1);
1632 update_face_from_frame_parameter (f, Qcursor_color, arg);
1635 /* Set the border-color of frame F to value described by ARG.
1636 ARG can be a string naming a color.
1637 The border-color is used for the border that is drawn by the X server.
1638 Note that this does not fully take effect if done before
1639 F has an x-window; it must be redone when the window is created.
1641 Note: this is done in two routines because of the way X10 works.
1643 Note: under X11, this is normally the province of the window manager,
1644 and so emacs' border colors may be overridden. */
1646 void
1647 x_set_border_color (f, arg, oldval)
1648 struct frame *f;
1649 Lisp_Object arg, oldval;
1651 int pix;
1653 CHECK_STRING (arg, 0);
1654 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1655 x_set_border_pixel (f, pix);
1656 update_face_from_frame_parameter (f, Qborder_color, arg);
1659 /* Set the border-color of frame F to pixel value PIX.
1660 Note that this does not fully take effect if done before
1661 F has an x-window. */
1663 void
1664 x_set_border_pixel (f, pix)
1665 struct frame *f;
1666 int pix;
1668 unload_color (f, f->output_data.x->border_pixel);
1669 f->output_data.x->border_pixel = pix;
1671 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1673 BLOCK_INPUT;
1674 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1675 (unsigned long)pix);
1676 UNBLOCK_INPUT;
1678 if (FRAME_VISIBLE_P (f))
1679 redraw_frame (f);
1684 /* Value is the internal representation of the specified cursor type
1685 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1686 of the bar cursor. */
1688 enum text_cursor_kinds
1689 x_specified_cursor_type (arg, width)
1690 Lisp_Object arg;
1691 int *width;
1693 enum text_cursor_kinds type;
1695 if (EQ (arg, Qbar))
1697 type = BAR_CURSOR;
1698 *width = 2;
1700 else if (CONSP (arg)
1701 && EQ (XCAR (arg), Qbar)
1702 && INTEGERP (XCDR (arg))
1703 && XINT (XCDR (arg)) >= 0)
1705 type = BAR_CURSOR;
1706 *width = XINT (XCDR (arg));
1708 else if (NILP (arg))
1709 type = NO_CURSOR;
1710 else
1711 /* Treat anything unknown as "box cursor".
1712 It was bad to signal an error; people have trouble fixing
1713 .Xdefaults with Emacs, when it has something bad in it. */
1714 type = FILLED_BOX_CURSOR;
1716 return type;
1719 void
1720 x_set_cursor_type (f, arg, oldval)
1721 FRAME_PTR f;
1722 Lisp_Object arg, oldval;
1724 int width;
1726 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1727 f->output_data.x->cursor_width = width;
1729 /* Make sure the cursor gets redrawn. This is overkill, but how
1730 often do people change cursor types? */
1731 update_mode_lines++;
1734 void
1735 x_set_icon_type (f, arg, oldval)
1736 struct frame *f;
1737 Lisp_Object arg, oldval;
1739 int result;
1741 if (STRINGP (arg))
1743 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1744 return;
1746 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1747 return;
1749 BLOCK_INPUT;
1750 if (NILP (arg))
1751 result = x_text_icon (f,
1752 (char *) XSTRING ((!NILP (f->icon_name)
1753 ? f->icon_name
1754 : f->name))->data);
1755 else
1756 result = x_bitmap_icon (f, arg);
1758 if (result)
1760 UNBLOCK_INPUT;
1761 error ("No icon window available");
1764 XFlush (FRAME_X_DISPLAY (f));
1765 UNBLOCK_INPUT;
1768 /* Return non-nil if frame F wants a bitmap icon. */
1770 Lisp_Object
1771 x_icon_type (f)
1772 FRAME_PTR f;
1774 Lisp_Object tem;
1776 tem = assq_no_quit (Qicon_type, f->param_alist);
1777 if (CONSP (tem))
1778 return XCDR (tem);
1779 else
1780 return Qnil;
1783 void
1784 x_set_icon_name (f, arg, oldval)
1785 struct frame *f;
1786 Lisp_Object arg, oldval;
1788 int result;
1790 if (STRINGP (arg))
1792 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1793 return;
1795 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1796 return;
1798 f->icon_name = arg;
1800 if (f->output_data.x->icon_bitmap != 0)
1801 return;
1803 BLOCK_INPUT;
1805 result = x_text_icon (f,
1806 (char *) XSTRING ((!NILP (f->icon_name)
1807 ? f->icon_name
1808 : !NILP (f->title)
1809 ? f->title
1810 : f->name))->data);
1812 if (result)
1814 UNBLOCK_INPUT;
1815 error ("No icon window available");
1818 XFlush (FRAME_X_DISPLAY (f));
1819 UNBLOCK_INPUT;
1822 void
1823 x_set_font (f, arg, oldval)
1824 struct frame *f;
1825 Lisp_Object arg, oldval;
1827 Lisp_Object result;
1828 Lisp_Object fontset_name;
1829 Lisp_Object frame;
1830 int old_fontset = f->output_data.x->fontset;
1832 CHECK_STRING (arg, 1);
1834 fontset_name = Fquery_fontset (arg, Qnil);
1836 BLOCK_INPUT;
1837 result = (STRINGP (fontset_name)
1838 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1839 : x_new_font (f, XSTRING (arg)->data));
1840 UNBLOCK_INPUT;
1842 if (EQ (result, Qnil))
1843 error ("Font `%s' is not defined", XSTRING (arg)->data);
1844 else if (EQ (result, Qt))
1845 error ("The characters of the given font have varying widths");
1846 else if (STRINGP (result))
1848 if (STRINGP (fontset_name))
1850 /* Fontset names are built from ASCII font names, so the
1851 names may be equal despite there was a change. */
1852 if (old_fontset == f->output_data.x->fontset)
1853 return;
1855 else if (!NILP (Fequal (result, oldval)))
1856 return;
1858 store_frame_param (f, Qfont, result);
1859 recompute_basic_faces (f);
1861 else
1862 abort ();
1864 do_pending_window_change (0);
1866 /* Don't call `face-set-after-frame-default' when faces haven't been
1867 initialized yet. This is the case when called from
1868 Fx_create_frame. In that case, the X widget or window doesn't
1869 exist either, and we can end up in x_report_frame_params with a
1870 null widget which gives a segfault. */
1871 if (FRAME_FACE_CACHE (f))
1873 XSETFRAME (frame, f);
1874 call1 (Qface_set_after_frame_default, frame);
1878 void
1879 x_set_border_width (f, arg, oldval)
1880 struct frame *f;
1881 Lisp_Object arg, oldval;
1883 CHECK_NUMBER (arg, 0);
1885 if (XINT (arg) == f->output_data.x->border_width)
1886 return;
1888 if (FRAME_X_WINDOW (f) != 0)
1889 error ("Cannot change the border width of a window");
1891 f->output_data.x->border_width = XINT (arg);
1894 void
1895 x_set_internal_border_width (f, arg, oldval)
1896 struct frame *f;
1897 Lisp_Object arg, oldval;
1899 int old = f->output_data.x->internal_border_width;
1901 CHECK_NUMBER (arg, 0);
1902 f->output_data.x->internal_border_width = XINT (arg);
1903 if (f->output_data.x->internal_border_width < 0)
1904 f->output_data.x->internal_border_width = 0;
1906 #ifdef USE_X_TOOLKIT
1907 if (f->output_data.x->edit_widget)
1908 widget_store_internal_border (f->output_data.x->edit_widget);
1909 #endif
1911 if (f->output_data.x->internal_border_width == old)
1912 return;
1914 if (FRAME_X_WINDOW (f) != 0)
1916 x_set_window_size (f, 0, f->width, f->height);
1917 SET_FRAME_GARBAGED (f);
1918 do_pending_window_change (0);
1922 void
1923 x_set_visibility (f, value, oldval)
1924 struct frame *f;
1925 Lisp_Object value, oldval;
1927 Lisp_Object frame;
1928 XSETFRAME (frame, f);
1930 if (NILP (value))
1931 Fmake_frame_invisible (frame, Qt);
1932 else if (EQ (value, Qicon))
1933 Ficonify_frame (frame);
1934 else
1935 Fmake_frame_visible (frame);
1939 /* Change window heights in windows rooted in WINDOW by N lines. */
1941 static void
1942 x_change_window_heights (window, n)
1943 Lisp_Object window;
1944 int n;
1946 struct window *w = XWINDOW (window);
1948 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1949 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1951 if (INTEGERP (w->orig_top))
1952 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1953 if (INTEGERP (w->orig_height))
1954 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1956 /* Handle just the top child in a vertical split. */
1957 if (!NILP (w->vchild))
1958 x_change_window_heights (w->vchild, n);
1960 /* Adjust all children in a horizontal split. */
1961 for (window = w->hchild; !NILP (window); window = w->next)
1963 w = XWINDOW (window);
1964 x_change_window_heights (window, n);
1968 void
1969 x_set_menu_bar_lines (f, value, oldval)
1970 struct frame *f;
1971 Lisp_Object value, oldval;
1973 int nlines;
1974 #ifndef USE_X_TOOLKIT
1975 int olines = FRAME_MENU_BAR_LINES (f);
1976 #endif
1978 /* Right now, menu bars don't work properly in minibuf-only frames;
1979 most of the commands try to apply themselves to the minibuffer
1980 frame itself, and get an error because you can't switch buffers
1981 in or split the minibuffer window. */
1982 if (FRAME_MINIBUF_ONLY_P (f))
1983 return;
1985 if (INTEGERP (value))
1986 nlines = XINT (value);
1987 else
1988 nlines = 0;
1990 /* Make sure we redisplay all windows in this frame. */
1991 windows_or_buffers_changed++;
1993 #ifdef USE_X_TOOLKIT
1994 FRAME_MENU_BAR_LINES (f) = 0;
1995 if (nlines)
1997 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1998 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1999 /* Make sure next redisplay shows the menu bar. */
2000 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2002 else
2004 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2005 free_frame_menubar (f);
2006 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2007 if (FRAME_X_P (f))
2008 f->output_data.x->menubar_widget = 0;
2010 #else /* not USE_X_TOOLKIT */
2011 FRAME_MENU_BAR_LINES (f) = nlines;
2012 x_change_window_heights (f->root_window, nlines - olines);
2013 #endif /* not USE_X_TOOLKIT */
2014 adjust_glyphs (f);
2018 /* Set the number of lines used for the tool bar of frame F to VALUE.
2019 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2020 is the old number of tool bar lines. This function changes the
2021 height of all windows on frame F to match the new tool bar height.
2022 The frame's height doesn't change. */
2024 void
2025 x_set_tool_bar_lines (f, value, oldval)
2026 struct frame *f;
2027 Lisp_Object value, oldval;
2029 int delta, nlines, root_height;
2030 Lisp_Object root_window;
2032 /* Treat tool bars like menu bars. */
2033 if (FRAME_MINIBUF_ONLY_P (f))
2034 return;
2036 /* Use VALUE only if an integer >= 0. */
2037 if (INTEGERP (value) && XINT (value) >= 0)
2038 nlines = XFASTINT (value);
2039 else
2040 nlines = 0;
2042 /* Make sure we redisplay all windows in this frame. */
2043 ++windows_or_buffers_changed;
2045 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2047 /* Don't resize the tool-bar to more than we have room for. */
2048 root_window = FRAME_ROOT_WINDOW (f);
2049 root_height = XINT (XWINDOW (root_window)->height);
2050 if (root_height - delta < 1)
2052 delta = root_height - 1;
2053 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2056 FRAME_TOOL_BAR_LINES (f) = nlines;
2057 x_change_window_heights (root_window, delta);
2058 adjust_glyphs (f);
2060 /* We also have to make sure that the internal border at the top of
2061 the frame, below the menu bar or tool bar, is redrawn when the
2062 tool bar disappears. This is so because the internal border is
2063 below the tool bar if one is displayed, but is below the menu bar
2064 if there isn't a tool bar. The tool bar draws into the area
2065 below the menu bar. */
2066 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2068 updating_frame = f;
2069 clear_frame ();
2070 clear_current_matrices (f);
2071 updating_frame = NULL;
2074 /* If the tool bar gets smaller, the internal border below it
2075 has to be cleared. It was formerly part of the display
2076 of the larger tool bar, and updating windows won't clear it. */
2077 if (delta < 0)
2079 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2080 int width = PIXEL_WIDTH (f);
2081 int y = nlines * CANON_Y_UNIT (f);
2083 BLOCK_INPUT;
2084 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2085 0, y, width, height, False);
2086 UNBLOCK_INPUT;
2091 /* Set the foreground color for scroll bars on frame F to VALUE.
2092 VALUE should be a string, a color name. If it isn't a string or
2093 isn't a valid color name, do nothing. OLDVAL is the old value of
2094 the frame parameter. */
2096 void
2097 x_set_scroll_bar_foreground (f, value, oldval)
2098 struct frame *f;
2099 Lisp_Object value, oldval;
2101 unsigned long pixel;
2103 if (STRINGP (value))
2104 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2105 else
2106 pixel = -1;
2108 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2109 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2111 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2112 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2114 /* Remove all scroll bars because they have wrong colors. */
2115 if (condemn_scroll_bars_hook)
2116 (*condemn_scroll_bars_hook) (f);
2117 if (judge_scroll_bars_hook)
2118 (*judge_scroll_bars_hook) (f);
2120 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2121 redraw_frame (f);
2126 /* Set the background color for scroll bars on frame F to VALUE VALUE
2127 should be a string, a color name. If it isn't a string or isn't a
2128 valid color name, do nothing. OLDVAL is the old value of the frame
2129 parameter. */
2131 void
2132 x_set_scroll_bar_background (f, value, oldval)
2133 struct frame *f;
2134 Lisp_Object value, oldval;
2136 unsigned long pixel;
2138 if (STRINGP (value))
2139 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2140 else
2141 pixel = -1;
2143 if (f->output_data.x->scroll_bar_background_pixel != -1)
2144 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2146 f->output_data.x->scroll_bar_background_pixel = pixel;
2147 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2149 /* Remove all scroll bars because they have wrong colors. */
2150 if (condemn_scroll_bars_hook)
2151 (*condemn_scroll_bars_hook) (f);
2152 if (judge_scroll_bars_hook)
2153 (*judge_scroll_bars_hook) (f);
2155 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2156 redraw_frame (f);
2161 /* Encode Lisp string STRING as a text in a format appropriate for
2162 XICCC (X Inter Client Communication Conventions).
2164 If STRING contains only ASCII characters, do no conversion and
2165 return the string data of STRING. Otherwise, encode the text by
2166 CODING_SYSTEM, and return a newly allocated memory area which
2167 should be freed by `xfree' by a caller.
2169 Store the byte length of resulting text in *TEXT_BYTES.
2171 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2172 which means that the `encoding' of the result can be `STRING'.
2173 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2174 the result should be `COMPOUND_TEXT'. */
2176 unsigned char *
2177 x_encode_text (string, coding_system, text_bytes, stringp)
2178 Lisp_Object string, coding_system;
2179 int *text_bytes, *stringp;
2181 unsigned char *str = XSTRING (string)->data;
2182 int chars = XSTRING (string)->size;
2183 int bytes = STRING_BYTES (XSTRING (string));
2184 int charset_info;
2185 int bufsize;
2186 unsigned char *buf;
2187 struct coding_system coding;
2189 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2190 if (charset_info == 0)
2192 /* No multibyte character in OBJ. We need not encode it. */
2193 *text_bytes = bytes;
2194 *stringp = 1;
2195 return str;
2198 setup_coding_system (coding_system, &coding);
2199 coding.src_multibyte = 1;
2200 coding.dst_multibyte = 0;
2201 coding.mode |= CODING_MODE_LAST_BLOCK;
2202 if (coding.type == coding_type_iso2022)
2203 coding.flags |= CODING_FLAG_ISO_SAFE;
2204 /* We suppress producing escape sequences for composition. */
2205 coding.composing = COMPOSITION_DISABLED;
2206 bufsize = encoding_buffer_size (&coding, bytes);
2207 buf = (unsigned char *) xmalloc (bufsize);
2208 encode_coding (&coding, str, buf, bytes, bufsize);
2209 *text_bytes = coding.produced;
2210 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2211 return buf;
2215 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2216 x_id_name.
2218 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2219 name; if NAME is a string, set F's name to NAME and set
2220 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2222 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2223 suggesting a new name, which lisp code should override; if
2224 F->explicit_name is set, ignore the new name; otherwise, set it. */
2226 void
2227 x_set_name (f, name, explicit)
2228 struct frame *f;
2229 Lisp_Object name;
2230 int explicit;
2232 /* Make sure that requests from lisp code override requests from
2233 Emacs redisplay code. */
2234 if (explicit)
2236 /* If we're switching from explicit to implicit, we had better
2237 update the mode lines and thereby update the title. */
2238 if (f->explicit_name && NILP (name))
2239 update_mode_lines = 1;
2241 f->explicit_name = ! NILP (name);
2243 else if (f->explicit_name)
2244 return;
2246 /* If NAME is nil, set the name to the x_id_name. */
2247 if (NILP (name))
2249 /* Check for no change needed in this very common case
2250 before we do any consing. */
2251 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2252 XSTRING (f->name)->data))
2253 return;
2254 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2256 else
2257 CHECK_STRING (name, 0);
2259 /* Don't change the name if it's already NAME. */
2260 if (! NILP (Fstring_equal (name, f->name)))
2261 return;
2263 f->name = name;
2265 /* For setting the frame title, the title parameter should override
2266 the name parameter. */
2267 if (! NILP (f->title))
2268 name = f->title;
2270 if (FRAME_X_WINDOW (f))
2272 BLOCK_INPUT;
2273 #ifdef HAVE_X11R4
2275 XTextProperty text, icon;
2276 int bytes, stringp;
2277 Lisp_Object coding_system;
2279 coding_system = Vlocale_coding_system;
2280 if (NILP (coding_system))
2281 coding_system = Qcompound_text;
2282 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2283 text.encoding = (stringp ? XA_STRING
2284 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2285 text.format = 8;
2286 text.nitems = bytes;
2288 if (NILP (f->icon_name))
2290 icon = text;
2292 else
2294 icon.value = x_encode_text (f->icon_name, coding_system,
2295 &bytes, &stringp);
2296 icon.encoding = (stringp ? XA_STRING
2297 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2298 icon.format = 8;
2299 icon.nitems = bytes;
2301 #ifdef USE_X_TOOLKIT
2302 XSetWMName (FRAME_X_DISPLAY (f),
2303 XtWindow (f->output_data.x->widget), &text);
2304 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2305 &icon);
2306 #else /* not USE_X_TOOLKIT */
2307 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2308 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2309 #endif /* not USE_X_TOOLKIT */
2310 if (!NILP (f->icon_name)
2311 && icon.value != XSTRING (f->icon_name)->data)
2312 xfree (icon.value);
2313 if (text.value != XSTRING (name)->data)
2314 xfree (text.value);
2316 #else /* not HAVE_X11R4 */
2317 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2318 XSTRING (name)->data);
2319 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2320 XSTRING (name)->data);
2321 #endif /* not HAVE_X11R4 */
2322 UNBLOCK_INPUT;
2326 /* This function should be called when the user's lisp code has
2327 specified a name for the frame; the name will override any set by the
2328 redisplay code. */
2329 void
2330 x_explicitly_set_name (f, arg, oldval)
2331 FRAME_PTR f;
2332 Lisp_Object arg, oldval;
2334 x_set_name (f, arg, 1);
2337 /* This function should be called by Emacs redisplay code to set the
2338 name; names set this way will never override names set by the user's
2339 lisp code. */
2340 void
2341 x_implicitly_set_name (f, arg, oldval)
2342 FRAME_PTR f;
2343 Lisp_Object arg, oldval;
2345 x_set_name (f, arg, 0);
2348 /* Change the title of frame F to NAME.
2349 If NAME is nil, use the frame name as the title.
2351 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2352 name; if NAME is a string, set F's name to NAME and set
2353 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2355 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2356 suggesting a new name, which lisp code should override; if
2357 F->explicit_name is set, ignore the new name; otherwise, set it. */
2359 void
2360 x_set_title (f, name, old_name)
2361 struct frame *f;
2362 Lisp_Object name, old_name;
2364 /* Don't change the title if it's already NAME. */
2365 if (EQ (name, f->title))
2366 return;
2368 update_mode_lines = 1;
2370 f->title = name;
2372 if (NILP (name))
2373 name = f->name;
2374 else
2375 CHECK_STRING (name, 0);
2377 if (FRAME_X_WINDOW (f))
2379 BLOCK_INPUT;
2380 #ifdef HAVE_X11R4
2382 XTextProperty text, icon;
2383 int bytes, stringp;
2384 Lisp_Object coding_system;
2386 coding_system = Vlocale_coding_system;
2387 if (NILP (coding_system))
2388 coding_system = Qcompound_text;
2389 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2390 text.encoding = (stringp ? XA_STRING
2391 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2392 text.format = 8;
2393 text.nitems = bytes;
2395 if (NILP (f->icon_name))
2397 icon = text;
2399 else
2401 icon.value = x_encode_text (f->icon_name, coding_system,
2402 &bytes, &stringp);
2403 icon.encoding = (stringp ? XA_STRING
2404 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2405 icon.format = 8;
2406 icon.nitems = bytes;
2408 #ifdef USE_X_TOOLKIT
2409 XSetWMName (FRAME_X_DISPLAY (f),
2410 XtWindow (f->output_data.x->widget), &text);
2411 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2412 &icon);
2413 #else /* not USE_X_TOOLKIT */
2414 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2415 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2416 #endif /* not USE_X_TOOLKIT */
2417 if (!NILP (f->icon_name)
2418 && icon.value != XSTRING (f->icon_name)->data)
2419 xfree (icon.value);
2420 if (text.value != XSTRING (name)->data)
2421 xfree (text.value);
2423 #else /* not HAVE_X11R4 */
2424 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2425 XSTRING (name)->data);
2426 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2427 XSTRING (name)->data);
2428 #endif /* not HAVE_X11R4 */
2429 UNBLOCK_INPUT;
2433 void
2434 x_set_autoraise (f, arg, oldval)
2435 struct frame *f;
2436 Lisp_Object arg, oldval;
2438 f->auto_raise = !EQ (Qnil, arg);
2441 void
2442 x_set_autolower (f, arg, oldval)
2443 struct frame *f;
2444 Lisp_Object arg, oldval;
2446 f->auto_lower = !EQ (Qnil, arg);
2449 void
2450 x_set_unsplittable (f, arg, oldval)
2451 struct frame *f;
2452 Lisp_Object arg, oldval;
2454 f->no_split = !NILP (arg);
2457 void
2458 x_set_vertical_scroll_bars (f, arg, oldval)
2459 struct frame *f;
2460 Lisp_Object arg, oldval;
2462 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2463 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2464 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2465 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2467 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2468 = (NILP (arg)
2469 ? vertical_scroll_bar_none
2470 : EQ (Qright, arg)
2471 ? vertical_scroll_bar_right
2472 : vertical_scroll_bar_left);
2474 /* We set this parameter before creating the X window for the
2475 frame, so we can get the geometry right from the start.
2476 However, if the window hasn't been created yet, we shouldn't
2477 call x_set_window_size. */
2478 if (FRAME_X_WINDOW (f))
2479 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2480 do_pending_window_change (0);
2484 void
2485 x_set_scroll_bar_width (f, arg, oldval)
2486 struct frame *f;
2487 Lisp_Object arg, oldval;
2489 int wid = FONT_WIDTH (f->output_data.x->font);
2491 if (NILP (arg))
2493 #ifdef USE_TOOLKIT_SCROLL_BARS
2494 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2495 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2496 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2497 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2498 #else
2499 /* Make the actual width at least 14 pixels and a multiple of a
2500 character width. */
2501 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2503 /* Use all of that space (aside from required margins) for the
2504 scroll bar. */
2505 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2506 #endif
2508 if (FRAME_X_WINDOW (f))
2509 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2510 do_pending_window_change (0);
2512 else if (INTEGERP (arg) && XINT (arg) > 0
2513 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2515 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2516 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2518 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2519 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2520 if (FRAME_X_WINDOW (f))
2521 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2524 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2525 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2526 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2531 /* Subroutines of creating an X frame. */
2533 /* Make sure that Vx_resource_name is set to a reasonable value.
2534 Fix it up, or set it to `emacs' if it is too hopeless. */
2536 static void
2537 validate_x_resource_name ()
2539 int len = 0;
2540 /* Number of valid characters in the resource name. */
2541 int good_count = 0;
2542 /* Number of invalid characters in the resource name. */
2543 int bad_count = 0;
2544 Lisp_Object new;
2545 int i;
2547 if (!STRINGP (Vx_resource_class))
2548 Vx_resource_class = build_string (EMACS_CLASS);
2550 if (STRINGP (Vx_resource_name))
2552 unsigned char *p = XSTRING (Vx_resource_name)->data;
2553 int i;
2555 len = STRING_BYTES (XSTRING (Vx_resource_name));
2557 /* Only letters, digits, - and _ are valid in resource names.
2558 Count the valid characters and count the invalid ones. */
2559 for (i = 0; i < len; i++)
2561 int c = p[i];
2562 if (! ((c >= 'a' && c <= 'z')
2563 || (c >= 'A' && c <= 'Z')
2564 || (c >= '0' && c <= '9')
2565 || c == '-' || c == '_'))
2566 bad_count++;
2567 else
2568 good_count++;
2571 else
2572 /* Not a string => completely invalid. */
2573 bad_count = 5, good_count = 0;
2575 /* If name is valid already, return. */
2576 if (bad_count == 0)
2577 return;
2579 /* If name is entirely invalid, or nearly so, use `emacs'. */
2580 if (good_count == 0
2581 || (good_count == 1 && bad_count > 0))
2583 Vx_resource_name = build_string ("emacs");
2584 return;
2587 /* Name is partly valid. Copy it and replace the invalid characters
2588 with underscores. */
2590 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2592 for (i = 0; i < len; i++)
2594 int c = XSTRING (new)->data[i];
2595 if (! ((c >= 'a' && c <= 'z')
2596 || (c >= 'A' && c <= 'Z')
2597 || (c >= '0' && c <= '9')
2598 || c == '-' || c == '_'))
2599 XSTRING (new)->data[i] = '_';
2604 extern char *x_get_string_resource ();
2606 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2607 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2608 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2609 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2610 the name specified by the `-name' or `-rn' command-line arguments.\n\
2612 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2613 class, respectively. You must specify both of them or neither.\n\
2614 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2615 and the class is `Emacs.CLASS.SUBCLASS'.")
2616 (attribute, class, component, subclass)
2617 Lisp_Object attribute, class, component, subclass;
2619 register char *value;
2620 char *name_key;
2621 char *class_key;
2623 check_x ();
2625 CHECK_STRING (attribute, 0);
2626 CHECK_STRING (class, 0);
2628 if (!NILP (component))
2629 CHECK_STRING (component, 1);
2630 if (!NILP (subclass))
2631 CHECK_STRING (subclass, 2);
2632 if (NILP (component) != NILP (subclass))
2633 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2635 validate_x_resource_name ();
2637 /* Allocate space for the components, the dots which separate them,
2638 and the final '\0'. Make them big enough for the worst case. */
2639 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2640 + (STRINGP (component)
2641 ? STRING_BYTES (XSTRING (component)) : 0)
2642 + STRING_BYTES (XSTRING (attribute))
2643 + 3);
2645 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2646 + STRING_BYTES (XSTRING (class))
2647 + (STRINGP (subclass)
2648 ? STRING_BYTES (XSTRING (subclass)) : 0)
2649 + 3);
2651 /* Start with emacs.FRAMENAME for the name (the specific one)
2652 and with `Emacs' for the class key (the general one). */
2653 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2654 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2656 strcat (class_key, ".");
2657 strcat (class_key, XSTRING (class)->data);
2659 if (!NILP (component))
2661 strcat (class_key, ".");
2662 strcat (class_key, XSTRING (subclass)->data);
2664 strcat (name_key, ".");
2665 strcat (name_key, XSTRING (component)->data);
2668 strcat (name_key, ".");
2669 strcat (name_key, XSTRING (attribute)->data);
2671 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2672 name_key, class_key);
2674 if (value != (char *) 0)
2675 return build_string (value);
2676 else
2677 return Qnil;
2680 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2682 Lisp_Object
2683 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2684 struct x_display_info *dpyinfo;
2685 Lisp_Object attribute, class, component, subclass;
2687 register char *value;
2688 char *name_key;
2689 char *class_key;
2691 CHECK_STRING (attribute, 0);
2692 CHECK_STRING (class, 0);
2694 if (!NILP (component))
2695 CHECK_STRING (component, 1);
2696 if (!NILP (subclass))
2697 CHECK_STRING (subclass, 2);
2698 if (NILP (component) != NILP (subclass))
2699 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2701 validate_x_resource_name ();
2703 /* Allocate space for the components, the dots which separate them,
2704 and the final '\0'. Make them big enough for the worst case. */
2705 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2706 + (STRINGP (component)
2707 ? STRING_BYTES (XSTRING (component)) : 0)
2708 + STRING_BYTES (XSTRING (attribute))
2709 + 3);
2711 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2712 + STRING_BYTES (XSTRING (class))
2713 + (STRINGP (subclass)
2714 ? STRING_BYTES (XSTRING (subclass)) : 0)
2715 + 3);
2717 /* Start with emacs.FRAMENAME for the name (the specific one)
2718 and with `Emacs' for the class key (the general one). */
2719 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2720 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2722 strcat (class_key, ".");
2723 strcat (class_key, XSTRING (class)->data);
2725 if (!NILP (component))
2727 strcat (class_key, ".");
2728 strcat (class_key, XSTRING (subclass)->data);
2730 strcat (name_key, ".");
2731 strcat (name_key, XSTRING (component)->data);
2734 strcat (name_key, ".");
2735 strcat (name_key, XSTRING (attribute)->data);
2737 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2739 if (value != (char *) 0)
2740 return build_string (value);
2741 else
2742 return Qnil;
2745 /* Used when C code wants a resource value. */
2747 char *
2748 x_get_resource_string (attribute, class)
2749 char *attribute, *class;
2751 char *name_key;
2752 char *class_key;
2753 struct frame *sf = SELECTED_FRAME ();
2755 /* Allocate space for the components, the dots which separate them,
2756 and the final '\0'. */
2757 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2758 + strlen (attribute) + 2);
2759 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2760 + strlen (class) + 2);
2762 sprintf (name_key, "%s.%s",
2763 XSTRING (Vinvocation_name)->data,
2764 attribute);
2765 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2767 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2768 name_key, class_key);
2771 /* Types we might convert a resource string into. */
2772 enum resource_types
2774 RES_TYPE_NUMBER,
2775 RES_TYPE_FLOAT,
2776 RES_TYPE_BOOLEAN,
2777 RES_TYPE_STRING,
2778 RES_TYPE_SYMBOL
2781 /* Return the value of parameter PARAM.
2783 First search ALIST, then Vdefault_frame_alist, then the X defaults
2784 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2786 Convert the resource to the type specified by desired_type.
2788 If no default is specified, return Qunbound. If you call
2789 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2790 and don't let it get stored in any Lisp-visible variables! */
2792 static Lisp_Object
2793 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2794 struct x_display_info *dpyinfo;
2795 Lisp_Object alist, param;
2796 char *attribute;
2797 char *class;
2798 enum resource_types type;
2800 register Lisp_Object tem;
2802 tem = Fassq (param, alist);
2803 if (EQ (tem, Qnil))
2804 tem = Fassq (param, Vdefault_frame_alist);
2805 if (EQ (tem, Qnil))
2808 if (attribute)
2810 tem = display_x_get_resource (dpyinfo,
2811 build_string (attribute),
2812 build_string (class),
2813 Qnil, Qnil);
2815 if (NILP (tem))
2816 return Qunbound;
2818 switch (type)
2820 case RES_TYPE_NUMBER:
2821 return make_number (atoi (XSTRING (tem)->data));
2823 case RES_TYPE_FLOAT:
2824 return make_float (atof (XSTRING (tem)->data));
2826 case RES_TYPE_BOOLEAN:
2827 tem = Fdowncase (tem);
2828 if (!strcmp (XSTRING (tem)->data, "on")
2829 || !strcmp (XSTRING (tem)->data, "true"))
2830 return Qt;
2831 else
2832 return Qnil;
2834 case RES_TYPE_STRING:
2835 return tem;
2837 case RES_TYPE_SYMBOL:
2838 /* As a special case, we map the values `true' and `on'
2839 to Qt, and `false' and `off' to Qnil. */
2841 Lisp_Object lower;
2842 lower = Fdowncase (tem);
2843 if (!strcmp (XSTRING (lower)->data, "on")
2844 || !strcmp (XSTRING (lower)->data, "true"))
2845 return Qt;
2846 else if (!strcmp (XSTRING (lower)->data, "off")
2847 || !strcmp (XSTRING (lower)->data, "false"))
2848 return Qnil;
2849 else
2850 return Fintern (tem, Qnil);
2853 default:
2854 abort ();
2857 else
2858 return Qunbound;
2860 return Fcdr (tem);
2863 /* Like x_get_arg, but also record the value in f->param_alist. */
2865 static Lisp_Object
2866 x_get_and_record_arg (f, alist, param, attribute, class, type)
2867 struct frame *f;
2868 Lisp_Object alist, param;
2869 char *attribute;
2870 char *class;
2871 enum resource_types type;
2873 Lisp_Object value;
2875 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2876 attribute, class, type);
2877 if (! NILP (value))
2878 store_frame_param (f, param, value);
2880 return value;
2883 /* Record in frame F the specified or default value according to ALIST
2884 of the parameter named PROP (a Lisp symbol).
2885 If no value is specified for PROP, look for an X default for XPROP
2886 on the frame named NAME.
2887 If that is not found either, use the value DEFLT. */
2889 static Lisp_Object
2890 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2891 struct frame *f;
2892 Lisp_Object alist;
2893 Lisp_Object prop;
2894 Lisp_Object deflt;
2895 char *xprop;
2896 char *xclass;
2897 enum resource_types type;
2899 Lisp_Object tem;
2901 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2902 if (EQ (tem, Qunbound))
2903 tem = deflt;
2904 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2905 return tem;
2909 /* Record in frame F the specified or default value according to ALIST
2910 of the parameter named PROP (a Lisp symbol). If no value is
2911 specified for PROP, look for an X default for XPROP on the frame
2912 named NAME. If that is not found either, use the value DEFLT. */
2914 static Lisp_Object
2915 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2916 foreground_p)
2917 struct frame *f;
2918 Lisp_Object alist;
2919 Lisp_Object prop;
2920 char *xprop;
2921 char *xclass;
2922 int foreground_p;
2924 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2925 Lisp_Object tem;
2927 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2928 if (EQ (tem, Qunbound))
2930 #ifdef USE_TOOLKIT_SCROLL_BARS
2932 /* See if an X resource for the scroll bar color has been
2933 specified. */
2934 tem = display_x_get_resource (dpyinfo,
2935 build_string (foreground_p
2936 ? "foreground"
2937 : "background"),
2938 build_string (""),
2939 build_string ("verticalScrollBar"),
2940 build_string (""));
2941 if (!STRINGP (tem))
2943 /* If nothing has been specified, scroll bars will use a
2944 toolkit-dependent default. Because these defaults are
2945 difficult to get at without actually creating a scroll
2946 bar, use nil to indicate that no color has been
2947 specified. */
2948 tem = Qnil;
2951 #else /* not USE_TOOLKIT_SCROLL_BARS */
2953 tem = Qnil;
2955 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2958 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2959 return tem;
2964 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2965 "Parse an X-style geometry string STRING.\n\
2966 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2967 The properties returned may include `top', `left', `height', and `width'.\n\
2968 The value of `left' or `top' may be an integer,\n\
2969 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2970 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2971 (string)
2972 Lisp_Object string;
2974 int geometry, x, y;
2975 unsigned int width, height;
2976 Lisp_Object result;
2978 CHECK_STRING (string, 0);
2980 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2981 &x, &y, &width, &height);
2983 #if 0
2984 if (!!(geometry & XValue) != !!(geometry & YValue))
2985 error ("Must specify both x and y position, or neither");
2986 #endif
2988 result = Qnil;
2989 if (geometry & XValue)
2991 Lisp_Object element;
2993 if (x >= 0 && (geometry & XNegative))
2994 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2995 else if (x < 0 && ! (geometry & XNegative))
2996 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2997 else
2998 element = Fcons (Qleft, make_number (x));
2999 result = Fcons (element, result);
3002 if (geometry & YValue)
3004 Lisp_Object element;
3006 if (y >= 0 && (geometry & YNegative))
3007 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3008 else if (y < 0 && ! (geometry & YNegative))
3009 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3010 else
3011 element = Fcons (Qtop, make_number (y));
3012 result = Fcons (element, result);
3015 if (geometry & WidthValue)
3016 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3017 if (geometry & HeightValue)
3018 result = Fcons (Fcons (Qheight, make_number (height)), result);
3020 return result;
3023 /* Calculate the desired size and position of this window,
3024 and return the flags saying which aspects were specified.
3026 This function does not make the coordinates positive. */
3028 #define DEFAULT_ROWS 40
3029 #define DEFAULT_COLS 80
3031 static int
3032 x_figure_window_size (f, parms)
3033 struct frame *f;
3034 Lisp_Object parms;
3036 register Lisp_Object tem0, tem1, tem2;
3037 long window_prompting = 0;
3038 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3040 /* Default values if we fall through.
3041 Actually, if that happens we should get
3042 window manager prompting. */
3043 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3044 f->height = DEFAULT_ROWS;
3045 /* Window managers expect that if program-specified
3046 positions are not (0,0), they're intentional, not defaults. */
3047 f->output_data.x->top_pos = 0;
3048 f->output_data.x->left_pos = 0;
3050 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3051 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3052 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3053 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3055 if (!EQ (tem0, Qunbound))
3057 CHECK_NUMBER (tem0, 0);
3058 f->height = XINT (tem0);
3060 if (!EQ (tem1, Qunbound))
3062 CHECK_NUMBER (tem1, 0);
3063 SET_FRAME_WIDTH (f, XINT (tem1));
3065 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3066 window_prompting |= USSize;
3067 else
3068 window_prompting |= PSize;
3071 f->output_data.x->vertical_scroll_bar_extra
3072 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3074 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3075 f->output_data.x->flags_areas_extra
3076 = FRAME_FLAGS_AREA_WIDTH (f);
3077 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3078 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3080 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3081 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3082 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3083 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3085 if (EQ (tem0, Qminus))
3087 f->output_data.x->top_pos = 0;
3088 window_prompting |= YNegative;
3090 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3091 && CONSP (XCDR (tem0))
3092 && INTEGERP (XCAR (XCDR (tem0))))
3094 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3095 window_prompting |= YNegative;
3097 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3098 && CONSP (XCDR (tem0))
3099 && INTEGERP (XCAR (XCDR (tem0))))
3101 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3103 else if (EQ (tem0, Qunbound))
3104 f->output_data.x->top_pos = 0;
3105 else
3107 CHECK_NUMBER (tem0, 0);
3108 f->output_data.x->top_pos = XINT (tem0);
3109 if (f->output_data.x->top_pos < 0)
3110 window_prompting |= YNegative;
3113 if (EQ (tem1, Qminus))
3115 f->output_data.x->left_pos = 0;
3116 window_prompting |= XNegative;
3118 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3119 && CONSP (XCDR (tem1))
3120 && INTEGERP (XCAR (XCDR (tem1))))
3122 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3123 window_prompting |= XNegative;
3125 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3126 && CONSP (XCDR (tem1))
3127 && INTEGERP (XCAR (XCDR (tem1))))
3129 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3131 else if (EQ (tem1, Qunbound))
3132 f->output_data.x->left_pos = 0;
3133 else
3135 CHECK_NUMBER (tem1, 0);
3136 f->output_data.x->left_pos = XINT (tem1);
3137 if (f->output_data.x->left_pos < 0)
3138 window_prompting |= XNegative;
3141 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3142 window_prompting |= USPosition;
3143 else
3144 window_prompting |= PPosition;
3147 return window_prompting;
3150 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3152 Status
3153 XSetWMProtocols (dpy, w, protocols, count)
3154 Display *dpy;
3155 Window w;
3156 Atom *protocols;
3157 int count;
3159 Atom prop;
3160 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3161 if (prop == None) return False;
3162 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3163 (unsigned char *) protocols, count);
3164 return True;
3166 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3168 #ifdef USE_X_TOOLKIT
3170 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3171 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3172 already be present because of the toolkit (Motif adds some of them,
3173 for example, but Xt doesn't). */
3175 static void
3176 hack_wm_protocols (f, widget)
3177 FRAME_PTR f;
3178 Widget widget;
3180 Display *dpy = XtDisplay (widget);
3181 Window w = XtWindow (widget);
3182 int need_delete = 1;
3183 int need_focus = 1;
3184 int need_save = 1;
3186 BLOCK_INPUT;
3188 Atom type, *atoms = 0;
3189 int format = 0;
3190 unsigned long nitems = 0;
3191 unsigned long bytes_after;
3193 if ((XGetWindowProperty (dpy, w,
3194 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3195 (long)0, (long)100, False, XA_ATOM,
3196 &type, &format, &nitems, &bytes_after,
3197 (unsigned char **) &atoms)
3198 == Success)
3199 && format == 32 && type == XA_ATOM)
3200 while (nitems > 0)
3202 nitems--;
3203 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3204 need_delete = 0;
3205 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3206 need_focus = 0;
3207 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3208 need_save = 0;
3210 if (atoms) XFree ((char *) atoms);
3213 Atom props [10];
3214 int count = 0;
3215 if (need_delete)
3216 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3217 if (need_focus)
3218 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3219 if (need_save)
3220 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3221 if (count)
3222 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3223 XA_ATOM, 32, PropModeAppend,
3224 (unsigned char *) props, count);
3226 UNBLOCK_INPUT;
3228 #endif
3232 /* Support routines for XIC (X Input Context). */
3234 #ifdef HAVE_X_I18N
3236 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3237 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3240 /* Supported XIM styles, ordered by preferenc. */
3242 static XIMStyle supported_xim_styles[] =
3244 XIMPreeditPosition | XIMStatusArea,
3245 XIMPreeditPosition | XIMStatusNothing,
3246 XIMPreeditPosition | XIMStatusNone,
3247 XIMPreeditNothing | XIMStatusArea,
3248 XIMPreeditNothing | XIMStatusNothing,
3249 XIMPreeditNothing | XIMStatusNone,
3250 XIMPreeditNone | XIMStatusArea,
3251 XIMPreeditNone | XIMStatusNothing,
3252 XIMPreeditNone | XIMStatusNone,
3257 /* Create an X fontset on frame F with base font name
3258 BASE_FONTNAME.. */
3260 static XFontSet
3261 xic_create_xfontset (f, base_fontname)
3262 struct frame *f;
3263 char *base_fontname;
3265 XFontSet xfs;
3266 char **missing_list;
3267 int missing_count;
3268 char *def_string;
3270 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3271 base_fontname, &missing_list,
3272 &missing_count, &def_string);
3273 if (missing_list)
3274 XFreeStringList (missing_list);
3276 /* No need to free def_string. */
3277 return xfs;
3281 /* Value is the best input style, given user preferences USER (already
3282 checked to be supported by Emacs), and styles supported by the
3283 input method XIM. */
3285 static XIMStyle
3286 best_xim_style (user, xim)
3287 XIMStyles *user;
3288 XIMStyles *xim;
3290 int i, j;
3292 for (i = 0; i < user->count_styles; ++i)
3293 for (j = 0; j < xim->count_styles; ++j)
3294 if (user->supported_styles[i] == xim->supported_styles[j])
3295 return user->supported_styles[i];
3297 /* Return the default style. */
3298 return XIMPreeditNothing | XIMStatusNothing;
3301 /* Create XIC for frame F. */
3303 static XIMStyle xic_style;
3305 void
3306 create_frame_xic (f)
3307 struct frame *f;
3309 XIM xim;
3310 XIC xic = NULL;
3311 XFontSet xfs = NULL;
3313 if (FRAME_XIC (f))
3314 return;
3316 xim = FRAME_X_XIM (f);
3317 if (xim)
3319 XRectangle s_area;
3320 XPoint spot;
3321 XVaNestedList preedit_attr;
3322 XVaNestedList status_attr;
3323 char *base_fontname;
3324 int fontset;
3326 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3327 spot.x = 0; spot.y = 1;
3328 /* Create X fontset. */
3329 fontset = FRAME_FONTSET (f);
3330 if (fontset < 0)
3331 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3332 else
3334 /* Determine the base fontname from the ASCII font name of
3335 FONTSET. */
3336 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3337 char *p = ascii_font;
3338 int i;
3340 for (i = 0; *p; p++)
3341 if (*p == '-') i++;
3342 if (i != 14)
3343 /* As the font name doesn't conform to XLFD, we can't
3344 modify it to get a suitable base fontname for the
3345 frame. */
3346 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3347 else
3349 int len = strlen (ascii_font) + 1;
3350 char *p1 = NULL;
3352 for (i = 0, p = ascii_font; i < 8; p++)
3354 if (*p == '-')
3356 i++;
3357 if (i == 3)
3358 p1 = p + 1;
3361 base_fontname = (char *) alloca (len);
3362 bzero (base_fontname, len);
3363 strcpy (base_fontname, "-*-*-");
3364 bcopy (p1, base_fontname + 5, p - p1);
3365 strcat (base_fontname, "*-*-*-*-*-*-*");
3368 xfs = xic_create_xfontset (f, base_fontname);
3370 /* Determine XIC style. */
3371 if (xic_style == 0)
3373 XIMStyles supported_list;
3374 supported_list.count_styles = (sizeof supported_xim_styles
3375 / sizeof supported_xim_styles[0]);
3376 supported_list.supported_styles = supported_xim_styles;
3377 xic_style = best_xim_style (&supported_list,
3378 FRAME_X_XIM_STYLES (f));
3381 preedit_attr = XVaCreateNestedList (0,
3382 XNFontSet, xfs,
3383 XNForeground,
3384 FRAME_FOREGROUND_PIXEL (f),
3385 XNBackground,
3386 FRAME_BACKGROUND_PIXEL (f),
3387 (xic_style & XIMPreeditPosition
3388 ? XNSpotLocation
3389 : NULL),
3390 &spot,
3391 NULL);
3392 status_attr = XVaCreateNestedList (0,
3393 XNArea,
3394 &s_area,
3395 XNFontSet,
3396 xfs,
3397 XNForeground,
3398 FRAME_FOREGROUND_PIXEL (f),
3399 XNBackground,
3400 FRAME_BACKGROUND_PIXEL (f),
3401 NULL);
3403 xic = XCreateIC (xim,
3404 XNInputStyle, xic_style,
3405 XNClientWindow, FRAME_X_WINDOW(f),
3406 XNFocusWindow, FRAME_X_WINDOW(f),
3407 XNStatusAttributes, status_attr,
3408 XNPreeditAttributes, preedit_attr,
3409 NULL);
3410 XFree (preedit_attr);
3411 XFree (status_attr);
3414 FRAME_XIC (f) = xic;
3415 FRAME_XIC_STYLE (f) = xic_style;
3416 FRAME_XIC_FONTSET (f) = xfs;
3420 /* Destroy XIC and free XIC fontset of frame F, if any. */
3422 void
3423 free_frame_xic (f)
3424 struct frame *f;
3426 if (FRAME_XIC (f) == NULL)
3427 return;
3429 XDestroyIC (FRAME_XIC (f));
3430 if (FRAME_XIC_FONTSET (f))
3431 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3433 FRAME_XIC (f) = NULL;
3434 FRAME_XIC_FONTSET (f) = NULL;
3438 /* Place preedit area for XIC of window W's frame to specified
3439 pixel position X/Y. X and Y are relative to window W. */
3441 void
3442 xic_set_preeditarea (w, x, y)
3443 struct window *w;
3444 int x, y;
3446 struct frame *f = XFRAME (w->frame);
3447 XVaNestedList attr;
3448 XPoint spot;
3450 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3451 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3452 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3453 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3454 XFree (attr);
3458 /* Place status area for XIC in bottom right corner of frame F.. */
3460 void
3461 xic_set_statusarea (f)
3462 struct frame *f;
3464 XIC xic = FRAME_XIC (f);
3465 XVaNestedList attr;
3466 XRectangle area;
3467 XRectangle *needed;
3469 /* Negotiate geometry of status area. If input method has existing
3470 status area, use its current size. */
3471 area.x = area.y = area.width = area.height = 0;
3472 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3473 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3474 XFree (attr);
3476 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3477 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3478 XFree (attr);
3480 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3482 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3483 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3484 XFree (attr);
3487 area.width = needed->width;
3488 area.height = needed->height;
3489 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3490 area.y = (PIXEL_HEIGHT (f) - area.height
3491 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3492 XFree (needed);
3494 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3495 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3496 XFree (attr);
3500 /* Set X fontset for XIC of frame F, using base font name
3501 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3503 void
3504 xic_set_xfontset (f, base_fontname)
3505 struct frame *f;
3506 char *base_fontname;
3508 XVaNestedList attr;
3509 XFontSet xfs;
3511 xfs = xic_create_xfontset (f, base_fontname);
3513 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3514 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3515 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3516 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3517 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3518 XFree (attr);
3520 if (FRAME_XIC_FONTSET (f))
3521 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3522 FRAME_XIC_FONTSET (f) = xfs;
3525 #endif /* HAVE_X_I18N */
3529 #ifdef USE_X_TOOLKIT
3531 /* Create and set up the X widget for frame F. */
3533 static void
3534 x_window (f, window_prompting, minibuffer_only)
3535 struct frame *f;
3536 long window_prompting;
3537 int minibuffer_only;
3539 XClassHint class_hints;
3540 XSetWindowAttributes attributes;
3541 unsigned long attribute_mask;
3542 Widget shell_widget;
3543 Widget pane_widget;
3544 Widget frame_widget;
3545 Arg al [25];
3546 int ac;
3548 BLOCK_INPUT;
3550 /* Use the resource name as the top-level widget name
3551 for looking up resources. Make a non-Lisp copy
3552 for the window manager, so GC relocation won't bother it.
3554 Elsewhere we specify the window name for the window manager. */
3557 char *str = (char *) XSTRING (Vx_resource_name)->data;
3558 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3559 strcpy (f->namebuf, str);
3562 ac = 0;
3563 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3564 XtSetArg (al[ac], XtNinput, 1); ac++;
3565 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3566 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3567 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3568 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3569 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3570 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3571 applicationShellWidgetClass,
3572 FRAME_X_DISPLAY (f), al, ac);
3574 f->output_data.x->widget = shell_widget;
3575 /* maybe_set_screen_title_format (shell_widget); */
3577 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3578 (widget_value *) NULL,
3579 shell_widget, False,
3580 (lw_callback) NULL,
3581 (lw_callback) NULL,
3582 (lw_callback) NULL,
3583 (lw_callback) NULL);
3585 ac = 0;
3586 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3587 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3588 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3589 XtSetValues (pane_widget, al, ac);
3590 f->output_data.x->column_widget = pane_widget;
3592 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3593 the emacs screen when changing menubar. This reduces flickering. */
3595 ac = 0;
3596 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3597 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3598 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3599 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3600 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3601 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3602 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3603 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3604 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3605 al, ac);
3607 f->output_data.x->edit_widget = frame_widget;
3609 XtManageChild (frame_widget);
3611 /* Do some needed geometry management. */
3613 int len;
3614 char *tem, shell_position[32];
3615 Arg al[2];
3616 int ac = 0;
3617 int extra_borders = 0;
3618 int menubar_size
3619 = (f->output_data.x->menubar_widget
3620 ? (f->output_data.x->menubar_widget->core.height
3621 + f->output_data.x->menubar_widget->core.border_width)
3622 : 0);
3624 #if 0 /* Experimentally, we now get the right results
3625 for -geometry -0-0 without this. 24 Aug 96, rms. */
3626 if (FRAME_EXTERNAL_MENU_BAR (f))
3628 Dimension ibw = 0;
3629 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3630 menubar_size += ibw;
3632 #endif
3634 f->output_data.x->menubar_height = menubar_size;
3636 #ifndef USE_LUCID
3637 /* Motif seems to need this amount added to the sizes
3638 specified for the shell widget. The Athena/Lucid widgets don't.
3639 Both conclusions reached experimentally. -- rms. */
3640 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3641 &extra_borders, NULL);
3642 extra_borders *= 2;
3643 #endif
3645 /* Convert our geometry parameters into a geometry string
3646 and specify it.
3647 Note that we do not specify here whether the position
3648 is a user-specified or program-specified one.
3649 We pass that information later, in x_wm_set_size_hints. */
3651 int left = f->output_data.x->left_pos;
3652 int xneg = window_prompting & XNegative;
3653 int top = f->output_data.x->top_pos;
3654 int yneg = window_prompting & YNegative;
3655 if (xneg)
3656 left = -left;
3657 if (yneg)
3658 top = -top;
3660 if (window_prompting & USPosition)
3661 sprintf (shell_position, "=%dx%d%c%d%c%d",
3662 PIXEL_WIDTH (f) + extra_borders,
3663 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3664 (xneg ? '-' : '+'), left,
3665 (yneg ? '-' : '+'), top);
3666 else
3667 sprintf (shell_position, "=%dx%d",
3668 PIXEL_WIDTH (f) + extra_borders,
3669 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3672 len = strlen (shell_position) + 1;
3673 /* We don't free this because we don't know whether
3674 it is safe to free it while the frame exists.
3675 It isn't worth the trouble of arranging to free it
3676 when the frame is deleted. */
3677 tem = (char *) xmalloc (len);
3678 strncpy (tem, shell_position, len);
3679 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3680 XtSetValues (shell_widget, al, ac);
3683 XtManageChild (pane_widget);
3684 XtRealizeWidget (shell_widget);
3686 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3688 validate_x_resource_name ();
3690 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3691 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3692 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3694 #ifdef HAVE_X_I18N
3695 FRAME_XIC (f) = NULL;
3696 #ifdef USE_XIM
3697 create_frame_xic (f);
3698 #endif
3699 #endif
3701 f->output_data.x->wm_hints.input = True;
3702 f->output_data.x->wm_hints.flags |= InputHint;
3703 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3704 &f->output_data.x->wm_hints);
3706 hack_wm_protocols (f, shell_widget);
3708 #ifdef HACK_EDITRES
3709 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3710 #endif
3712 /* Do a stupid property change to force the server to generate a
3713 PropertyNotify event so that the event_stream server timestamp will
3714 be initialized to something relevant to the time we created the window.
3716 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3717 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3718 XA_ATOM, 32, PropModeAppend,
3719 (unsigned char*) NULL, 0);
3721 /* Make all the standard events reach the Emacs frame. */
3722 attributes.event_mask = STANDARD_EVENT_SET;
3724 #ifdef HAVE_X_I18N
3725 if (FRAME_XIC (f))
3727 /* XIM server might require some X events. */
3728 unsigned long fevent = NoEventMask;
3729 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3730 attributes.event_mask |= fevent;
3732 #endif /* HAVE_X_I18N */
3734 attribute_mask = CWEventMask;
3735 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3736 attribute_mask, &attributes);
3738 XtMapWidget (frame_widget);
3740 /* x_set_name normally ignores requests to set the name if the
3741 requested name is the same as the current name. This is the one
3742 place where that assumption isn't correct; f->name is set, but
3743 the X server hasn't been told. */
3745 Lisp_Object name;
3746 int explicit = f->explicit_name;
3748 f->explicit_name = 0;
3749 name = f->name;
3750 f->name = Qnil;
3751 x_set_name (f, name, explicit);
3754 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3755 f->output_data.x->text_cursor);
3757 UNBLOCK_INPUT;
3759 /* This is a no-op, except under Motif. Make sure main areas are
3760 set to something reasonable, in case we get an error later. */
3761 lw_set_main_areas (pane_widget, 0, frame_widget);
3764 #else /* not USE_X_TOOLKIT */
3766 /* Create and set up the X window for frame F. */
3768 void
3769 x_window (f)
3770 struct frame *f;
3773 XClassHint class_hints;
3774 XSetWindowAttributes attributes;
3775 unsigned long attribute_mask;
3777 attributes.background_pixel = f->output_data.x->background_pixel;
3778 attributes.border_pixel = f->output_data.x->border_pixel;
3779 attributes.bit_gravity = StaticGravity;
3780 attributes.backing_store = NotUseful;
3781 attributes.save_under = True;
3782 attributes.event_mask = STANDARD_EVENT_SET;
3783 attributes.colormap = FRAME_X_COLORMAP (f);
3784 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3785 | CWColormap);
3787 BLOCK_INPUT;
3788 FRAME_X_WINDOW (f)
3789 = XCreateWindow (FRAME_X_DISPLAY (f),
3790 f->output_data.x->parent_desc,
3791 f->output_data.x->left_pos,
3792 f->output_data.x->top_pos,
3793 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3794 f->output_data.x->border_width,
3795 CopyFromParent, /* depth */
3796 InputOutput, /* class */
3797 FRAME_X_VISUAL (f),
3798 attribute_mask, &attributes);
3800 #ifdef HAVE_X_I18N
3801 #ifdef USE_XIM
3802 create_frame_xic (f);
3803 if (FRAME_XIC (f))
3805 /* XIM server might require some X events. */
3806 unsigned long fevent = NoEventMask;
3807 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3808 attributes.event_mask |= fevent;
3809 attribute_mask = CWEventMask;
3810 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3811 attribute_mask, &attributes);
3813 #endif
3814 #endif /* HAVE_X_I18N */
3816 validate_x_resource_name ();
3818 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3819 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3820 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3822 /* The menubar is part of the ordinary display;
3823 it does not count in addition to the height of the window. */
3824 f->output_data.x->menubar_height = 0;
3826 /* This indicates that we use the "Passive Input" input model.
3827 Unless we do this, we don't get the Focus{In,Out} events that we
3828 need to draw the cursor correctly. Accursed bureaucrats.
3829 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3831 f->output_data.x->wm_hints.input = True;
3832 f->output_data.x->wm_hints.flags |= InputHint;
3833 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3834 &f->output_data.x->wm_hints);
3835 f->output_data.x->wm_hints.icon_pixmap = None;
3837 /* Request "save yourself" and "delete window" commands from wm. */
3839 Atom protocols[2];
3840 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3841 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3842 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3845 /* x_set_name normally ignores requests to set the name if the
3846 requested name is the same as the current name. This is the one
3847 place where that assumption isn't correct; f->name is set, but
3848 the X server hasn't been told. */
3850 Lisp_Object name;
3851 int explicit = f->explicit_name;
3853 f->explicit_name = 0;
3854 name = f->name;
3855 f->name = Qnil;
3856 x_set_name (f, name, explicit);
3859 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3860 f->output_data.x->text_cursor);
3862 UNBLOCK_INPUT;
3864 if (FRAME_X_WINDOW (f) == 0)
3865 error ("Unable to create window");
3868 #endif /* not USE_X_TOOLKIT */
3870 /* Handle the icon stuff for this window. Perhaps later we might
3871 want an x_set_icon_position which can be called interactively as
3872 well. */
3874 static void
3875 x_icon (f, parms)
3876 struct frame *f;
3877 Lisp_Object parms;
3879 Lisp_Object icon_x, icon_y;
3880 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3882 /* Set the position of the icon. Note that twm groups all
3883 icons in an icon window. */
3884 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3885 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3886 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3888 CHECK_NUMBER (icon_x, 0);
3889 CHECK_NUMBER (icon_y, 0);
3891 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3892 error ("Both left and top icon corners of icon must be specified");
3894 BLOCK_INPUT;
3896 if (! EQ (icon_x, Qunbound))
3897 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3899 /* Start up iconic or window? */
3900 x_wm_set_window_state
3901 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3902 Qicon)
3903 ? IconicState
3904 : NormalState));
3906 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3907 ? f->icon_name
3908 : f->name))->data);
3910 UNBLOCK_INPUT;
3913 /* Make the GCs needed for this window, setting the
3914 background, border and mouse colors; also create the
3915 mouse cursor and the gray border tile. */
3917 static char cursor_bits[] =
3919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3922 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3925 static void
3926 x_make_gc (f)
3927 struct frame *f;
3929 XGCValues gc_values;
3931 BLOCK_INPUT;
3933 /* Create the GCs of this frame.
3934 Note that many default values are used. */
3936 /* Normal video */
3937 gc_values.font = f->output_data.x->font->fid;
3938 gc_values.foreground = f->output_data.x->foreground_pixel;
3939 gc_values.background = f->output_data.x->background_pixel;
3940 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3941 f->output_data.x->normal_gc
3942 = XCreateGC (FRAME_X_DISPLAY (f),
3943 FRAME_X_WINDOW (f),
3944 GCLineWidth | GCFont | GCForeground | GCBackground,
3945 &gc_values);
3947 /* Reverse video style. */
3948 gc_values.foreground = f->output_data.x->background_pixel;
3949 gc_values.background = f->output_data.x->foreground_pixel;
3950 f->output_data.x->reverse_gc
3951 = XCreateGC (FRAME_X_DISPLAY (f),
3952 FRAME_X_WINDOW (f),
3953 GCFont | GCForeground | GCBackground | GCLineWidth,
3954 &gc_values);
3956 /* Cursor has cursor-color background, background-color foreground. */
3957 gc_values.foreground = f->output_data.x->background_pixel;
3958 gc_values.background = f->output_data.x->cursor_pixel;
3959 gc_values.fill_style = FillOpaqueStippled;
3960 gc_values.stipple
3961 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3962 FRAME_X_DISPLAY_INFO (f)->root_window,
3963 cursor_bits, 16, 16);
3964 f->output_data.x->cursor_gc
3965 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3966 (GCFont | GCForeground | GCBackground
3967 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3968 &gc_values);
3970 /* Reliefs. */
3971 f->output_data.x->white_relief.gc = 0;
3972 f->output_data.x->black_relief.gc = 0;
3974 /* Create the gray border tile used when the pointer is not in
3975 the frame. Since this depends on the frame's pixel values,
3976 this must be done on a per-frame basis. */
3977 f->output_data.x->border_tile
3978 = (XCreatePixmapFromBitmapData
3979 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3980 gray_bits, gray_width, gray_height,
3981 f->output_data.x->foreground_pixel,
3982 f->output_data.x->background_pixel,
3983 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3985 UNBLOCK_INPUT;
3989 /* Free what was was allocated in x_make_gc. */
3991 void
3992 x_free_gcs (f)
3993 struct frame *f;
3995 Display *dpy = FRAME_X_DISPLAY (f);
3997 BLOCK_INPUT;
3999 if (f->output_data.x->normal_gc)
4001 XFreeGC (dpy, f->output_data.x->normal_gc);
4002 f->output_data.x->normal_gc = 0;
4005 if (f->output_data.x->reverse_gc)
4007 XFreeGC (dpy, f->output_data.x->reverse_gc);
4008 f->output_data.x->reverse_gc = 0;
4011 if (f->output_data.x->cursor_gc)
4013 XFreeGC (dpy, f->output_data.x->cursor_gc);
4014 f->output_data.x->cursor_gc = 0;
4017 if (f->output_data.x->border_tile)
4019 XFreePixmap (dpy, f->output_data.x->border_tile);
4020 f->output_data.x->border_tile = 0;
4023 UNBLOCK_INPUT;
4027 /* Handler for signals raised during x_create_frame and
4028 x_create_top_frame. FRAME is the frame which is partially
4029 constructed. */
4031 static Lisp_Object
4032 unwind_create_frame (frame)
4033 Lisp_Object frame;
4035 struct frame *f = XFRAME (frame);
4037 /* If frame is ``official'', nothing to do. */
4038 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4040 #if GLYPH_DEBUG
4041 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4042 #endif
4044 x_free_frame_resources (f);
4046 /* Check that reference counts are indeed correct. */
4047 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4048 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4049 return Qt;
4052 return Qnil;
4056 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4057 1, 1, 0,
4058 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
4059 Returns an Emacs frame object.\n\
4060 ALIST is an alist of frame parameters.\n\
4061 If the parameters specify that the frame should not have a minibuffer,\n\
4062 and do not specify a specific minibuffer window to use,\n\
4063 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4064 be shared by the new frame.\n\
4066 This function is an internal primitive--use `make-frame' instead.")
4067 (parms)
4068 Lisp_Object parms;
4070 struct frame *f;
4071 Lisp_Object frame, tem;
4072 Lisp_Object name;
4073 int minibuffer_only = 0;
4074 long window_prompting = 0;
4075 int width, height;
4076 int count = BINDING_STACK_SIZE ();
4077 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4078 Lisp_Object display;
4079 struct x_display_info *dpyinfo = NULL;
4080 Lisp_Object parent;
4081 struct kboard *kb;
4083 check_x ();
4085 /* Use this general default value to start with
4086 until we know if this frame has a specified name. */
4087 Vx_resource_name = Vinvocation_name;
4089 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4090 if (EQ (display, Qunbound))
4091 display = Qnil;
4092 dpyinfo = check_x_display_info (display);
4093 #ifdef MULTI_KBOARD
4094 kb = dpyinfo->kboard;
4095 #else
4096 kb = &the_only_kboard;
4097 #endif
4099 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4100 if (!STRINGP (name)
4101 && ! EQ (name, Qunbound)
4102 && ! NILP (name))
4103 error ("Invalid frame name--not a string or nil");
4105 if (STRINGP (name))
4106 Vx_resource_name = name;
4108 /* See if parent window is specified. */
4109 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4110 if (EQ (parent, Qunbound))
4111 parent = Qnil;
4112 if (! NILP (parent))
4113 CHECK_NUMBER (parent, 0);
4115 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4116 /* No need to protect DISPLAY because that's not used after passing
4117 it to make_frame_without_minibuffer. */
4118 frame = Qnil;
4119 GCPRO4 (parms, parent, name, frame);
4120 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4121 RES_TYPE_SYMBOL);
4122 if (EQ (tem, Qnone) || NILP (tem))
4123 f = make_frame_without_minibuffer (Qnil, kb, display);
4124 else if (EQ (tem, Qonly))
4126 f = make_minibuffer_frame ();
4127 minibuffer_only = 1;
4129 else if (WINDOWP (tem))
4130 f = make_frame_without_minibuffer (tem, kb, display);
4131 else
4132 f = make_frame (1);
4134 XSETFRAME (frame, f);
4136 /* Note that X Windows does support scroll bars. */
4137 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4139 f->output_method = output_x_window;
4140 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4141 bzero (f->output_data.x, sizeof (struct x_output));
4142 f->output_data.x->icon_bitmap = -1;
4143 f->output_data.x->fontset = -1;
4144 f->output_data.x->scroll_bar_foreground_pixel = -1;
4145 f->output_data.x->scroll_bar_background_pixel = -1;
4146 record_unwind_protect (unwind_create_frame, frame);
4148 f->icon_name
4149 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4150 RES_TYPE_STRING);
4151 if (! STRINGP (f->icon_name))
4152 f->icon_name = Qnil;
4154 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4155 #if GLYPH_DEBUG
4156 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4157 dpyinfo_refcount = dpyinfo->reference_count;
4158 #endif /* GLYPH_DEBUG */
4159 #ifdef MULTI_KBOARD
4160 FRAME_KBOARD (f) = kb;
4161 #endif
4163 /* These colors will be set anyway later, but it's important
4164 to get the color reference counts right, so initialize them! */
4166 Lisp_Object black;
4167 struct gcpro gcpro1;
4169 black = build_string ("black");
4170 GCPRO1 (black);
4171 f->output_data.x->foreground_pixel
4172 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4173 f->output_data.x->background_pixel
4174 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4175 f->output_data.x->cursor_pixel
4176 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4177 f->output_data.x->cursor_foreground_pixel
4178 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4179 f->output_data.x->border_pixel
4180 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4181 f->output_data.x->mouse_pixel
4182 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4183 UNGCPRO;
4186 /* Specify the parent under which to make this X window. */
4188 if (!NILP (parent))
4190 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4191 f->output_data.x->explicit_parent = 1;
4193 else
4195 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4196 f->output_data.x->explicit_parent = 0;
4199 /* Set the name; the functions to which we pass f expect the name to
4200 be set. */
4201 if (EQ (name, Qunbound) || NILP (name))
4203 f->name = build_string (dpyinfo->x_id_name);
4204 f->explicit_name = 0;
4206 else
4208 f->name = name;
4209 f->explicit_name = 1;
4210 /* use the frame's title when getting resources for this frame. */
4211 specbind (Qx_resource_name, name);
4214 /* Extract the window parameters from the supplied values
4215 that are needed to determine window geometry. */
4217 Lisp_Object font;
4219 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4221 BLOCK_INPUT;
4222 /* First, try whatever font the caller has specified. */
4223 if (STRINGP (font))
4225 tem = Fquery_fontset (font, Qnil);
4226 if (STRINGP (tem))
4227 font = x_new_fontset (f, XSTRING (tem)->data);
4228 else
4229 font = x_new_font (f, XSTRING (font)->data);
4232 /* Try out a font which we hope has bold and italic variations. */
4233 if (!STRINGP (font))
4234 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4235 if (!STRINGP (font))
4236 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4237 if (! STRINGP (font))
4238 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4239 if (! STRINGP (font))
4240 /* This was formerly the first thing tried, but it finds too many fonts
4241 and takes too long. */
4242 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4243 /* If those didn't work, look for something which will at least work. */
4244 if (! STRINGP (font))
4245 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4246 UNBLOCK_INPUT;
4247 if (! STRINGP (font))
4248 font = build_string ("fixed");
4250 x_default_parameter (f, parms, Qfont, font,
4251 "font", "Font", RES_TYPE_STRING);
4254 #ifdef USE_LUCID
4255 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4256 whereby it fails to get any font. */
4257 xlwmenu_default_font = f->output_data.x->font;
4258 #endif
4260 x_default_parameter (f, parms, Qborder_width, make_number (2),
4261 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4263 /* This defaults to 2 in order to match xterm. We recognize either
4264 internalBorderWidth or internalBorder (which is what xterm calls
4265 it). */
4266 if (NILP (Fassq (Qinternal_border_width, parms)))
4268 Lisp_Object value;
4270 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4271 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4272 if (! EQ (value, Qunbound))
4273 parms = Fcons (Fcons (Qinternal_border_width, value),
4274 parms);
4276 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4277 "internalBorderWidth", "internalBorderWidth",
4278 RES_TYPE_NUMBER);
4279 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4280 "verticalScrollBars", "ScrollBars",
4281 RES_TYPE_SYMBOL);
4283 /* Also do the stuff which must be set before the window exists. */
4284 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4285 "foreground", "Foreground", RES_TYPE_STRING);
4286 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4287 "background", "Background", RES_TYPE_STRING);
4288 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4289 "pointerColor", "Foreground", RES_TYPE_STRING);
4290 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4291 "cursorColor", "Foreground", RES_TYPE_STRING);
4292 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4293 "borderColor", "BorderColor", RES_TYPE_STRING);
4294 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4295 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4296 x_default_parameter (f, parms, Qline_spacing, Qnil,
4297 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4299 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4300 "scrollBarForeground",
4301 "ScrollBarForeground", 1);
4302 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4303 "scrollBarBackground",
4304 "ScrollBarBackground", 0);
4306 /* Init faces before x_default_parameter is called for scroll-bar
4307 parameters because that function calls x_set_scroll_bar_width,
4308 which calls change_frame_size, which calls Fset_window_buffer,
4309 which runs hooks, which call Fvertical_motion. At the end, we
4310 end up in init_iterator with a null face cache, which should not
4311 happen. */
4312 init_frame_faces (f);
4314 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4315 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4316 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4317 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4318 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4319 "bufferPredicate", "BufferPredicate",
4320 RES_TYPE_SYMBOL);
4321 x_default_parameter (f, parms, Qtitle, Qnil,
4322 "title", "Title", RES_TYPE_STRING);
4324 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4326 /* Add the tool-bar height to the initial frame height so that the
4327 user gets a text display area of the size he specified with -g or
4328 via .Xdefaults. Later changes of the tool-bar height don't
4329 change the frame size. This is done so that users can create
4330 tall Emacs frames without having to guess how tall the tool-bar
4331 will get. */
4332 if (FRAME_TOOL_BAR_LINES (f))
4334 int margin, relief, bar_height;
4336 relief = (tool_bar_button_relief > 0
4337 ? tool_bar_button_relief
4338 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4340 if (INTEGERP (Vtool_bar_button_margin)
4341 && XINT (Vtool_bar_button_margin) > 0)
4342 margin = XFASTINT (Vtool_bar_button_margin);
4343 else if (CONSP (Vtool_bar_button_margin)
4344 && INTEGERP (XCDR (Vtool_bar_button_margin))
4345 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4346 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4347 else
4348 margin = 0;
4350 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4351 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4354 /* Compute the size of the X window. */
4355 window_prompting = x_figure_window_size (f, parms);
4357 if (window_prompting & XNegative)
4359 if (window_prompting & YNegative)
4360 f->output_data.x->win_gravity = SouthEastGravity;
4361 else
4362 f->output_data.x->win_gravity = NorthEastGravity;
4364 else
4366 if (window_prompting & YNegative)
4367 f->output_data.x->win_gravity = SouthWestGravity;
4368 else
4369 f->output_data.x->win_gravity = NorthWestGravity;
4372 f->output_data.x->size_hint_flags = window_prompting;
4374 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4375 f->no_split = minibuffer_only || EQ (tem, Qt);
4377 /* Create the X widget or window. */
4378 #ifdef USE_X_TOOLKIT
4379 x_window (f, window_prompting, minibuffer_only);
4380 #else
4381 x_window (f);
4382 #endif
4384 x_icon (f, parms);
4385 x_make_gc (f);
4387 /* Now consider the frame official. */
4388 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4389 Vframe_list = Fcons (frame, Vframe_list);
4391 /* We need to do this after creating the X window, so that the
4392 icon-creation functions can say whose icon they're describing. */
4393 x_default_parameter (f, parms, Qicon_type, Qnil,
4394 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4396 x_default_parameter (f, parms, Qauto_raise, Qnil,
4397 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4398 x_default_parameter (f, parms, Qauto_lower, Qnil,
4399 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4400 x_default_parameter (f, parms, Qcursor_type, Qbox,
4401 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4402 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4403 "scrollBarWidth", "ScrollBarWidth",
4404 RES_TYPE_NUMBER);
4406 /* Dimensions, especially f->height, must be done via change_frame_size.
4407 Change will not be effected unless different from the current
4408 f->height. */
4409 width = f->width;
4410 height = f->height;
4412 f->height = 0;
4413 SET_FRAME_WIDTH (f, 0);
4414 change_frame_size (f, height, width, 1, 0, 0);
4416 /* Set up faces after all frame parameters are known. This call
4417 also merges in face attributes specified for new frames. If we
4418 don't do this, the `menu' face for instance won't have the right
4419 colors, and the menu bar won't appear in the specified colors for
4420 new frames. */
4421 call1 (Qface_set_after_frame_default, frame);
4423 #ifdef USE_X_TOOLKIT
4424 /* Create the menu bar. */
4425 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4427 /* If this signals an error, we haven't set size hints for the
4428 frame and we didn't make it visible. */
4429 initialize_frame_menubar (f);
4431 /* This is a no-op, except under Motif where it arranges the
4432 main window for the widgets on it. */
4433 lw_set_main_areas (f->output_data.x->column_widget,
4434 f->output_data.x->menubar_widget,
4435 f->output_data.x->edit_widget);
4437 #endif /* USE_X_TOOLKIT */
4439 /* Tell the server what size and position, etc, we want, and how
4440 badly we want them. This should be done after we have the menu
4441 bar so that its size can be taken into account. */
4442 BLOCK_INPUT;
4443 x_wm_set_size_hint (f, window_prompting, 0);
4444 UNBLOCK_INPUT;
4446 /* Make the window appear on the frame and enable display, unless
4447 the caller says not to. However, with explicit parent, Emacs
4448 cannot control visibility, so don't try. */
4449 if (! f->output_data.x->explicit_parent)
4451 Lisp_Object visibility;
4453 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4454 RES_TYPE_SYMBOL);
4455 if (EQ (visibility, Qunbound))
4456 visibility = Qt;
4458 if (EQ (visibility, Qicon))
4459 x_iconify_frame (f);
4460 else if (! NILP (visibility))
4461 x_make_frame_visible (f);
4462 else
4463 /* Must have been Qnil. */
4467 UNGCPRO;
4469 /* Make sure windows on this frame appear in calls to next-window
4470 and similar functions. */
4471 Vwindow_list = Qnil;
4473 return unbind_to (count, frame);
4477 /* FRAME is used only to get a handle on the X display. We don't pass the
4478 display info directly because we're called from frame.c, which doesn't
4479 know about that structure. */
4481 Lisp_Object
4482 x_get_focus_frame (frame)
4483 struct frame *frame;
4485 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4486 Lisp_Object xfocus;
4487 if (! dpyinfo->x_focus_frame)
4488 return Qnil;
4490 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4491 return xfocus;
4495 /* In certain situations, when the window manager follows a
4496 click-to-focus policy, there seems to be no way around calling
4497 XSetInputFocus to give another frame the input focus .
4499 In an ideal world, XSetInputFocus should generally be avoided so
4500 that applications don't interfere with the window manager's focus
4501 policy. But I think it's okay to use when it's clearly done
4502 following a user-command. */
4504 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4505 "Set the input focus to FRAME.\n\
4506 FRAME nil means use the selected frame.")
4507 (frame)
4508 Lisp_Object frame;
4510 struct frame *f = check_x_frame (frame);
4511 Display *dpy = FRAME_X_DISPLAY (f);
4512 int count;
4514 BLOCK_INPUT;
4515 count = x_catch_errors (dpy);
4516 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4517 RevertToParent, CurrentTime);
4518 x_uncatch_errors (dpy, count);
4519 UNBLOCK_INPUT;
4521 return Qnil;
4525 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4526 "Internal function called by `color-defined-p', which see.")
4527 (color, frame)
4528 Lisp_Object color, frame;
4530 XColor foo;
4531 FRAME_PTR f = check_x_frame (frame);
4533 CHECK_STRING (color, 1);
4535 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4536 return Qt;
4537 else
4538 return Qnil;
4541 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4542 "Internal function called by `color-values', which see.")
4543 (color, frame)
4544 Lisp_Object color, frame;
4546 XColor foo;
4547 FRAME_PTR f = check_x_frame (frame);
4549 CHECK_STRING (color, 1);
4551 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4553 Lisp_Object rgb[3];
4555 rgb[0] = make_number (foo.red);
4556 rgb[1] = make_number (foo.green);
4557 rgb[2] = make_number (foo.blue);
4558 return Flist (3, rgb);
4560 else
4561 return Qnil;
4564 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4565 "Internal function called by `display-color-p', which see.")
4566 (display)
4567 Lisp_Object display;
4569 struct x_display_info *dpyinfo = check_x_display_info (display);
4571 if (dpyinfo->n_planes <= 2)
4572 return Qnil;
4574 switch (dpyinfo->visual->class)
4576 case StaticColor:
4577 case PseudoColor:
4578 case TrueColor:
4579 case DirectColor:
4580 return Qt;
4582 default:
4583 return Qnil;
4587 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4588 0, 1, 0,
4589 "Return t if the X display supports shades of gray.\n\
4590 Note that color displays do support shades of gray.\n\
4591 The optional argument DISPLAY specifies which display to ask about.\n\
4592 DISPLAY should be either a frame or a display name (a string).\n\
4593 If omitted or nil, that stands for the selected frame's display.")
4594 (display)
4595 Lisp_Object display;
4597 struct x_display_info *dpyinfo = check_x_display_info (display);
4599 if (dpyinfo->n_planes <= 1)
4600 return Qnil;
4602 switch (dpyinfo->visual->class)
4604 case StaticColor:
4605 case PseudoColor:
4606 case TrueColor:
4607 case DirectColor:
4608 case StaticGray:
4609 case GrayScale:
4610 return Qt;
4612 default:
4613 return Qnil;
4617 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4618 0, 1, 0,
4619 "Returns the width in pixels of the X display DISPLAY.\n\
4620 The optional argument DISPLAY specifies which display to ask about.\n\
4621 DISPLAY should be either a frame or a display name (a string).\n\
4622 If omitted or nil, that stands for the selected frame's display.")
4623 (display)
4624 Lisp_Object display;
4626 struct x_display_info *dpyinfo = check_x_display_info (display);
4628 return make_number (dpyinfo->width);
4631 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4632 Sx_display_pixel_height, 0, 1, 0,
4633 "Returns the height in pixels of the X display DISPLAY.\n\
4634 The optional argument DISPLAY specifies which display to ask about.\n\
4635 DISPLAY should be either a frame or a display name (a string).\n\
4636 If omitted or nil, that stands for the selected frame's display.")
4637 (display)
4638 Lisp_Object display;
4640 struct x_display_info *dpyinfo = check_x_display_info (display);
4642 return make_number (dpyinfo->height);
4645 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4646 0, 1, 0,
4647 "Returns the number of bitplanes of the X display DISPLAY.\n\
4648 The optional argument DISPLAY specifies which display to ask about.\n\
4649 DISPLAY should be either a frame or a display name (a string).\n\
4650 If omitted or nil, that stands for the selected frame's display.")
4651 (display)
4652 Lisp_Object display;
4654 struct x_display_info *dpyinfo = check_x_display_info (display);
4656 return make_number (dpyinfo->n_planes);
4659 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4660 0, 1, 0,
4661 "Returns the number of color cells of the X display DISPLAY.\n\
4662 The optional argument DISPLAY specifies which display to ask about.\n\
4663 DISPLAY should be either a frame or a display name (a string).\n\
4664 If omitted or nil, that stands for the selected frame's display.")
4665 (display)
4666 Lisp_Object display;
4668 struct x_display_info *dpyinfo = check_x_display_info (display);
4670 return make_number (DisplayCells (dpyinfo->display,
4671 XScreenNumberOfScreen (dpyinfo->screen)));
4674 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4675 Sx_server_max_request_size,
4676 0, 1, 0,
4677 "Returns the maximum request size of the X server of display DISPLAY.\n\
4678 The optional argument DISPLAY specifies which display to ask about.\n\
4679 DISPLAY should be either a frame or a display name (a string).\n\
4680 If omitted or nil, that stands for the selected frame's display.")
4681 (display)
4682 Lisp_Object display;
4684 struct x_display_info *dpyinfo = check_x_display_info (display);
4686 return make_number (MAXREQUEST (dpyinfo->display));
4689 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4690 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4691 The optional argument DISPLAY specifies which display to ask about.\n\
4692 DISPLAY should be either a frame or a display name (a string).\n\
4693 If omitted or nil, that stands for the selected frame's display.")
4694 (display)
4695 Lisp_Object display;
4697 struct x_display_info *dpyinfo = check_x_display_info (display);
4698 char *vendor = ServerVendor (dpyinfo->display);
4700 if (! vendor) vendor = "";
4701 return build_string (vendor);
4704 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4705 "Returns the version numbers of the X server of display DISPLAY.\n\
4706 The value is a list of three integers: the major and minor\n\
4707 version numbers of the X Protocol in use, and the vendor-specific release\n\
4708 number. See also the function `x-server-vendor'.\n\n\
4709 The optional argument DISPLAY specifies which display to ask about.\n\
4710 DISPLAY should be either a frame or a display name (a string).\n\
4711 If omitted or nil, that stands for the selected frame's display.")
4712 (display)
4713 Lisp_Object display;
4715 struct x_display_info *dpyinfo = check_x_display_info (display);
4716 Display *dpy = dpyinfo->display;
4718 return Fcons (make_number (ProtocolVersion (dpy)),
4719 Fcons (make_number (ProtocolRevision (dpy)),
4720 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4723 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4724 "Returns the number of screens on the X server of display DISPLAY.\n\
4725 The optional argument DISPLAY specifies which display to ask about.\n\
4726 DISPLAY should be either a frame or a display name (a string).\n\
4727 If omitted or nil, that stands for the selected frame's display.")
4728 (display)
4729 Lisp_Object display;
4731 struct x_display_info *dpyinfo = check_x_display_info (display);
4733 return make_number (ScreenCount (dpyinfo->display));
4736 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4737 "Returns the height in millimeters of the X display DISPLAY.\n\
4738 The optional argument DISPLAY specifies which display to ask about.\n\
4739 DISPLAY should be either a frame or a display name (a string).\n\
4740 If omitted or nil, that stands for the selected frame's display.")
4741 (display)
4742 Lisp_Object display;
4744 struct x_display_info *dpyinfo = check_x_display_info (display);
4746 return make_number (HeightMMOfScreen (dpyinfo->screen));
4749 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4750 "Returns the width in millimeters of the X display DISPLAY.\n\
4751 The optional argument DISPLAY specifies which display to ask about.\n\
4752 DISPLAY should be either a frame or a display name (a string).\n\
4753 If omitted or nil, that stands for the selected frame's display.")
4754 (display)
4755 Lisp_Object display;
4757 struct x_display_info *dpyinfo = check_x_display_info (display);
4759 return make_number (WidthMMOfScreen (dpyinfo->screen));
4762 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4763 Sx_display_backing_store, 0, 1, 0,
4764 "Returns an indication of whether X display DISPLAY does backing store.\n\
4765 The value may be `always', `when-mapped', or `not-useful'.\n\
4766 The optional argument DISPLAY specifies which display to ask about.\n\
4767 DISPLAY should be either a frame or a display name (a string).\n\
4768 If omitted or nil, that stands for the selected frame's display.")
4769 (display)
4770 Lisp_Object display;
4772 struct x_display_info *dpyinfo = check_x_display_info (display);
4773 Lisp_Object result;
4775 switch (DoesBackingStore (dpyinfo->screen))
4777 case Always:
4778 result = intern ("always");
4779 break;
4781 case WhenMapped:
4782 result = intern ("when-mapped");
4783 break;
4785 case NotUseful:
4786 result = intern ("not-useful");
4787 break;
4789 default:
4790 error ("Strange value for BackingStore parameter of screen");
4791 result = Qnil;
4794 return result;
4797 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4798 Sx_display_visual_class, 0, 1, 0,
4799 "Returns the visual class of the X display DISPLAY.\n\
4800 The value is one of the symbols `static-gray', `gray-scale',\n\
4801 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4802 The optional argument DISPLAY specifies which display to ask about.\n\
4803 DISPLAY should be either a frame or a display name (a string).\n\
4804 If omitted or nil, that stands for the selected frame's display.")
4805 (display)
4806 Lisp_Object display;
4808 struct x_display_info *dpyinfo = check_x_display_info (display);
4809 Lisp_Object result;
4811 switch (dpyinfo->visual->class)
4813 case StaticGray:
4814 result = intern ("static-gray");
4815 break;
4816 case GrayScale:
4817 result = intern ("gray-scale");
4818 break;
4819 case StaticColor:
4820 result = intern ("static-color");
4821 break;
4822 case PseudoColor:
4823 result = intern ("pseudo-color");
4824 break;
4825 case TrueColor:
4826 result = intern ("true-color");
4827 break;
4828 case DirectColor:
4829 result = intern ("direct-color");
4830 break;
4831 default:
4832 error ("Display has an unknown visual class");
4833 result = Qnil;
4836 return result;
4839 DEFUN ("x-display-save-under", Fx_display_save_under,
4840 Sx_display_save_under, 0, 1, 0,
4841 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4842 The optional argument DISPLAY specifies which display to ask about.\n\
4843 DISPLAY should be either a frame or a display name (a string).\n\
4844 If omitted or nil, that stands for the selected frame's display.")
4845 (display)
4846 Lisp_Object display;
4848 struct x_display_info *dpyinfo = check_x_display_info (display);
4850 if (DoesSaveUnders (dpyinfo->screen) == True)
4851 return Qt;
4852 else
4853 return Qnil;
4857 x_pixel_width (f)
4858 register struct frame *f;
4860 return PIXEL_WIDTH (f);
4864 x_pixel_height (f)
4865 register struct frame *f;
4867 return PIXEL_HEIGHT (f);
4871 x_char_width (f)
4872 register struct frame *f;
4874 return FONT_WIDTH (f->output_data.x->font);
4878 x_char_height (f)
4879 register struct frame *f;
4881 return f->output_data.x->line_height;
4885 x_screen_planes (f)
4886 register struct frame *f;
4888 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4893 /************************************************************************
4894 X Displays
4895 ************************************************************************/
4898 /* Mapping visual names to visuals. */
4900 static struct visual_class
4902 char *name;
4903 int class;
4905 visual_classes[] =
4907 {"StaticGray", StaticGray},
4908 {"GrayScale", GrayScale},
4909 {"StaticColor", StaticColor},
4910 {"PseudoColor", PseudoColor},
4911 {"TrueColor", TrueColor},
4912 {"DirectColor", DirectColor},
4913 NULL
4917 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4919 /* Value is the screen number of screen SCR. This is a substitute for
4920 the X function with the same name when that doesn't exist. */
4923 XScreenNumberOfScreen (scr)
4924 register Screen *scr;
4926 Display *dpy = scr->display;
4927 int i;
4929 for (i = 0; i < dpy->nscreens; ++i)
4930 if (scr == dpy->screens[i])
4931 break;
4933 return i;
4936 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4939 /* Select the visual that should be used on display DPYINFO. Set
4940 members of DPYINFO appropriately. Called from x_term_init. */
4942 void
4943 select_visual (dpyinfo)
4944 struct x_display_info *dpyinfo;
4946 Display *dpy = dpyinfo->display;
4947 Screen *screen = dpyinfo->screen;
4948 Lisp_Object value;
4950 /* See if a visual is specified. */
4951 value = display_x_get_resource (dpyinfo,
4952 build_string ("visualClass"),
4953 build_string ("VisualClass"),
4954 Qnil, Qnil);
4955 if (STRINGP (value))
4957 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4958 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4959 depth, a decimal number. NAME is compared with case ignored. */
4960 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4961 char *dash;
4962 int i, class = -1;
4963 XVisualInfo vinfo;
4965 strcpy (s, XSTRING (value)->data);
4966 dash = index (s, '-');
4967 if (dash)
4969 dpyinfo->n_planes = atoi (dash + 1);
4970 *dash = '\0';
4972 else
4973 /* We won't find a matching visual with depth 0, so that
4974 an error will be printed below. */
4975 dpyinfo->n_planes = 0;
4977 /* Determine the visual class. */
4978 for (i = 0; visual_classes[i].name; ++i)
4979 if (xstricmp (s, visual_classes[i].name) == 0)
4981 class = visual_classes[i].class;
4982 break;
4985 /* Look up a matching visual for the specified class. */
4986 if (class == -1
4987 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4988 dpyinfo->n_planes, class, &vinfo))
4989 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
4991 dpyinfo->visual = vinfo.visual;
4993 else
4995 int n_visuals;
4996 XVisualInfo *vinfo, vinfo_template;
4998 dpyinfo->visual = DefaultVisualOfScreen (screen);
5000 #ifdef HAVE_X11R4
5001 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5002 #else
5003 vinfo_template.visualid = dpyinfo->visual->visualid;
5004 #endif
5005 vinfo_template.screen = XScreenNumberOfScreen (screen);
5006 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5007 &vinfo_template, &n_visuals);
5008 if (n_visuals != 1)
5009 fatal ("Can't get proper X visual info");
5011 dpyinfo->n_planes = vinfo->depth;
5012 XFree ((char *) vinfo);
5017 /* Return the X display structure for the display named NAME.
5018 Open a new connection if necessary. */
5020 struct x_display_info *
5021 x_display_info_for_name (name)
5022 Lisp_Object name;
5024 Lisp_Object names;
5025 struct x_display_info *dpyinfo;
5027 CHECK_STRING (name, 0);
5029 if (! EQ (Vwindow_system, intern ("x")))
5030 error ("Not using X Windows");
5032 for (dpyinfo = x_display_list, names = x_display_name_list;
5033 dpyinfo;
5034 dpyinfo = dpyinfo->next, names = XCDR (names))
5036 Lisp_Object tem;
5037 tem = Fstring_equal (XCAR (XCAR (names)), name);
5038 if (!NILP (tem))
5039 return dpyinfo;
5042 /* Use this general default value to start with. */
5043 Vx_resource_name = Vinvocation_name;
5045 validate_x_resource_name ();
5047 dpyinfo = x_term_init (name, (char *)0,
5048 (char *) XSTRING (Vx_resource_name)->data);
5050 if (dpyinfo == 0)
5051 error ("Cannot connect to X server %s", XSTRING (name)->data);
5053 x_in_use = 1;
5054 XSETFASTINT (Vwindow_system_version, 11);
5056 return dpyinfo;
5060 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5061 1, 3, 0, "Open a connection to an X server.\n\
5062 DISPLAY is the name of the display to connect to.\n\
5063 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5064 If the optional third arg MUST-SUCCEED is non-nil,\n\
5065 terminate Emacs if we can't open the connection.")
5066 (display, xrm_string, must_succeed)
5067 Lisp_Object display, xrm_string, must_succeed;
5069 unsigned char *xrm_option;
5070 struct x_display_info *dpyinfo;
5072 CHECK_STRING (display, 0);
5073 if (! NILP (xrm_string))
5074 CHECK_STRING (xrm_string, 1);
5076 if (! EQ (Vwindow_system, intern ("x")))
5077 error ("Not using X Windows");
5079 if (! NILP (xrm_string))
5080 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
5081 else
5082 xrm_option = (unsigned char *) 0;
5084 validate_x_resource_name ();
5086 /* This is what opens the connection and sets x_current_display.
5087 This also initializes many symbols, such as those used for input. */
5088 dpyinfo = x_term_init (display, xrm_option,
5089 (char *) XSTRING (Vx_resource_name)->data);
5091 if (dpyinfo == 0)
5093 if (!NILP (must_succeed))
5094 fatal ("Cannot connect to X server %s.\n\
5095 Check the DISPLAY environment variable or use `-d'.\n\
5096 Also use the `xhost' program to verify that it is set to permit\n\
5097 connections from your machine.\n",
5098 XSTRING (display)->data);
5099 else
5100 error ("Cannot connect to X server %s", XSTRING (display)->data);
5103 x_in_use = 1;
5105 XSETFASTINT (Vwindow_system_version, 11);
5106 return Qnil;
5109 DEFUN ("x-close-connection", Fx_close_connection,
5110 Sx_close_connection, 1, 1, 0,
5111 "Close the connection to DISPLAY's X server.\n\
5112 For DISPLAY, specify either a frame or a display name (a string).\n\
5113 If DISPLAY is nil, that stands for the selected frame's display.")
5114 (display)
5115 Lisp_Object display;
5117 struct x_display_info *dpyinfo = check_x_display_info (display);
5118 int i;
5120 if (dpyinfo->reference_count > 0)
5121 error ("Display still has frames on it");
5123 BLOCK_INPUT;
5124 /* Free the fonts in the font table. */
5125 for (i = 0; i < dpyinfo->n_fonts; i++)
5126 if (dpyinfo->font_table[i].name)
5128 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5129 xfree (dpyinfo->font_table[i].full_name);
5130 xfree (dpyinfo->font_table[i].name);
5131 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5134 x_destroy_all_bitmaps (dpyinfo);
5135 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5137 #ifdef USE_X_TOOLKIT
5138 XtCloseDisplay (dpyinfo->display);
5139 #else
5140 XCloseDisplay (dpyinfo->display);
5141 #endif
5143 x_delete_display (dpyinfo);
5144 UNBLOCK_INPUT;
5146 return Qnil;
5149 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5150 "Return the list of display names that Emacs has connections to.")
5153 Lisp_Object tail, result;
5155 result = Qnil;
5156 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5157 result = Fcons (XCAR (XCAR (tail)), result);
5159 return result;
5162 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5163 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5164 If ON is nil, allow buffering of requests.\n\
5165 Turning on synchronization prohibits the Xlib routines from buffering\n\
5166 requests and seriously degrades performance, but makes debugging much\n\
5167 easier.\n\
5168 The optional second argument DISPLAY specifies which display to act on.\n\
5169 DISPLAY should be either a frame or a display name (a string).\n\
5170 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5171 (on, display)
5172 Lisp_Object display, on;
5174 struct x_display_info *dpyinfo = check_x_display_info (display);
5176 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5178 return Qnil;
5181 /* Wait for responses to all X commands issued so far for frame F. */
5183 void
5184 x_sync (f)
5185 FRAME_PTR f;
5187 BLOCK_INPUT;
5188 XSync (FRAME_X_DISPLAY (f), False);
5189 UNBLOCK_INPUT;
5193 /***********************************************************************
5194 Image types
5195 ***********************************************************************/
5197 /* Value is the number of elements of vector VECTOR. */
5199 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5201 /* List of supported image types. Use define_image_type to add new
5202 types. Use lookup_image_type to find a type for a given symbol. */
5204 static struct image_type *image_types;
5206 /* The symbol `image' which is the car of the lists used to represent
5207 images in Lisp. */
5209 extern Lisp_Object Qimage;
5211 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5213 Lisp_Object Qxbm;
5215 /* Keywords. */
5217 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5218 extern Lisp_Object QCdata;
5219 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5220 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5221 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5223 /* Other symbols. */
5225 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5227 /* Time in seconds after which images should be removed from the cache
5228 if not displayed. */
5230 Lisp_Object Vimage_cache_eviction_delay;
5232 /* Function prototypes. */
5234 static void define_image_type P_ ((struct image_type *type));
5235 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5236 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5237 static void x_laplace P_ ((struct frame *, struct image *));
5238 static void x_emboss P_ ((struct frame *, struct image *));
5239 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5240 Lisp_Object));
5243 /* Define a new image type from TYPE. This adds a copy of TYPE to
5244 image_types and adds the symbol *TYPE->type to Vimage_types. */
5246 static void
5247 define_image_type (type)
5248 struct image_type *type;
5250 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5251 The initialized data segment is read-only. */
5252 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5253 bcopy (type, p, sizeof *p);
5254 p->next = image_types;
5255 image_types = p;
5256 Vimage_types = Fcons (*p->type, Vimage_types);
5260 /* Look up image type SYMBOL, and return a pointer to its image_type
5261 structure. Value is null if SYMBOL is not a known image type. */
5263 static INLINE struct image_type *
5264 lookup_image_type (symbol)
5265 Lisp_Object symbol;
5267 struct image_type *type;
5269 for (type = image_types; type; type = type->next)
5270 if (EQ (symbol, *type->type))
5271 break;
5273 return type;
5277 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5278 valid image specification is a list whose car is the symbol
5279 `image', and whose rest is a property list. The property list must
5280 contain a value for key `:type'. That value must be the name of a
5281 supported image type. The rest of the property list depends on the
5282 image type. */
5285 valid_image_p (object)
5286 Lisp_Object object;
5288 int valid_p = 0;
5290 if (CONSP (object) && EQ (XCAR (object), Qimage))
5292 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5293 struct image_type *type = lookup_image_type (symbol);
5295 if (type)
5296 valid_p = type->valid_p (object);
5299 return valid_p;
5303 /* Log error message with format string FORMAT and argument ARG.
5304 Signaling an error, e.g. when an image cannot be loaded, is not a
5305 good idea because this would interrupt redisplay, and the error
5306 message display would lead to another redisplay. This function
5307 therefore simply displays a message. */
5309 static void
5310 image_error (format, arg1, arg2)
5311 char *format;
5312 Lisp_Object arg1, arg2;
5314 add_to_log (format, arg1, arg2);
5319 /***********************************************************************
5320 Image specifications
5321 ***********************************************************************/
5323 enum image_value_type
5325 IMAGE_DONT_CHECK_VALUE_TYPE,
5326 IMAGE_STRING_VALUE,
5327 IMAGE_SYMBOL_VALUE,
5328 IMAGE_POSITIVE_INTEGER_VALUE,
5329 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5330 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5331 IMAGE_ASCENT_VALUE,
5332 IMAGE_INTEGER_VALUE,
5333 IMAGE_FUNCTION_VALUE,
5334 IMAGE_NUMBER_VALUE,
5335 IMAGE_BOOL_VALUE
5338 /* Structure used when parsing image specifications. */
5340 struct image_keyword
5342 /* Name of keyword. */
5343 char *name;
5345 /* The type of value allowed. */
5346 enum image_value_type type;
5348 /* Non-zero means key must be present. */
5349 int mandatory_p;
5351 /* Used to recognize duplicate keywords in a property list. */
5352 int count;
5354 /* The value that was found. */
5355 Lisp_Object value;
5359 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5360 int, Lisp_Object));
5361 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5364 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5365 has the format (image KEYWORD VALUE ...). One of the keyword/
5366 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5367 image_keywords structures of size NKEYWORDS describing other
5368 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5370 static int
5371 parse_image_spec (spec, keywords, nkeywords, type)
5372 Lisp_Object spec;
5373 struct image_keyword *keywords;
5374 int nkeywords;
5375 Lisp_Object type;
5377 int i;
5378 Lisp_Object plist;
5380 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5381 return 0;
5383 plist = XCDR (spec);
5384 while (CONSP (plist))
5386 Lisp_Object key, value;
5388 /* First element of a pair must be a symbol. */
5389 key = XCAR (plist);
5390 plist = XCDR (plist);
5391 if (!SYMBOLP (key))
5392 return 0;
5394 /* There must follow a value. */
5395 if (!CONSP (plist))
5396 return 0;
5397 value = XCAR (plist);
5398 plist = XCDR (plist);
5400 /* Find key in KEYWORDS. Error if not found. */
5401 for (i = 0; i < nkeywords; ++i)
5402 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5403 break;
5405 if (i == nkeywords)
5406 continue;
5408 /* Record that we recognized the keyword. If a keywords
5409 was found more than once, it's an error. */
5410 keywords[i].value = value;
5411 ++keywords[i].count;
5413 if (keywords[i].count > 1)
5414 return 0;
5416 /* Check type of value against allowed type. */
5417 switch (keywords[i].type)
5419 case IMAGE_STRING_VALUE:
5420 if (!STRINGP (value))
5421 return 0;
5422 break;
5424 case IMAGE_SYMBOL_VALUE:
5425 if (!SYMBOLP (value))
5426 return 0;
5427 break;
5429 case IMAGE_POSITIVE_INTEGER_VALUE:
5430 if (!INTEGERP (value) || XINT (value) <= 0)
5431 return 0;
5432 break;
5434 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5435 if (INTEGERP (value) && XINT (value) >= 0)
5436 break;
5437 if (CONSP (value)
5438 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5439 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5440 break;
5441 return 0;
5443 case IMAGE_ASCENT_VALUE:
5444 if (SYMBOLP (value) && EQ (value, Qcenter))
5445 break;
5446 else if (INTEGERP (value)
5447 && XINT (value) >= 0
5448 && XINT (value) <= 100)
5449 break;
5450 return 0;
5452 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5453 if (!INTEGERP (value) || XINT (value) < 0)
5454 return 0;
5455 break;
5457 case IMAGE_DONT_CHECK_VALUE_TYPE:
5458 break;
5460 case IMAGE_FUNCTION_VALUE:
5461 value = indirect_function (value);
5462 if (SUBRP (value)
5463 || COMPILEDP (value)
5464 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5465 break;
5466 return 0;
5468 case IMAGE_NUMBER_VALUE:
5469 if (!INTEGERP (value) && !FLOATP (value))
5470 return 0;
5471 break;
5473 case IMAGE_INTEGER_VALUE:
5474 if (!INTEGERP (value))
5475 return 0;
5476 break;
5478 case IMAGE_BOOL_VALUE:
5479 if (!NILP (value) && !EQ (value, Qt))
5480 return 0;
5481 break;
5483 default:
5484 abort ();
5485 break;
5488 if (EQ (key, QCtype) && !EQ (type, value))
5489 return 0;
5492 /* Check that all mandatory fields are present. */
5493 for (i = 0; i < nkeywords; ++i)
5494 if (keywords[i].mandatory_p && keywords[i].count == 0)
5495 return 0;
5497 return NILP (plist);
5501 /* Return the value of KEY in image specification SPEC. Value is nil
5502 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5503 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5505 static Lisp_Object
5506 image_spec_value (spec, key, found)
5507 Lisp_Object spec, key;
5508 int *found;
5510 Lisp_Object tail;
5512 xassert (valid_image_p (spec));
5514 for (tail = XCDR (spec);
5515 CONSP (tail) && CONSP (XCDR (tail));
5516 tail = XCDR (XCDR (tail)))
5518 if (EQ (XCAR (tail), key))
5520 if (found)
5521 *found = 1;
5522 return XCAR (XCDR (tail));
5526 if (found)
5527 *found = 0;
5528 return Qnil;
5532 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5533 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5534 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5535 size in canonical character units.\n\
5536 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5537 or omitted means use the selected frame.")
5538 (spec, pixels, frame)
5539 Lisp_Object spec, pixels, frame;
5541 Lisp_Object size;
5543 size = Qnil;
5544 if (valid_image_p (spec))
5546 struct frame *f = check_x_frame (frame);
5547 int id = lookup_image (f, spec);
5548 struct image *img = IMAGE_FROM_ID (f, id);
5549 int width = img->width + 2 * img->hmargin;
5550 int height = img->height + 2 * img->vmargin;
5552 if (NILP (pixels))
5553 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5554 make_float ((double) height / CANON_Y_UNIT (f)));
5555 else
5556 size = Fcons (make_number (width), make_number (height));
5558 else
5559 error ("Invalid image specification");
5561 return size;
5565 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5566 "Return t if image SPEC has a mask bitmap.\n\
5567 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5568 or omitted means use the selected frame.")
5569 (spec, frame)
5570 Lisp_Object spec, frame;
5572 Lisp_Object mask;
5574 mask = Qnil;
5575 if (valid_image_p (spec))
5577 struct frame *f = check_x_frame (frame);
5578 int id = lookup_image (f, spec);
5579 struct image *img = IMAGE_FROM_ID (f, id);
5580 if (img->mask)
5581 mask = Qt;
5583 else
5584 error ("Invalid image specification");
5586 return mask;
5591 /***********************************************************************
5592 Image type independent image structures
5593 ***********************************************************************/
5595 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5596 static void free_image P_ ((struct frame *f, struct image *img));
5599 /* Allocate and return a new image structure for image specification
5600 SPEC. SPEC has a hash value of HASH. */
5602 static struct image *
5603 make_image (spec, hash)
5604 Lisp_Object spec;
5605 unsigned hash;
5607 struct image *img = (struct image *) xmalloc (sizeof *img);
5609 xassert (valid_image_p (spec));
5610 bzero (img, sizeof *img);
5611 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5612 xassert (img->type != NULL);
5613 img->spec = spec;
5614 img->data.lisp_val = Qnil;
5615 img->ascent = DEFAULT_IMAGE_ASCENT;
5616 img->hash = hash;
5617 return img;
5621 /* Free image IMG which was used on frame F, including its resources. */
5623 static void
5624 free_image (f, img)
5625 struct frame *f;
5626 struct image *img;
5628 if (img)
5630 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5632 /* Remove IMG from the hash table of its cache. */
5633 if (img->prev)
5634 img->prev->next = img->next;
5635 else
5636 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5638 if (img->next)
5639 img->next->prev = img->prev;
5641 c->images[img->id] = NULL;
5643 /* Free resources, then free IMG. */
5644 img->type->free (f, img);
5645 xfree (img);
5650 /* Prepare image IMG for display on frame F. Must be called before
5651 drawing an image. */
5653 void
5654 prepare_image_for_display (f, img)
5655 struct frame *f;
5656 struct image *img;
5658 EMACS_TIME t;
5660 /* We're about to display IMG, so set its timestamp to `now'. */
5661 EMACS_GET_TIME (t);
5662 img->timestamp = EMACS_SECS (t);
5664 /* If IMG doesn't have a pixmap yet, load it now, using the image
5665 type dependent loader function. */
5666 if (img->pixmap == None && !img->load_failed_p)
5667 img->load_failed_p = img->type->load (f, img) == 0;
5671 /* Value is the number of pixels for the ascent of image IMG when
5672 drawn in face FACE. */
5675 image_ascent (img, face)
5676 struct image *img;
5677 struct face *face;
5679 int height = img->height + img->vmargin;
5680 int ascent;
5682 if (img->ascent == CENTERED_IMAGE_ASCENT)
5684 if (face->font)
5685 /* This expression is arranged so that if the image can't be
5686 exactly centered, it will be moved slightly up. This is
5687 because a typical font is `top-heavy' (due to the presence
5688 uppercase letters), so the image placement should err towards
5689 being top-heavy too. It also just generally looks better. */
5690 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5691 else
5692 ascent = height / 2;
5694 else
5695 ascent = height * img->ascent / 100.0;
5697 return ascent;
5702 /***********************************************************************
5703 Helper functions for X image types
5704 ***********************************************************************/
5706 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5707 int, int));
5708 static void x_clear_image P_ ((struct frame *f, struct image *img));
5709 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5710 struct image *img,
5711 Lisp_Object color_name,
5712 unsigned long dflt));
5715 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5716 free the pixmap if any. MASK_P non-zero means clear the mask
5717 pixmap if any. COLORS_P non-zero means free colors allocated for
5718 the image, if any. */
5720 static void
5721 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5722 struct frame *f;
5723 struct image *img;
5724 int pixmap_p, mask_p, colors_p;
5726 if (pixmap_p && img->pixmap)
5728 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5729 img->pixmap = None;
5732 if (mask_p && img->mask)
5734 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5735 img->mask = None;
5738 if (colors_p && img->ncolors)
5740 x_free_colors (f, img->colors, img->ncolors);
5741 xfree (img->colors);
5742 img->colors = NULL;
5743 img->ncolors = 0;
5747 /* Free X resources of image IMG which is used on frame F. */
5749 static void
5750 x_clear_image (f, img)
5751 struct frame *f;
5752 struct image *img;
5754 BLOCK_INPUT;
5755 x_clear_image_1 (f, img, 1, 1, 1);
5756 UNBLOCK_INPUT;
5760 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5761 cannot be allocated, use DFLT. Add a newly allocated color to
5762 IMG->colors, so that it can be freed again. Value is the pixel
5763 color. */
5765 static unsigned long
5766 x_alloc_image_color (f, img, color_name, dflt)
5767 struct frame *f;
5768 struct image *img;
5769 Lisp_Object color_name;
5770 unsigned long dflt;
5772 XColor color;
5773 unsigned long result;
5775 xassert (STRINGP (color_name));
5777 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5779 /* This isn't called frequently so we get away with simply
5780 reallocating the color vector to the needed size, here. */
5781 ++img->ncolors;
5782 img->colors =
5783 (unsigned long *) xrealloc (img->colors,
5784 img->ncolors * sizeof *img->colors);
5785 img->colors[img->ncolors - 1] = color.pixel;
5786 result = color.pixel;
5788 else
5789 result = dflt;
5791 return result;
5796 /***********************************************************************
5797 Image Cache
5798 ***********************************************************************/
5800 static void cache_image P_ ((struct frame *f, struct image *img));
5801 static void postprocess_image P_ ((struct frame *, struct image *));
5804 /* Return a new, initialized image cache that is allocated from the
5805 heap. Call free_image_cache to free an image cache. */
5807 struct image_cache *
5808 make_image_cache ()
5810 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5811 int size;
5813 bzero (c, sizeof *c);
5814 c->size = 50;
5815 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5816 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5817 c->buckets = (struct image **) xmalloc (size);
5818 bzero (c->buckets, size);
5819 return c;
5823 /* Free image cache of frame F. Be aware that X frames share images
5824 caches. */
5826 void
5827 free_image_cache (f)
5828 struct frame *f;
5830 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5831 if (c)
5833 int i;
5835 /* Cache should not be referenced by any frame when freed. */
5836 xassert (c->refcount == 0);
5838 for (i = 0; i < c->used; ++i)
5839 free_image (f, c->images[i]);
5840 xfree (c->images);
5841 xfree (c->buckets);
5842 xfree (c);
5843 FRAME_X_IMAGE_CACHE (f) = NULL;
5848 /* Clear image cache of frame F. FORCE_P non-zero means free all
5849 images. FORCE_P zero means clear only images that haven't been
5850 displayed for some time. Should be called from time to time to
5851 reduce the number of loaded images. If image-eviction-seconds is
5852 non-nil, this frees images in the cache which weren't displayed for
5853 at least that many seconds. */
5855 void
5856 clear_image_cache (f, force_p)
5857 struct frame *f;
5858 int force_p;
5860 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5862 if (c && INTEGERP (Vimage_cache_eviction_delay))
5864 EMACS_TIME t;
5865 unsigned long old;
5866 int i, nfreed;
5868 EMACS_GET_TIME (t);
5869 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5871 /* Block input so that we won't be interrupted by a SIGIO
5872 while being in an inconsistent state. */
5873 BLOCK_INPUT;
5875 for (i = nfreed = 0; i < c->used; ++i)
5877 struct image *img = c->images[i];
5878 if (img != NULL
5879 && (force_p || img->timestamp < old))
5881 free_image (f, img);
5882 ++nfreed;
5886 /* We may be clearing the image cache because, for example,
5887 Emacs was iconified for a longer period of time. In that
5888 case, current matrices may still contain references to
5889 images freed above. So, clear these matrices. */
5890 if (nfreed)
5892 Lisp_Object tail, frame;
5894 FOR_EACH_FRAME (tail, frame)
5896 struct frame *f = XFRAME (frame);
5897 if (FRAME_X_P (f)
5898 && FRAME_X_IMAGE_CACHE (f) == c)
5899 clear_current_matrices (f);
5902 ++windows_or_buffers_changed;
5905 UNBLOCK_INPUT;
5910 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5911 0, 1, 0,
5912 "Clear the image cache of FRAME.\n\
5913 FRAME nil or omitted means use the selected frame.\n\
5914 FRAME t means clear the image caches of all frames.")
5915 (frame)
5916 Lisp_Object frame;
5918 if (EQ (frame, Qt))
5920 Lisp_Object tail;
5922 FOR_EACH_FRAME (tail, frame)
5923 if (FRAME_X_P (XFRAME (frame)))
5924 clear_image_cache (XFRAME (frame), 1);
5926 else
5927 clear_image_cache (check_x_frame (frame), 1);
5929 return Qnil;
5933 /* Compute masks and transform image IMG on frame F, as specified
5934 by the image's specification, */
5936 static void
5937 postprocess_image (f, img)
5938 struct frame *f;
5939 struct image *img;
5941 /* Manipulation of the image's mask. */
5942 if (img->pixmap)
5944 Lisp_Object conversion, spec;
5945 Lisp_Object mask;
5947 spec = img->spec;
5949 /* `:heuristic-mask t'
5950 `:mask heuristic'
5951 means build a mask heuristically.
5952 `:heuristic-mask (R G B)'
5953 `:mask (heuristic (R G B))'
5954 means build a mask from color (R G B) in the
5955 image.
5956 `:mask nil'
5957 means remove a mask, if any. */
5959 mask = image_spec_value (spec, QCheuristic_mask, NULL);
5960 if (!NILP (mask))
5961 x_build_heuristic_mask (f, img, mask);
5962 else
5964 int found_p;
5966 mask = image_spec_value (spec, QCmask, &found_p);
5968 if (EQ (mask, Qheuristic))
5969 x_build_heuristic_mask (f, img, Qt);
5970 else if (CONSP (mask)
5971 && EQ (XCAR (mask), Qheuristic))
5973 if (CONSP (XCDR (mask)))
5974 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
5975 else
5976 x_build_heuristic_mask (f, img, XCDR (mask));
5978 else if (NILP (mask) && found_p && img->mask)
5980 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5981 img->mask = None;
5986 /* Should we apply an image transformation algorithm? */
5987 conversion = image_spec_value (spec, QCconversion, NULL);
5988 if (EQ (conversion, Qdisabled))
5989 x_disable_image (f, img);
5990 else if (EQ (conversion, Qlaplace))
5991 x_laplace (f, img);
5992 else if (EQ (conversion, Qemboss))
5993 x_emboss (f, img);
5994 else if (CONSP (conversion)
5995 && EQ (XCAR (conversion), Qedge_detection))
5997 Lisp_Object tem;
5998 tem = XCDR (conversion);
5999 if (CONSP (tem))
6000 x_edge_detection (f, img,
6001 Fplist_get (tem, QCmatrix),
6002 Fplist_get (tem, QCcolor_adjustment));
6008 /* Return the id of image with Lisp specification SPEC on frame F.
6009 SPEC must be a valid Lisp image specification (see valid_image_p). */
6012 lookup_image (f, spec)
6013 struct frame *f;
6014 Lisp_Object spec;
6016 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6017 struct image *img;
6018 int i;
6019 unsigned hash;
6020 struct gcpro gcpro1;
6021 EMACS_TIME now;
6023 /* F must be a window-system frame, and SPEC must be a valid image
6024 specification. */
6025 xassert (FRAME_WINDOW_P (f));
6026 xassert (valid_image_p (spec));
6028 GCPRO1 (spec);
6030 /* Look up SPEC in the hash table of the image cache. */
6031 hash = sxhash (spec, 0);
6032 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6034 for (img = c->buckets[i]; img; img = img->next)
6035 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6036 break;
6038 /* If not found, create a new image and cache it. */
6039 if (img == NULL)
6041 extern Lisp_Object Qpostscript;
6043 BLOCK_INPUT;
6044 img = make_image (spec, hash);
6045 cache_image (f, img);
6046 img->load_failed_p = img->type->load (f, img) == 0;
6048 /* If we can't load the image, and we don't have a width and
6049 height, use some arbitrary width and height so that we can
6050 draw a rectangle for it. */
6051 if (img->load_failed_p)
6053 Lisp_Object value;
6055 value = image_spec_value (spec, QCwidth, NULL);
6056 img->width = (INTEGERP (value)
6057 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6058 value = image_spec_value (spec, QCheight, NULL);
6059 img->height = (INTEGERP (value)
6060 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6062 else
6064 /* Handle image type independent image attributes
6065 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
6066 Lisp_Object ascent, margin, relief;
6068 ascent = image_spec_value (spec, QCascent, NULL);
6069 if (INTEGERP (ascent))
6070 img->ascent = XFASTINT (ascent);
6071 else if (EQ (ascent, Qcenter))
6072 img->ascent = CENTERED_IMAGE_ASCENT;
6074 margin = image_spec_value (spec, QCmargin, NULL);
6075 if (INTEGERP (margin) && XINT (margin) >= 0)
6076 img->vmargin = img->hmargin = XFASTINT (margin);
6077 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6078 && INTEGERP (XCDR (margin)))
6080 if (XINT (XCAR (margin)) > 0)
6081 img->hmargin = XFASTINT (XCAR (margin));
6082 if (XINT (XCDR (margin)) > 0)
6083 img->vmargin = XFASTINT (XCDR (margin));
6086 relief = image_spec_value (spec, QCrelief, NULL);
6087 if (INTEGERP (relief))
6089 img->relief = XINT (relief);
6090 img->hmargin += abs (img->relief);
6091 img->vmargin += abs (img->relief);
6094 /* Do image transformations and compute masks, unless we
6095 don't have the image yet. */
6096 if (!EQ (*img->type->type, Qpostscript))
6097 postprocess_image (f, img);
6100 UNBLOCK_INPUT;
6101 xassert (!interrupt_input_blocked);
6104 /* We're using IMG, so set its timestamp to `now'. */
6105 EMACS_GET_TIME (now);
6106 img->timestamp = EMACS_SECS (now);
6108 UNGCPRO;
6110 /* Value is the image id. */
6111 return img->id;
6115 /* Cache image IMG in the image cache of frame F. */
6117 static void
6118 cache_image (f, img)
6119 struct frame *f;
6120 struct image *img;
6122 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6123 int i;
6125 /* Find a free slot in c->images. */
6126 for (i = 0; i < c->used; ++i)
6127 if (c->images[i] == NULL)
6128 break;
6130 /* If no free slot found, maybe enlarge c->images. */
6131 if (i == c->used && c->used == c->size)
6133 c->size *= 2;
6134 c->images = (struct image **) xrealloc (c->images,
6135 c->size * sizeof *c->images);
6138 /* Add IMG to c->images, and assign IMG an id. */
6139 c->images[i] = img;
6140 img->id = i;
6141 if (i == c->used)
6142 ++c->used;
6144 /* Add IMG to the cache's hash table. */
6145 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6146 img->next = c->buckets[i];
6147 if (img->next)
6148 img->next->prev = img;
6149 img->prev = NULL;
6150 c->buckets[i] = img;
6154 /* Call FN on every image in the image cache of frame F. Used to mark
6155 Lisp Objects in the image cache. */
6157 void
6158 forall_images_in_image_cache (f, fn)
6159 struct frame *f;
6160 void (*fn) P_ ((struct image *img));
6162 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6164 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6165 if (c)
6167 int i;
6168 for (i = 0; i < c->used; ++i)
6169 if (c->images[i])
6170 fn (c->images[i]);
6177 /***********************************************************************
6178 X support code
6179 ***********************************************************************/
6181 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6182 XImage **, Pixmap *));
6183 static void x_destroy_x_image P_ ((XImage *));
6184 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6187 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6188 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6189 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6190 via xmalloc. Print error messages via image_error if an error
6191 occurs. Value is non-zero if successful. */
6193 static int
6194 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6195 struct frame *f;
6196 int width, height, depth;
6197 XImage **ximg;
6198 Pixmap *pixmap;
6200 Display *display = FRAME_X_DISPLAY (f);
6201 Screen *screen = FRAME_X_SCREEN (f);
6202 Window window = FRAME_X_WINDOW (f);
6204 xassert (interrupt_input_blocked);
6206 if (depth <= 0)
6207 depth = DefaultDepthOfScreen (screen);
6208 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6209 depth, ZPixmap, 0, NULL, width, height,
6210 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6211 if (*ximg == NULL)
6213 image_error ("Unable to allocate X image", Qnil, Qnil);
6214 return 0;
6217 /* Allocate image raster. */
6218 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6220 /* Allocate a pixmap of the same size. */
6221 *pixmap = XCreatePixmap (display, window, width, height, depth);
6222 if (*pixmap == None)
6224 x_destroy_x_image (*ximg);
6225 *ximg = NULL;
6226 image_error ("Unable to create X pixmap", Qnil, Qnil);
6227 return 0;
6230 return 1;
6234 /* Destroy XImage XIMG. Free XIMG->data. */
6236 static void
6237 x_destroy_x_image (ximg)
6238 XImage *ximg;
6240 xassert (interrupt_input_blocked);
6241 if (ximg)
6243 xfree (ximg->data);
6244 ximg->data = NULL;
6245 XDestroyImage (ximg);
6250 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6251 are width and height of both the image and pixmap. */
6253 static void
6254 x_put_x_image (f, ximg, pixmap, width, height)
6255 struct frame *f;
6256 XImage *ximg;
6257 Pixmap pixmap;
6259 GC gc;
6261 xassert (interrupt_input_blocked);
6262 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6263 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6264 XFreeGC (FRAME_X_DISPLAY (f), gc);
6269 /***********************************************************************
6270 File Handling
6271 ***********************************************************************/
6273 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6274 static char *slurp_file P_ ((char *, int *));
6277 /* Find image file FILE. Look in data-directory, then
6278 x-bitmap-file-path. Value is the full name of the file found, or
6279 nil if not found. */
6281 static Lisp_Object
6282 x_find_image_file (file)
6283 Lisp_Object file;
6285 Lisp_Object file_found, search_path;
6286 struct gcpro gcpro1, gcpro2;
6287 int fd;
6289 file_found = Qnil;
6290 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6291 GCPRO2 (file_found, search_path);
6293 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6294 fd = openp (search_path, file, "", &file_found, 0);
6296 if (fd == -1)
6297 file_found = Qnil;
6298 else
6299 close (fd);
6301 UNGCPRO;
6302 return file_found;
6306 /* Read FILE into memory. Value is a pointer to a buffer allocated
6307 with xmalloc holding FILE's contents. Value is null if an error
6308 occurred. *SIZE is set to the size of the file. */
6310 static char *
6311 slurp_file (file, size)
6312 char *file;
6313 int *size;
6315 FILE *fp = NULL;
6316 char *buf = NULL;
6317 struct stat st;
6319 if (stat (file, &st) == 0
6320 && (fp = fopen (file, "r")) != NULL
6321 && (buf = (char *) xmalloc (st.st_size),
6322 fread (buf, 1, st.st_size, fp) == st.st_size))
6324 *size = st.st_size;
6325 fclose (fp);
6327 else
6329 if (fp)
6330 fclose (fp);
6331 if (buf)
6333 xfree (buf);
6334 buf = NULL;
6338 return buf;
6343 /***********************************************************************
6344 XBM images
6345 ***********************************************************************/
6347 static int xbm_scan P_ ((char **, char *, char *, int *));
6348 static int xbm_load P_ ((struct frame *f, struct image *img));
6349 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6350 char *, char *));
6351 static int xbm_image_p P_ ((Lisp_Object object));
6352 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6353 unsigned char **));
6354 static int xbm_file_p P_ ((Lisp_Object));
6357 /* Indices of image specification fields in xbm_format, below. */
6359 enum xbm_keyword_index
6361 XBM_TYPE,
6362 XBM_FILE,
6363 XBM_WIDTH,
6364 XBM_HEIGHT,
6365 XBM_DATA,
6366 XBM_FOREGROUND,
6367 XBM_BACKGROUND,
6368 XBM_ASCENT,
6369 XBM_MARGIN,
6370 XBM_RELIEF,
6371 XBM_ALGORITHM,
6372 XBM_HEURISTIC_MASK,
6373 XBM_MASK,
6374 XBM_LAST
6377 /* Vector of image_keyword structures describing the format
6378 of valid XBM image specifications. */
6380 static struct image_keyword xbm_format[XBM_LAST] =
6382 {":type", IMAGE_SYMBOL_VALUE, 1},
6383 {":file", IMAGE_STRING_VALUE, 0},
6384 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6385 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6386 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6387 {":foreground", IMAGE_STRING_VALUE, 0},
6388 {":background", IMAGE_STRING_VALUE, 0},
6389 {":ascent", IMAGE_ASCENT_VALUE, 0},
6390 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6391 {":relief", IMAGE_INTEGER_VALUE, 0},
6392 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6393 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6394 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6397 /* Structure describing the image type XBM. */
6399 static struct image_type xbm_type =
6401 &Qxbm,
6402 xbm_image_p,
6403 xbm_load,
6404 x_clear_image,
6405 NULL
6408 /* Tokens returned from xbm_scan. */
6410 enum xbm_token
6412 XBM_TK_IDENT = 256,
6413 XBM_TK_NUMBER
6417 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6418 A valid specification is a list starting with the symbol `image'
6419 The rest of the list is a property list which must contain an
6420 entry `:type xbm..
6422 If the specification specifies a file to load, it must contain
6423 an entry `:file FILENAME' where FILENAME is a string.
6425 If the specification is for a bitmap loaded from memory it must
6426 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6427 WIDTH and HEIGHT are integers > 0. DATA may be:
6429 1. a string large enough to hold the bitmap data, i.e. it must
6430 have a size >= (WIDTH + 7) / 8 * HEIGHT
6432 2. a bool-vector of size >= WIDTH * HEIGHT
6434 3. a vector of strings or bool-vectors, one for each line of the
6435 bitmap.
6437 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6438 may not be specified in this case because they are defined in the
6439 XBM file.
6441 Both the file and data forms may contain the additional entries
6442 `:background COLOR' and `:foreground COLOR'. If not present,
6443 foreground and background of the frame on which the image is
6444 displayed is used. */
6446 static int
6447 xbm_image_p (object)
6448 Lisp_Object object;
6450 struct image_keyword kw[XBM_LAST];
6452 bcopy (xbm_format, kw, sizeof kw);
6453 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6454 return 0;
6456 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6458 if (kw[XBM_FILE].count)
6460 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6461 return 0;
6463 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6465 /* In-memory XBM file. */
6466 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6467 return 0;
6469 else
6471 Lisp_Object data;
6472 int width, height;
6474 /* Entries for `:width', `:height' and `:data' must be present. */
6475 if (!kw[XBM_WIDTH].count
6476 || !kw[XBM_HEIGHT].count
6477 || !kw[XBM_DATA].count)
6478 return 0;
6480 data = kw[XBM_DATA].value;
6481 width = XFASTINT (kw[XBM_WIDTH].value);
6482 height = XFASTINT (kw[XBM_HEIGHT].value);
6484 /* Check type of data, and width and height against contents of
6485 data. */
6486 if (VECTORP (data))
6488 int i;
6490 /* Number of elements of the vector must be >= height. */
6491 if (XVECTOR (data)->size < height)
6492 return 0;
6494 /* Each string or bool-vector in data must be large enough
6495 for one line of the image. */
6496 for (i = 0; i < height; ++i)
6498 Lisp_Object elt = XVECTOR (data)->contents[i];
6500 if (STRINGP (elt))
6502 if (XSTRING (elt)->size
6503 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6504 return 0;
6506 else if (BOOL_VECTOR_P (elt))
6508 if (XBOOL_VECTOR (elt)->size < width)
6509 return 0;
6511 else
6512 return 0;
6515 else if (STRINGP (data))
6517 if (XSTRING (data)->size
6518 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6519 return 0;
6521 else if (BOOL_VECTOR_P (data))
6523 if (XBOOL_VECTOR (data)->size < width * height)
6524 return 0;
6526 else
6527 return 0;
6530 return 1;
6534 /* Scan a bitmap file. FP is the stream to read from. Value is
6535 either an enumerator from enum xbm_token, or a character for a
6536 single-character token, or 0 at end of file. If scanning an
6537 identifier, store the lexeme of the identifier in SVAL. If
6538 scanning a number, store its value in *IVAL. */
6540 static int
6541 xbm_scan (s, end, sval, ival)
6542 char **s, *end;
6543 char *sval;
6544 int *ival;
6546 int c;
6548 loop:
6550 /* Skip white space. */
6551 while (*s < end && (c = *(*s)++, isspace (c)))
6554 if (*s >= end)
6555 c = 0;
6556 else if (isdigit (c))
6558 int value = 0, digit;
6560 if (c == '0' && *s < end)
6562 c = *(*s)++;
6563 if (c == 'x' || c == 'X')
6565 while (*s < end)
6567 c = *(*s)++;
6568 if (isdigit (c))
6569 digit = c - '0';
6570 else if (c >= 'a' && c <= 'f')
6571 digit = c - 'a' + 10;
6572 else if (c >= 'A' && c <= 'F')
6573 digit = c - 'A' + 10;
6574 else
6575 break;
6576 value = 16 * value + digit;
6579 else if (isdigit (c))
6581 value = c - '0';
6582 while (*s < end
6583 && (c = *(*s)++, isdigit (c)))
6584 value = 8 * value + c - '0';
6587 else
6589 value = c - '0';
6590 while (*s < end
6591 && (c = *(*s)++, isdigit (c)))
6592 value = 10 * value + c - '0';
6595 if (*s < end)
6596 *s = *s - 1;
6597 *ival = value;
6598 c = XBM_TK_NUMBER;
6600 else if (isalpha (c) || c == '_')
6602 *sval++ = c;
6603 while (*s < end
6604 && (c = *(*s)++, (isalnum (c) || c == '_')))
6605 *sval++ = c;
6606 *sval = 0;
6607 if (*s < end)
6608 *s = *s - 1;
6609 c = XBM_TK_IDENT;
6611 else if (c == '/' && **s == '*')
6613 /* C-style comment. */
6614 ++*s;
6615 while (**s && (**s != '*' || *(*s + 1) != '/'))
6616 ++*s;
6617 if (**s)
6619 *s += 2;
6620 goto loop;
6624 return c;
6628 /* Replacement for XReadBitmapFileData which isn't available under old
6629 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6630 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6631 the image. Return in *DATA the bitmap data allocated with xmalloc.
6632 Value is non-zero if successful. DATA null means just test if
6633 CONTENTS looks like an in-memory XBM file. */
6635 static int
6636 xbm_read_bitmap_data (contents, end, width, height, data)
6637 char *contents, *end;
6638 int *width, *height;
6639 unsigned char **data;
6641 char *s = contents;
6642 char buffer[BUFSIZ];
6643 int padding_p = 0;
6644 int v10 = 0;
6645 int bytes_per_line, i, nbytes;
6646 unsigned char *p;
6647 int value;
6648 int LA1;
6650 #define match() \
6651 LA1 = xbm_scan (&s, end, buffer, &value)
6653 #define expect(TOKEN) \
6654 if (LA1 != (TOKEN)) \
6655 goto failure; \
6656 else \
6657 match ()
6659 #define expect_ident(IDENT) \
6660 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6661 match (); \
6662 else \
6663 goto failure
6665 *width = *height = -1;
6666 if (data)
6667 *data = NULL;
6668 LA1 = xbm_scan (&s, end, buffer, &value);
6670 /* Parse defines for width, height and hot-spots. */
6671 while (LA1 == '#')
6673 match ();
6674 expect_ident ("define");
6675 expect (XBM_TK_IDENT);
6677 if (LA1 == XBM_TK_NUMBER);
6679 char *p = strrchr (buffer, '_');
6680 p = p ? p + 1 : buffer;
6681 if (strcmp (p, "width") == 0)
6682 *width = value;
6683 else if (strcmp (p, "height") == 0)
6684 *height = value;
6686 expect (XBM_TK_NUMBER);
6689 if (*width < 0 || *height < 0)
6690 goto failure;
6691 else if (data == NULL)
6692 goto success;
6694 /* Parse bits. Must start with `static'. */
6695 expect_ident ("static");
6696 if (LA1 == XBM_TK_IDENT)
6698 if (strcmp (buffer, "unsigned") == 0)
6700 match ();
6701 expect_ident ("char");
6703 else if (strcmp (buffer, "short") == 0)
6705 match ();
6706 v10 = 1;
6707 if (*width % 16 && *width % 16 < 9)
6708 padding_p = 1;
6710 else if (strcmp (buffer, "char") == 0)
6711 match ();
6712 else
6713 goto failure;
6715 else
6716 goto failure;
6718 expect (XBM_TK_IDENT);
6719 expect ('[');
6720 expect (']');
6721 expect ('=');
6722 expect ('{');
6724 bytes_per_line = (*width + 7) / 8 + padding_p;
6725 nbytes = bytes_per_line * *height;
6726 p = *data = (char *) xmalloc (nbytes);
6728 if (v10)
6730 for (i = 0; i < nbytes; i += 2)
6732 int val = value;
6733 expect (XBM_TK_NUMBER);
6735 *p++ = val;
6736 if (!padding_p || ((i + 2) % bytes_per_line))
6737 *p++ = value >> 8;
6739 if (LA1 == ',' || LA1 == '}')
6740 match ();
6741 else
6742 goto failure;
6745 else
6747 for (i = 0; i < nbytes; ++i)
6749 int val = value;
6750 expect (XBM_TK_NUMBER);
6752 *p++ = val;
6754 if (LA1 == ',' || LA1 == '}')
6755 match ();
6756 else
6757 goto failure;
6761 success:
6762 return 1;
6764 failure:
6766 if (data && *data)
6768 xfree (*data);
6769 *data = NULL;
6771 return 0;
6773 #undef match
6774 #undef expect
6775 #undef expect_ident
6779 /* Load XBM image IMG which will be displayed on frame F from buffer
6780 CONTENTS. END is the end of the buffer. Value is non-zero if
6781 successful. */
6783 static int
6784 xbm_load_image (f, img, contents, end)
6785 struct frame *f;
6786 struct image *img;
6787 char *contents, *end;
6789 int rc;
6790 unsigned char *data;
6791 int success_p = 0;
6793 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6794 if (rc)
6796 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6797 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6798 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6799 Lisp_Object value;
6801 xassert (img->width > 0 && img->height > 0);
6803 /* Get foreground and background colors, maybe allocate colors. */
6804 value = image_spec_value (img->spec, QCforeground, NULL);
6805 if (!NILP (value))
6806 foreground = x_alloc_image_color (f, img, value, foreground);
6808 value = image_spec_value (img->spec, QCbackground, NULL);
6809 if (!NILP (value))
6810 background = x_alloc_image_color (f, img, value, background);
6812 img->pixmap
6813 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6814 FRAME_X_WINDOW (f),
6815 data,
6816 img->width, img->height,
6817 foreground, background,
6818 depth);
6819 xfree (data);
6821 if (img->pixmap == None)
6823 x_clear_image (f, img);
6824 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6826 else
6827 success_p = 1;
6829 else
6830 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6832 return success_p;
6836 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6838 static int
6839 xbm_file_p (data)
6840 Lisp_Object data;
6842 int w, h;
6843 return (STRINGP (data)
6844 && xbm_read_bitmap_data (XSTRING (data)->data,
6845 (XSTRING (data)->data
6846 + STRING_BYTES (XSTRING (data))),
6847 &w, &h, NULL));
6851 /* Fill image IMG which is used on frame F with pixmap data. Value is
6852 non-zero if successful. */
6854 static int
6855 xbm_load (f, img)
6856 struct frame *f;
6857 struct image *img;
6859 int success_p = 0;
6860 Lisp_Object file_name;
6862 xassert (xbm_image_p (img->spec));
6864 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6865 file_name = image_spec_value (img->spec, QCfile, NULL);
6866 if (STRINGP (file_name))
6868 Lisp_Object file;
6869 char *contents;
6870 int size;
6871 struct gcpro gcpro1;
6873 file = x_find_image_file (file_name);
6874 GCPRO1 (file);
6875 if (!STRINGP (file))
6877 image_error ("Cannot find image file `%s'", file_name, Qnil);
6878 UNGCPRO;
6879 return 0;
6882 contents = slurp_file (XSTRING (file)->data, &size);
6883 if (contents == NULL)
6885 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6886 UNGCPRO;
6887 return 0;
6890 success_p = xbm_load_image (f, img, contents, contents + size);
6891 UNGCPRO;
6893 else
6895 struct image_keyword fmt[XBM_LAST];
6896 Lisp_Object data;
6897 int depth;
6898 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6899 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6900 char *bits;
6901 int parsed_p;
6902 int in_memory_file_p = 0;
6904 /* See if data looks like an in-memory XBM file. */
6905 data = image_spec_value (img->spec, QCdata, NULL);
6906 in_memory_file_p = xbm_file_p (data);
6908 /* Parse the image specification. */
6909 bcopy (xbm_format, fmt, sizeof fmt);
6910 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6911 xassert (parsed_p);
6913 /* Get specified width, and height. */
6914 if (!in_memory_file_p)
6916 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6917 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6918 xassert (img->width > 0 && img->height > 0);
6921 /* Get foreground and background colors, maybe allocate colors. */
6922 if (fmt[XBM_FOREGROUND].count)
6923 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6924 foreground);
6925 if (fmt[XBM_BACKGROUND].count)
6926 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6927 background);
6929 if (in_memory_file_p)
6930 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6931 (XSTRING (data)->data
6932 + STRING_BYTES (XSTRING (data))));
6933 else
6935 if (VECTORP (data))
6937 int i;
6938 char *p;
6939 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6941 p = bits = (char *) alloca (nbytes * img->height);
6942 for (i = 0; i < img->height; ++i, p += nbytes)
6944 Lisp_Object line = XVECTOR (data)->contents[i];
6945 if (STRINGP (line))
6946 bcopy (XSTRING (line)->data, p, nbytes);
6947 else
6948 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6951 else if (STRINGP (data))
6952 bits = XSTRING (data)->data;
6953 else
6954 bits = XBOOL_VECTOR (data)->data;
6956 /* Create the pixmap. */
6957 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6958 img->pixmap
6959 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6960 FRAME_X_WINDOW (f),
6961 bits,
6962 img->width, img->height,
6963 foreground, background,
6964 depth);
6965 if (img->pixmap)
6966 success_p = 1;
6967 else
6969 image_error ("Unable to create pixmap for XBM image `%s'",
6970 img->spec, Qnil);
6971 x_clear_image (f, img);
6976 return success_p;
6981 /***********************************************************************
6982 XPM images
6983 ***********************************************************************/
6985 #if HAVE_XPM
6987 static int xpm_image_p P_ ((Lisp_Object object));
6988 static int xpm_load P_ ((struct frame *f, struct image *img));
6989 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6991 #include "X11/xpm.h"
6993 /* The symbol `xpm' identifying XPM-format images. */
6995 Lisp_Object Qxpm;
6997 /* Indices of image specification fields in xpm_format, below. */
6999 enum xpm_keyword_index
7001 XPM_TYPE,
7002 XPM_FILE,
7003 XPM_DATA,
7004 XPM_ASCENT,
7005 XPM_MARGIN,
7006 XPM_RELIEF,
7007 XPM_ALGORITHM,
7008 XPM_HEURISTIC_MASK,
7009 XPM_MASK,
7010 XPM_COLOR_SYMBOLS,
7011 XPM_LAST
7014 /* Vector of image_keyword structures describing the format
7015 of valid XPM image specifications. */
7017 static struct image_keyword xpm_format[XPM_LAST] =
7019 {":type", IMAGE_SYMBOL_VALUE, 1},
7020 {":file", IMAGE_STRING_VALUE, 0},
7021 {":data", IMAGE_STRING_VALUE, 0},
7022 {":ascent", IMAGE_ASCENT_VALUE, 0},
7023 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7024 {":relief", IMAGE_INTEGER_VALUE, 0},
7025 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7026 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7027 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7028 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7031 /* Structure describing the image type XBM. */
7033 static struct image_type xpm_type =
7035 &Qxpm,
7036 xpm_image_p,
7037 xpm_load,
7038 x_clear_image,
7039 NULL
7043 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7044 functions for allocating image colors. Our own functions handle
7045 color allocation failures more gracefully than the ones on the XPM
7046 lib. */
7048 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7049 #define ALLOC_XPM_COLORS
7050 #endif
7052 #ifdef ALLOC_XPM_COLORS
7054 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7055 static void xpm_free_color_cache P_ ((void));
7056 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7057 static int xpm_color_bucket P_ ((char *));
7058 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7059 XColor *, int));
7061 /* An entry in a hash table used to cache color definitions of named
7062 colors. This cache is necessary to speed up XPM image loading in
7063 case we do color allocations ourselves. Without it, we would need
7064 a call to XParseColor per pixel in the image. */
7066 struct xpm_cached_color
7068 /* Next in collision chain. */
7069 struct xpm_cached_color *next;
7071 /* Color definition (RGB and pixel color). */
7072 XColor color;
7074 /* Color name. */
7075 char name[1];
7078 /* The hash table used for the color cache, and its bucket vector
7079 size. */
7081 #define XPM_COLOR_CACHE_BUCKETS 1001
7082 struct xpm_cached_color **xpm_color_cache;
7084 /* Initialize the color cache. */
7086 static void
7087 xpm_init_color_cache (f, attrs)
7088 struct frame *f;
7089 XpmAttributes *attrs;
7091 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7092 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7093 memset (xpm_color_cache, 0, nbytes);
7094 init_color_table ();
7096 if (attrs->valuemask & XpmColorSymbols)
7098 int i;
7099 XColor color;
7101 for (i = 0; i < attrs->numsymbols; ++i)
7102 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7103 attrs->colorsymbols[i].value, &color))
7105 color.pixel = lookup_rgb_color (f, color.red, color.green,
7106 color.blue);
7107 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7113 /* Free the color cache. */
7115 static void
7116 xpm_free_color_cache ()
7118 struct xpm_cached_color *p, *next;
7119 int i;
7121 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7122 for (p = xpm_color_cache[i]; p; p = next)
7124 next = p->next;
7125 xfree (p);
7128 xfree (xpm_color_cache);
7129 xpm_color_cache = NULL;
7130 free_color_table ();
7134 /* Return the bucket index for color named COLOR_NAME in the color
7135 cache. */
7137 static int
7138 xpm_color_bucket (color_name)
7139 char *color_name;
7141 unsigned h = 0;
7142 char *s;
7144 for (s = color_name; *s; ++s)
7145 h = (h << 2) ^ *s;
7146 return h %= XPM_COLOR_CACHE_BUCKETS;
7150 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7151 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7152 entry added. */
7154 static struct xpm_cached_color *
7155 xpm_cache_color (f, color_name, color, bucket)
7156 struct frame *f;
7157 char *color_name;
7158 XColor *color;
7159 int bucket;
7161 size_t nbytes;
7162 struct xpm_cached_color *p;
7164 if (bucket < 0)
7165 bucket = xpm_color_bucket (color_name);
7167 nbytes = sizeof *p + strlen (color_name);
7168 p = (struct xpm_cached_color *) xmalloc (nbytes);
7169 strcpy (p->name, color_name);
7170 p->color = *color;
7171 p->next = xpm_color_cache[bucket];
7172 xpm_color_cache[bucket] = p;
7173 return p;
7177 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7178 return the cached definition in *COLOR. Otherwise, make a new
7179 entry in the cache and allocate the color. Value is zero if color
7180 allocation failed. */
7182 static int
7183 xpm_lookup_color (f, color_name, color)
7184 struct frame *f;
7185 char *color_name;
7186 XColor *color;
7188 struct xpm_cached_color *p;
7189 int h = xpm_color_bucket (color_name);
7191 for (p = xpm_color_cache[h]; p; p = p->next)
7192 if (strcmp (p->name, color_name) == 0)
7193 break;
7195 if (p != NULL)
7196 *color = p->color;
7197 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7198 color_name, color))
7200 color->pixel = lookup_rgb_color (f, color->red, color->green,
7201 color->blue);
7202 p = xpm_cache_color (f, color_name, color, h);
7205 return p != NULL;
7209 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7210 CLOSURE is a pointer to the frame on which we allocate the
7211 color. Return in *COLOR the allocated color. Value is non-zero
7212 if successful. */
7214 static int
7215 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7216 Display *dpy;
7217 Colormap cmap;
7218 char *color_name;
7219 XColor *color;
7220 void *closure;
7222 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7226 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7227 is a pointer to the frame on which we allocate the color. Value is
7228 non-zero if successful. */
7230 static int
7231 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7232 Display *dpy;
7233 Colormap cmap;
7234 Pixel *pixels;
7235 int npixels;
7236 void *closure;
7238 return 1;
7241 #endif /* ALLOC_XPM_COLORS */
7244 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7245 for XPM images. Such a list must consist of conses whose car and
7246 cdr are strings. */
7248 static int
7249 xpm_valid_color_symbols_p (color_symbols)
7250 Lisp_Object color_symbols;
7252 while (CONSP (color_symbols))
7254 Lisp_Object sym = XCAR (color_symbols);
7255 if (!CONSP (sym)
7256 || !STRINGP (XCAR (sym))
7257 || !STRINGP (XCDR (sym)))
7258 break;
7259 color_symbols = XCDR (color_symbols);
7262 return NILP (color_symbols);
7266 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7268 static int
7269 xpm_image_p (object)
7270 Lisp_Object object;
7272 struct image_keyword fmt[XPM_LAST];
7273 bcopy (xpm_format, fmt, sizeof fmt);
7274 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7275 /* Either `:file' or `:data' must be present. */
7276 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7277 /* Either no `:color-symbols' or it's a list of conses
7278 whose car and cdr are strings. */
7279 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7280 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7284 /* Load image IMG which will be displayed on frame F. Value is
7285 non-zero if successful. */
7287 static int
7288 xpm_load (f, img)
7289 struct frame *f;
7290 struct image *img;
7292 int rc;
7293 XpmAttributes attrs;
7294 Lisp_Object specified_file, color_symbols;
7296 /* Configure the XPM lib. Use the visual of frame F. Allocate
7297 close colors. Return colors allocated. */
7298 bzero (&attrs, sizeof attrs);
7299 attrs.visual = FRAME_X_VISUAL (f);
7300 attrs.colormap = FRAME_X_COLORMAP (f);
7301 attrs.valuemask |= XpmVisual;
7302 attrs.valuemask |= XpmColormap;
7304 #ifdef ALLOC_XPM_COLORS
7305 /* Allocate colors with our own functions which handle
7306 failing color allocation more gracefully. */
7307 attrs.color_closure = f;
7308 attrs.alloc_color = xpm_alloc_color;
7309 attrs.free_colors = xpm_free_colors;
7310 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7311 #else /* not ALLOC_XPM_COLORS */
7312 /* Let the XPM lib allocate colors. */
7313 attrs.valuemask |= XpmReturnAllocPixels;
7314 #ifdef XpmAllocCloseColors
7315 attrs.alloc_close_colors = 1;
7316 attrs.valuemask |= XpmAllocCloseColors;
7317 #else /* not XpmAllocCloseColors */
7318 attrs.closeness = 600;
7319 attrs.valuemask |= XpmCloseness;
7320 #endif /* not XpmAllocCloseColors */
7321 #endif /* ALLOC_XPM_COLORS */
7323 /* If image specification contains symbolic color definitions, add
7324 these to `attrs'. */
7325 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7326 if (CONSP (color_symbols))
7328 Lisp_Object tail;
7329 XpmColorSymbol *xpm_syms;
7330 int i, size;
7332 attrs.valuemask |= XpmColorSymbols;
7334 /* Count number of symbols. */
7335 attrs.numsymbols = 0;
7336 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7337 ++attrs.numsymbols;
7339 /* Allocate an XpmColorSymbol array. */
7340 size = attrs.numsymbols * sizeof *xpm_syms;
7341 xpm_syms = (XpmColorSymbol *) alloca (size);
7342 bzero (xpm_syms, size);
7343 attrs.colorsymbols = xpm_syms;
7345 /* Fill the color symbol array. */
7346 for (tail = color_symbols, i = 0;
7347 CONSP (tail);
7348 ++i, tail = XCDR (tail))
7350 Lisp_Object name = XCAR (XCAR (tail));
7351 Lisp_Object color = XCDR (XCAR (tail));
7352 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7353 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7354 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7355 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7359 /* Create a pixmap for the image, either from a file, or from a
7360 string buffer containing data in the same format as an XPM file. */
7361 #ifdef ALLOC_XPM_COLORS
7362 xpm_init_color_cache (f, &attrs);
7363 #endif
7365 specified_file = image_spec_value (img->spec, QCfile, NULL);
7366 if (STRINGP (specified_file))
7368 Lisp_Object file = x_find_image_file (specified_file);
7369 if (!STRINGP (file))
7371 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7372 return 0;
7375 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7376 XSTRING (file)->data, &img->pixmap, &img->mask,
7377 &attrs);
7379 else
7381 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7382 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7383 XSTRING (buffer)->data,
7384 &img->pixmap, &img->mask,
7385 &attrs);
7388 if (rc == XpmSuccess)
7390 #ifdef ALLOC_XPM_COLORS
7391 img->colors = colors_in_color_table (&img->ncolors);
7392 #else /* not ALLOC_XPM_COLORS */
7393 int i;
7395 img->ncolors = attrs.nalloc_pixels;
7396 img->colors = (unsigned long *) xmalloc (img->ncolors
7397 * sizeof *img->colors);
7398 for (i = 0; i < attrs.nalloc_pixels; ++i)
7400 img->colors[i] = attrs.alloc_pixels[i];
7401 #ifdef DEBUG_X_COLORS
7402 register_color (img->colors[i]);
7403 #endif
7405 #endif /* not ALLOC_XPM_COLORS */
7407 img->width = attrs.width;
7408 img->height = attrs.height;
7409 xassert (img->width > 0 && img->height > 0);
7411 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7412 XpmFreeAttributes (&attrs);
7414 else
7416 switch (rc)
7418 case XpmOpenFailed:
7419 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7420 break;
7422 case XpmFileInvalid:
7423 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7424 break;
7426 case XpmNoMemory:
7427 image_error ("Out of memory (%s)", img->spec, Qnil);
7428 break;
7430 case XpmColorFailed:
7431 image_error ("Color allocation error (%s)", img->spec, Qnil);
7432 break;
7434 default:
7435 image_error ("Unknown error (%s)", img->spec, Qnil);
7436 break;
7440 #ifdef ALLOC_XPM_COLORS
7441 xpm_free_color_cache ();
7442 #endif
7443 return rc == XpmSuccess;
7446 #endif /* HAVE_XPM != 0 */
7449 /***********************************************************************
7450 Color table
7451 ***********************************************************************/
7453 /* An entry in the color table mapping an RGB color to a pixel color. */
7455 struct ct_color
7457 int r, g, b;
7458 unsigned long pixel;
7460 /* Next in color table collision list. */
7461 struct ct_color *next;
7464 /* The bucket vector size to use. Must be prime. */
7466 #define CT_SIZE 101
7468 /* Value is a hash of the RGB color given by R, G, and B. */
7470 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7472 /* The color hash table. */
7474 struct ct_color **ct_table;
7476 /* Number of entries in the color table. */
7478 int ct_colors_allocated;
7480 /* Initialize the color table. */
7482 static void
7483 init_color_table ()
7485 int size = CT_SIZE * sizeof (*ct_table);
7486 ct_table = (struct ct_color **) xmalloc (size);
7487 bzero (ct_table, size);
7488 ct_colors_allocated = 0;
7492 /* Free memory associated with the color table. */
7494 static void
7495 free_color_table ()
7497 int i;
7498 struct ct_color *p, *next;
7500 for (i = 0; i < CT_SIZE; ++i)
7501 for (p = ct_table[i]; p; p = next)
7503 next = p->next;
7504 xfree (p);
7507 xfree (ct_table);
7508 ct_table = NULL;
7512 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7513 entry for that color already is in the color table, return the
7514 pixel color of that entry. Otherwise, allocate a new color for R,
7515 G, B, and make an entry in the color table. */
7517 static unsigned long
7518 lookup_rgb_color (f, r, g, b)
7519 struct frame *f;
7520 int r, g, b;
7522 unsigned hash = CT_HASH_RGB (r, g, b);
7523 int i = hash % CT_SIZE;
7524 struct ct_color *p;
7526 for (p = ct_table[i]; p; p = p->next)
7527 if (p->r == r && p->g == g && p->b == b)
7528 break;
7530 if (p == NULL)
7532 XColor color;
7533 Colormap cmap;
7534 int rc;
7536 color.red = r;
7537 color.green = g;
7538 color.blue = b;
7540 cmap = FRAME_X_COLORMAP (f);
7541 rc = x_alloc_nearest_color (f, cmap, &color);
7543 if (rc)
7545 ++ct_colors_allocated;
7547 p = (struct ct_color *) xmalloc (sizeof *p);
7548 p->r = r;
7549 p->g = g;
7550 p->b = b;
7551 p->pixel = color.pixel;
7552 p->next = ct_table[i];
7553 ct_table[i] = p;
7555 else
7556 return FRAME_FOREGROUND_PIXEL (f);
7559 return p->pixel;
7563 /* Look up pixel color PIXEL which is used on frame F in the color
7564 table. If not already present, allocate it. Value is PIXEL. */
7566 static unsigned long
7567 lookup_pixel_color (f, pixel)
7568 struct frame *f;
7569 unsigned long pixel;
7571 int i = pixel % CT_SIZE;
7572 struct ct_color *p;
7574 for (p = ct_table[i]; p; p = p->next)
7575 if (p->pixel == pixel)
7576 break;
7578 if (p == NULL)
7580 XColor color;
7581 Colormap cmap;
7582 int rc;
7584 cmap = FRAME_X_COLORMAP (f);
7585 color.pixel = pixel;
7586 x_query_color (f, &color);
7587 rc = x_alloc_nearest_color (f, cmap, &color);
7589 if (rc)
7591 ++ct_colors_allocated;
7593 p = (struct ct_color *) xmalloc (sizeof *p);
7594 p->r = color.red;
7595 p->g = color.green;
7596 p->b = color.blue;
7597 p->pixel = pixel;
7598 p->next = ct_table[i];
7599 ct_table[i] = p;
7601 else
7602 return FRAME_FOREGROUND_PIXEL (f);
7605 return p->pixel;
7609 /* Value is a vector of all pixel colors contained in the color table,
7610 allocated via xmalloc. Set *N to the number of colors. */
7612 static unsigned long *
7613 colors_in_color_table (n)
7614 int *n;
7616 int i, j;
7617 struct ct_color *p;
7618 unsigned long *colors;
7620 if (ct_colors_allocated == 0)
7622 *n = 0;
7623 colors = NULL;
7625 else
7627 colors = (unsigned long *) xmalloc (ct_colors_allocated
7628 * sizeof *colors);
7629 *n = ct_colors_allocated;
7631 for (i = j = 0; i < CT_SIZE; ++i)
7632 for (p = ct_table[i]; p; p = p->next)
7633 colors[j++] = p->pixel;
7636 return colors;
7641 /***********************************************************************
7642 Algorithms
7643 ***********************************************************************/
7645 static void x_laplace_write_row P_ ((struct frame *, long *,
7646 int, XImage *, int));
7647 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7648 XColor *, int, XImage *, int));
7649 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7650 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7651 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7653 /* Non-zero means draw a cross on images having `:conversion
7654 disabled'. */
7656 int cross_disabled_images;
7658 /* Edge detection matrices for different edge-detection
7659 strategies. */
7661 static int emboss_matrix[9] = {
7662 /* x - 1 x x + 1 */
7663 2, -1, 0, /* y - 1 */
7664 -1, 0, 1, /* y */
7665 0, 1, -2 /* y + 1 */
7668 static int laplace_matrix[9] = {
7669 /* x - 1 x x + 1 */
7670 1, 0, 0, /* y - 1 */
7671 0, 0, 0, /* y */
7672 0, 0, -1 /* y + 1 */
7675 /* Value is the intensity of the color whose red/green/blue values
7676 are R, G, and B. */
7678 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7681 /* On frame F, return an array of XColor structures describing image
7682 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7683 non-zero means also fill the red/green/blue members of the XColor
7684 structures. Value is a pointer to the array of XColors structures,
7685 allocated with xmalloc; it must be freed by the caller. */
7687 static XColor *
7688 x_to_xcolors (f, img, rgb_p)
7689 struct frame *f;
7690 struct image *img;
7691 int rgb_p;
7693 int x, y;
7694 XColor *colors, *p;
7695 XImage *ximg;
7697 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7699 /* Get the X image IMG->pixmap. */
7700 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7701 0, 0, img->width, img->height, ~0, ZPixmap);
7703 /* Fill the `pixel' members of the XColor array. I wished there
7704 were an easy and portable way to circumvent XGetPixel. */
7705 p = colors;
7706 for (y = 0; y < img->height; ++y)
7708 XColor *row = p;
7710 for (x = 0; x < img->width; ++x, ++p)
7711 p->pixel = XGetPixel (ximg, x, y);
7713 if (rgb_p)
7714 x_query_colors (f, row, img->width);
7717 XDestroyImage (ximg);
7718 return colors;
7722 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7723 RGB members are set. F is the frame on which this all happens.
7724 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7726 static void
7727 x_from_xcolors (f, img, colors)
7728 struct frame *f;
7729 struct image *img;
7730 XColor *colors;
7732 int x, y;
7733 XImage *oimg;
7734 Pixmap pixmap;
7735 XColor *p;
7737 init_color_table ();
7739 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7740 &oimg, &pixmap);
7741 p = colors;
7742 for (y = 0; y < img->height; ++y)
7743 for (x = 0; x < img->width; ++x, ++p)
7745 unsigned long pixel;
7746 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7747 XPutPixel (oimg, x, y, pixel);
7750 xfree (colors);
7751 x_clear_image_1 (f, img, 1, 0, 1);
7753 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7754 x_destroy_x_image (oimg);
7755 img->pixmap = pixmap;
7756 img->colors = colors_in_color_table (&img->ncolors);
7757 free_color_table ();
7761 /* On frame F, perform edge-detection on image IMG.
7763 MATRIX is a nine-element array specifying the transformation
7764 matrix. See emboss_matrix for an example.
7766 COLOR_ADJUST is a color adjustment added to each pixel of the
7767 outgoing image. */
7769 static void
7770 x_detect_edges (f, img, matrix, color_adjust)
7771 struct frame *f;
7772 struct image *img;
7773 int matrix[9], color_adjust;
7775 XColor *colors = x_to_xcolors (f, img, 1);
7776 XColor *new, *p;
7777 int x, y, i, sum;
7779 for (i = sum = 0; i < 9; ++i)
7780 sum += abs (matrix[i]);
7782 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7784 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
7786 for (y = 0; y < img->height; ++y)
7788 p = COLOR (new, 0, y);
7789 p->red = p->green = p->blue = 0xffff/2;
7790 p = COLOR (new, img->width - 1, y);
7791 p->red = p->green = p->blue = 0xffff/2;
7794 for (x = 1; x < img->width - 1; ++x)
7796 p = COLOR (new, x, 0);
7797 p->red = p->green = p->blue = 0xffff/2;
7798 p = COLOR (new, x, img->height - 1);
7799 p->red = p->green = p->blue = 0xffff/2;
7802 for (y = 1; y < img->height - 1; ++y)
7804 p = COLOR (new, 1, y);
7806 for (x = 1; x < img->width - 1; ++x, ++p)
7808 int r, g, b, y1, x1;
7810 r = g = b = i = 0;
7811 for (y1 = y - 1; y1 < y + 2; ++y1)
7812 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7813 if (matrix[i])
7815 XColor *t = COLOR (colors, x1, y1);
7816 r += matrix[i] * t->red;
7817 g += matrix[i] * t->green;
7818 b += matrix[i] * t->blue;
7821 r = (r / sum + color_adjust) & 0xffff;
7822 g = (g / sum + color_adjust) & 0xffff;
7823 b = (b / sum + color_adjust) & 0xffff;
7824 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7828 xfree (colors);
7829 x_from_xcolors (f, img, new);
7831 #undef COLOR
7835 /* Perform the pre-defined `emboss' edge-detection on image IMG
7836 on frame F. */
7838 static void
7839 x_emboss (f, img)
7840 struct frame *f;
7841 struct image *img;
7843 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7847 /* Perform the pre-defined `laplace' edge-detection on image IMG
7848 on frame F. */
7850 static void
7851 x_laplace (f, img)
7852 struct frame *f;
7853 struct image *img;
7855 x_detect_edges (f, img, laplace_matrix, 45000);
7859 /* Perform edge-detection on image IMG on frame F, with specified
7860 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7862 MATRIX must be either
7864 - a list of at least 9 numbers in row-major form
7865 - a vector of at least 9 numbers
7867 COLOR_ADJUST nil means use a default; otherwise it must be a
7868 number. */
7870 static void
7871 x_edge_detection (f, img, matrix, color_adjust)
7872 struct frame *f;
7873 struct image *img;
7874 Lisp_Object matrix, color_adjust;
7876 int i = 0;
7877 int trans[9];
7879 if (CONSP (matrix))
7881 for (i = 0;
7882 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7883 ++i, matrix = XCDR (matrix))
7884 trans[i] = XFLOATINT (XCAR (matrix));
7886 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7888 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7889 trans[i] = XFLOATINT (AREF (matrix, i));
7892 if (NILP (color_adjust))
7893 color_adjust = make_number (0xffff / 2);
7895 if (i == 9 && NUMBERP (color_adjust))
7896 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7900 /* Transform image IMG on frame F so that it looks disabled. */
7902 static void
7903 x_disable_image (f, img)
7904 struct frame *f;
7905 struct image *img;
7907 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7909 if (dpyinfo->n_planes >= 2)
7911 /* Color (or grayscale). Convert to gray, and equalize. Just
7912 drawing such images with a stipple can look very odd, so
7913 we're using this method instead. */
7914 XColor *colors = x_to_xcolors (f, img, 1);
7915 XColor *p, *end;
7916 const int h = 15000;
7917 const int l = 30000;
7919 for (p = colors, end = colors + img->width * img->height;
7920 p < end;
7921 ++p)
7923 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7924 int i2 = (0xffff - h - l) * i / 0xffff + l;
7925 p->red = p->green = p->blue = i2;
7928 x_from_xcolors (f, img, colors);
7931 /* Draw a cross over the disabled image, if we must or if we
7932 should. */
7933 if (dpyinfo->n_planes < 2 || cross_disabled_images)
7935 Display *dpy = FRAME_X_DISPLAY (f);
7936 GC gc;
7938 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
7939 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
7940 XDrawLine (dpy, img->pixmap, gc, 0, 0,
7941 img->width - 1, img->height - 1);
7942 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
7943 img->width - 1, 0);
7944 XFreeGC (dpy, gc);
7946 if (img->mask)
7948 gc = XCreateGC (dpy, img->mask, 0, NULL);
7949 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
7950 XDrawLine (dpy, img->mask, gc, 0, 0,
7951 img->width - 1, img->height - 1);
7952 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
7953 img->width - 1, 0);
7954 XFreeGC (dpy, gc);
7960 /* Build a mask for image IMG which is used on frame F. FILE is the
7961 name of an image file, for error messages. HOW determines how to
7962 determine the background color of IMG. If it is a list '(R G B)',
7963 with R, G, and B being integers >= 0, take that as the color of the
7964 background. Otherwise, determine the background color of IMG
7965 heuristically. Value is non-zero if successful. */
7967 static int
7968 x_build_heuristic_mask (f, img, how)
7969 struct frame *f;
7970 struct image *img;
7971 Lisp_Object how;
7973 Display *dpy = FRAME_X_DISPLAY (f);
7974 XImage *ximg, *mask_img;
7975 int x, y, rc, look_at_corners_p;
7976 unsigned long bg = 0;
7978 if (img->mask)
7980 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
7981 img->mask = None;
7984 /* Create an image and pixmap serving as mask. */
7985 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7986 &mask_img, &img->mask);
7987 if (!rc)
7988 return 0;
7990 /* Get the X image of IMG->pixmap. */
7991 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7992 ~0, ZPixmap);
7994 /* Determine the background color of ximg. If HOW is `(R G B)'
7995 take that as color. Otherwise, try to determine the color
7996 heuristically. */
7997 look_at_corners_p = 1;
7999 if (CONSP (how))
8001 int rgb[3], i = 0;
8003 while (i < 3
8004 && CONSP (how)
8005 && NATNUMP (XCAR (how)))
8007 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8008 how = XCDR (how);
8011 if (i == 3 && NILP (how))
8013 char color_name[30];
8014 XColor exact, color;
8015 Colormap cmap;
8017 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8019 cmap = FRAME_X_COLORMAP (f);
8020 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
8022 bg = color.pixel;
8023 look_at_corners_p = 0;
8028 if (look_at_corners_p)
8030 unsigned long corners[4];
8031 int i, best_count;
8033 /* Get the colors at the corners of ximg. */
8034 corners[0] = XGetPixel (ximg, 0, 0);
8035 corners[1] = XGetPixel (ximg, img->width - 1, 0);
8036 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
8037 corners[3] = XGetPixel (ximg, 0, img->height - 1);
8039 /* Choose the most frequently found color as background. */
8040 for (i = best_count = 0; i < 4; ++i)
8042 int j, n;
8044 for (j = n = 0; j < 4; ++j)
8045 if (corners[i] == corners[j])
8046 ++n;
8048 if (n > best_count)
8049 bg = corners[i], best_count = n;
8053 /* Set all bits in mask_img to 1 whose color in ximg is different
8054 from the background color bg. */
8055 for (y = 0; y < img->height; ++y)
8056 for (x = 0; x < img->width; ++x)
8057 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8059 /* Put mask_img into img->mask. */
8060 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8061 x_destroy_x_image (mask_img);
8062 XDestroyImage (ximg);
8064 return 1;
8069 /***********************************************************************
8070 PBM (mono, gray, color)
8071 ***********************************************************************/
8073 static int pbm_image_p P_ ((Lisp_Object object));
8074 static int pbm_load P_ ((struct frame *f, struct image *img));
8075 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8077 /* The symbol `pbm' identifying images of this type. */
8079 Lisp_Object Qpbm;
8081 /* Indices of image specification fields in gs_format, below. */
8083 enum pbm_keyword_index
8085 PBM_TYPE,
8086 PBM_FILE,
8087 PBM_DATA,
8088 PBM_ASCENT,
8089 PBM_MARGIN,
8090 PBM_RELIEF,
8091 PBM_ALGORITHM,
8092 PBM_HEURISTIC_MASK,
8093 PBM_MASK,
8094 PBM_FOREGROUND,
8095 PBM_BACKGROUND,
8096 PBM_LAST
8099 /* Vector of image_keyword structures describing the format
8100 of valid user-defined image specifications. */
8102 static struct image_keyword pbm_format[PBM_LAST] =
8104 {":type", IMAGE_SYMBOL_VALUE, 1},
8105 {":file", IMAGE_STRING_VALUE, 0},
8106 {":data", IMAGE_STRING_VALUE, 0},
8107 {":ascent", IMAGE_ASCENT_VALUE, 0},
8108 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8109 {":relief", IMAGE_INTEGER_VALUE, 0},
8110 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8111 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8112 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8113 {":foreground", IMAGE_STRING_VALUE, 0},
8114 {":background", IMAGE_STRING_VALUE, 0}
8117 /* Structure describing the image type `pbm'. */
8119 static struct image_type pbm_type =
8121 &Qpbm,
8122 pbm_image_p,
8123 pbm_load,
8124 x_clear_image,
8125 NULL
8129 /* Return non-zero if OBJECT is a valid PBM image specification. */
8131 static int
8132 pbm_image_p (object)
8133 Lisp_Object object;
8135 struct image_keyword fmt[PBM_LAST];
8137 bcopy (pbm_format, fmt, sizeof fmt);
8139 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8140 return 0;
8142 /* Must specify either :data or :file. */
8143 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8147 /* Scan a decimal number from *S and return it. Advance *S while
8148 reading the number. END is the end of the string. Value is -1 at
8149 end of input. */
8151 static int
8152 pbm_scan_number (s, end)
8153 unsigned char **s, *end;
8155 int c = 0, val = -1;
8157 while (*s < end)
8159 /* Skip white-space. */
8160 while (*s < end && (c = *(*s)++, isspace (c)))
8163 if (c == '#')
8165 /* Skip comment to end of line. */
8166 while (*s < end && (c = *(*s)++, c != '\n'))
8169 else if (isdigit (c))
8171 /* Read decimal number. */
8172 val = c - '0';
8173 while (*s < end && (c = *(*s)++, isdigit (c)))
8174 val = 10 * val + c - '0';
8175 break;
8177 else
8178 break;
8181 return val;
8185 /* Load PBM image IMG for use on frame F. */
8187 static int
8188 pbm_load (f, img)
8189 struct frame *f;
8190 struct image *img;
8192 int raw_p, x, y;
8193 int width, height, max_color_idx = 0;
8194 XImage *ximg;
8195 Lisp_Object file, specified_file;
8196 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8197 struct gcpro gcpro1;
8198 unsigned char *contents = NULL;
8199 unsigned char *end, *p;
8200 int size;
8202 specified_file = image_spec_value (img->spec, QCfile, NULL);
8203 file = Qnil;
8204 GCPRO1 (file);
8206 if (STRINGP (specified_file))
8208 file = x_find_image_file (specified_file);
8209 if (!STRINGP (file))
8211 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8212 UNGCPRO;
8213 return 0;
8216 contents = slurp_file (XSTRING (file)->data, &size);
8217 if (contents == NULL)
8219 image_error ("Error reading `%s'", file, Qnil);
8220 UNGCPRO;
8221 return 0;
8224 p = contents;
8225 end = contents + size;
8227 else
8229 Lisp_Object data;
8230 data = image_spec_value (img->spec, QCdata, NULL);
8231 p = XSTRING (data)->data;
8232 end = p + STRING_BYTES (XSTRING (data));
8235 /* Check magic number. */
8236 if (end - p < 2 || *p++ != 'P')
8238 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8239 error:
8240 xfree (contents);
8241 UNGCPRO;
8242 return 0;
8245 switch (*p++)
8247 case '1':
8248 raw_p = 0, type = PBM_MONO;
8249 break;
8251 case '2':
8252 raw_p = 0, type = PBM_GRAY;
8253 break;
8255 case '3':
8256 raw_p = 0, type = PBM_COLOR;
8257 break;
8259 case '4':
8260 raw_p = 1, type = PBM_MONO;
8261 break;
8263 case '5':
8264 raw_p = 1, type = PBM_GRAY;
8265 break;
8267 case '6':
8268 raw_p = 1, type = PBM_COLOR;
8269 break;
8271 default:
8272 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8273 goto error;
8276 /* Read width, height, maximum color-component. Characters
8277 starting with `#' up to the end of a line are ignored. */
8278 width = pbm_scan_number (&p, end);
8279 height = pbm_scan_number (&p, end);
8281 if (type != PBM_MONO)
8283 max_color_idx = pbm_scan_number (&p, end);
8284 if (raw_p && max_color_idx > 255)
8285 max_color_idx = 255;
8288 if (width < 0
8289 || height < 0
8290 || (type != PBM_MONO && max_color_idx < 0))
8291 goto error;
8293 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8294 &ximg, &img->pixmap))
8295 goto error;
8297 /* Initialize the color hash table. */
8298 init_color_table ();
8300 if (type == PBM_MONO)
8302 int c = 0, g;
8303 struct image_keyword fmt[PBM_LAST];
8304 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8305 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8307 /* Parse the image specification. */
8308 bcopy (pbm_format, fmt, sizeof fmt);
8309 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8311 /* Get foreground and background colors, maybe allocate colors. */
8312 if (fmt[PBM_FOREGROUND].count)
8313 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8314 if (fmt[PBM_BACKGROUND].count)
8315 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8317 for (y = 0; y < height; ++y)
8318 for (x = 0; x < width; ++x)
8320 if (raw_p)
8322 if ((x & 7) == 0)
8323 c = *p++;
8324 g = c & 0x80;
8325 c <<= 1;
8327 else
8328 g = pbm_scan_number (&p, end);
8330 XPutPixel (ximg, x, y, g ? fg : bg);
8333 else
8335 for (y = 0; y < height; ++y)
8336 for (x = 0; x < width; ++x)
8338 int r, g, b;
8340 if (type == PBM_GRAY)
8341 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8342 else if (raw_p)
8344 r = *p++;
8345 g = *p++;
8346 b = *p++;
8348 else
8350 r = pbm_scan_number (&p, end);
8351 g = pbm_scan_number (&p, end);
8352 b = pbm_scan_number (&p, end);
8355 if (r < 0 || g < 0 || b < 0)
8357 xfree (ximg->data);
8358 ximg->data = NULL;
8359 XDestroyImage (ximg);
8360 image_error ("Invalid pixel value in image `%s'",
8361 img->spec, Qnil);
8362 goto error;
8365 /* RGB values are now in the range 0..max_color_idx.
8366 Scale this to the range 0..0xffff supported by X. */
8367 r = (double) r * 65535 / max_color_idx;
8368 g = (double) g * 65535 / max_color_idx;
8369 b = (double) b * 65535 / max_color_idx;
8370 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8374 /* Store in IMG->colors the colors allocated for the image, and
8375 free the color table. */
8376 img->colors = colors_in_color_table (&img->ncolors);
8377 free_color_table ();
8379 /* Put the image into a pixmap. */
8380 x_put_x_image (f, ximg, img->pixmap, width, height);
8381 x_destroy_x_image (ximg);
8383 img->width = width;
8384 img->height = height;
8386 UNGCPRO;
8387 xfree (contents);
8388 return 1;
8393 /***********************************************************************
8395 ***********************************************************************/
8397 #if HAVE_PNG
8399 #include <png.h>
8401 /* Function prototypes. */
8403 static int png_image_p P_ ((Lisp_Object object));
8404 static int png_load P_ ((struct frame *f, struct image *img));
8406 /* The symbol `png' identifying images of this type. */
8408 Lisp_Object Qpng;
8410 /* Indices of image specification fields in png_format, below. */
8412 enum png_keyword_index
8414 PNG_TYPE,
8415 PNG_DATA,
8416 PNG_FILE,
8417 PNG_ASCENT,
8418 PNG_MARGIN,
8419 PNG_RELIEF,
8420 PNG_ALGORITHM,
8421 PNG_HEURISTIC_MASK,
8422 PNG_MASK,
8423 PNG_LAST
8426 /* Vector of image_keyword structures describing the format
8427 of valid user-defined image specifications. */
8429 static struct image_keyword png_format[PNG_LAST] =
8431 {":type", IMAGE_SYMBOL_VALUE, 1},
8432 {":data", IMAGE_STRING_VALUE, 0},
8433 {":file", IMAGE_STRING_VALUE, 0},
8434 {":ascent", IMAGE_ASCENT_VALUE, 0},
8435 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8436 {":relief", IMAGE_INTEGER_VALUE, 0},
8437 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8438 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8439 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8442 /* Structure describing the image type `png'. */
8444 static struct image_type png_type =
8446 &Qpng,
8447 png_image_p,
8448 png_load,
8449 x_clear_image,
8450 NULL
8454 /* Return non-zero if OBJECT is a valid PNG image specification. */
8456 static int
8457 png_image_p (object)
8458 Lisp_Object object;
8460 struct image_keyword fmt[PNG_LAST];
8461 bcopy (png_format, fmt, sizeof fmt);
8463 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8464 return 0;
8466 /* Must specify either the :data or :file keyword. */
8467 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8471 /* Error and warning handlers installed when the PNG library
8472 is initialized. */
8474 static void
8475 my_png_error (png_ptr, msg)
8476 png_struct *png_ptr;
8477 char *msg;
8479 xassert (png_ptr != NULL);
8480 image_error ("PNG error: %s", build_string (msg), Qnil);
8481 longjmp (png_ptr->jmpbuf, 1);
8485 static void
8486 my_png_warning (png_ptr, msg)
8487 png_struct *png_ptr;
8488 char *msg;
8490 xassert (png_ptr != NULL);
8491 image_error ("PNG warning: %s", build_string (msg), Qnil);
8494 /* Memory source for PNG decoding. */
8496 struct png_memory_storage
8498 unsigned char *bytes; /* The data */
8499 size_t len; /* How big is it? */
8500 int index; /* Where are we? */
8504 /* Function set as reader function when reading PNG image from memory.
8505 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8506 bytes from the input to DATA. */
8508 static void
8509 png_read_from_memory (png_ptr, data, length)
8510 png_structp png_ptr;
8511 png_bytep data;
8512 png_size_t length;
8514 struct png_memory_storage *tbr
8515 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8517 if (length > tbr->len - tbr->index)
8518 png_error (png_ptr, "Read error");
8520 bcopy (tbr->bytes + tbr->index, data, length);
8521 tbr->index = tbr->index + length;
8524 /* Load PNG image IMG for use on frame F. Value is non-zero if
8525 successful. */
8527 static int
8528 png_load (f, img)
8529 struct frame *f;
8530 struct image *img;
8532 Lisp_Object file, specified_file;
8533 Lisp_Object specified_data;
8534 int x, y, i;
8535 XImage *ximg, *mask_img = NULL;
8536 struct gcpro gcpro1;
8537 png_struct *png_ptr = NULL;
8538 png_info *info_ptr = NULL, *end_info = NULL;
8539 FILE *volatile fp = NULL;
8540 png_byte sig[8];
8541 png_byte * volatile pixels = NULL;
8542 png_byte ** volatile rows = NULL;
8543 png_uint_32 width, height;
8544 int bit_depth, color_type, interlace_type;
8545 png_byte channels;
8546 png_uint_32 row_bytes;
8547 int transparent_p;
8548 char *gamma_str;
8549 double screen_gamma, image_gamma;
8550 int intent;
8551 struct png_memory_storage tbr; /* Data to be read */
8553 /* Find out what file to load. */
8554 specified_file = image_spec_value (img->spec, QCfile, NULL);
8555 specified_data = image_spec_value (img->spec, QCdata, NULL);
8556 file = Qnil;
8557 GCPRO1 (file);
8559 if (NILP (specified_data))
8561 file = x_find_image_file (specified_file);
8562 if (!STRINGP (file))
8564 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8565 UNGCPRO;
8566 return 0;
8569 /* Open the image file. */
8570 fp = fopen (XSTRING (file)->data, "rb");
8571 if (!fp)
8573 image_error ("Cannot open image file `%s'", file, Qnil);
8574 UNGCPRO;
8575 fclose (fp);
8576 return 0;
8579 /* Check PNG signature. */
8580 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8581 || !png_check_sig (sig, sizeof sig))
8583 image_error ("Not a PNG file: `%s'", file, Qnil);
8584 UNGCPRO;
8585 fclose (fp);
8586 return 0;
8589 else
8591 /* Read from memory. */
8592 tbr.bytes = XSTRING (specified_data)->data;
8593 tbr.len = STRING_BYTES (XSTRING (specified_data));
8594 tbr.index = 0;
8596 /* Check PNG signature. */
8597 if (tbr.len < sizeof sig
8598 || !png_check_sig (tbr.bytes, sizeof sig))
8600 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8601 UNGCPRO;
8602 return 0;
8605 /* Need to skip past the signature. */
8606 tbr.bytes += sizeof (sig);
8609 /* Initialize read and info structs for PNG lib. */
8610 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8611 my_png_error, my_png_warning);
8612 if (!png_ptr)
8614 if (fp) fclose (fp);
8615 UNGCPRO;
8616 return 0;
8619 info_ptr = png_create_info_struct (png_ptr);
8620 if (!info_ptr)
8622 png_destroy_read_struct (&png_ptr, NULL, NULL);
8623 if (fp) fclose (fp);
8624 UNGCPRO;
8625 return 0;
8628 end_info = png_create_info_struct (png_ptr);
8629 if (!end_info)
8631 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8632 if (fp) fclose (fp);
8633 UNGCPRO;
8634 return 0;
8637 /* Set error jump-back. We come back here when the PNG library
8638 detects an error. */
8639 if (setjmp (png_ptr->jmpbuf))
8641 error:
8642 if (png_ptr)
8643 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8644 xfree (pixels);
8645 xfree (rows);
8646 if (fp) fclose (fp);
8647 UNGCPRO;
8648 return 0;
8651 /* Read image info. */
8652 if (!NILP (specified_data))
8653 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8654 else
8655 png_init_io (png_ptr, fp);
8657 png_set_sig_bytes (png_ptr, sizeof sig);
8658 png_read_info (png_ptr, info_ptr);
8659 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8660 &interlace_type, NULL, NULL);
8662 /* If image contains simply transparency data, we prefer to
8663 construct a clipping mask. */
8664 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8665 transparent_p = 1;
8666 else
8667 transparent_p = 0;
8669 /* This function is easier to write if we only have to handle
8670 one data format: RGB or RGBA with 8 bits per channel. Let's
8671 transform other formats into that format. */
8673 /* Strip more than 8 bits per channel. */
8674 if (bit_depth == 16)
8675 png_set_strip_16 (png_ptr);
8677 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8678 if available. */
8679 png_set_expand (png_ptr);
8681 /* Convert grayscale images to RGB. */
8682 if (color_type == PNG_COLOR_TYPE_GRAY
8683 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8684 png_set_gray_to_rgb (png_ptr);
8686 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8687 gamma_str = getenv ("SCREEN_GAMMA");
8688 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8690 /* Tell the PNG lib to handle gamma correction for us. */
8692 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8693 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8694 /* There is a special chunk in the image specifying the gamma. */
8695 png_set_sRGB (png_ptr, info_ptr, intent);
8696 else
8697 #endif
8698 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8699 /* Image contains gamma information. */
8700 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8701 else
8702 /* Use a default of 0.5 for the image gamma. */
8703 png_set_gamma (png_ptr, screen_gamma, 0.5);
8705 /* Handle alpha channel by combining the image with a background
8706 color. Do this only if a real alpha channel is supplied. For
8707 simple transparency, we prefer a clipping mask. */
8708 if (!transparent_p)
8710 png_color_16 *image_background;
8712 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8713 /* Image contains a background color with which to
8714 combine the image. */
8715 png_set_background (png_ptr, image_background,
8716 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8717 else
8719 /* Image does not contain a background color with which
8720 to combine the image data via an alpha channel. Use
8721 the frame's background instead. */
8722 XColor color;
8723 Colormap cmap;
8724 png_color_16 frame_background;
8726 cmap = FRAME_X_COLORMAP (f);
8727 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8728 x_query_color (f, &color);
8730 bzero (&frame_background, sizeof frame_background);
8731 frame_background.red = color.red;
8732 frame_background.green = color.green;
8733 frame_background.blue = color.blue;
8735 png_set_background (png_ptr, &frame_background,
8736 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8740 /* Update info structure. */
8741 png_read_update_info (png_ptr, info_ptr);
8743 /* Get number of channels. Valid values are 1 for grayscale images
8744 and images with a palette, 2 for grayscale images with transparency
8745 information (alpha channel), 3 for RGB images, and 4 for RGB
8746 images with alpha channel, i.e. RGBA. If conversions above were
8747 sufficient we should only have 3 or 4 channels here. */
8748 channels = png_get_channels (png_ptr, info_ptr);
8749 xassert (channels == 3 || channels == 4);
8751 /* Number of bytes needed for one row of the image. */
8752 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8754 /* Allocate memory for the image. */
8755 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8756 rows = (png_byte **) xmalloc (height * sizeof *rows);
8757 for (i = 0; i < height; ++i)
8758 rows[i] = pixels + i * row_bytes;
8760 /* Read the entire image. */
8761 png_read_image (png_ptr, rows);
8762 png_read_end (png_ptr, info_ptr);
8763 if (fp)
8765 fclose (fp);
8766 fp = NULL;
8769 /* Create the X image and pixmap. */
8770 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8771 &img->pixmap))
8772 goto error;
8774 /* Create an image and pixmap serving as mask if the PNG image
8775 contains an alpha channel. */
8776 if (channels == 4
8777 && !transparent_p
8778 && !x_create_x_image_and_pixmap (f, width, height, 1,
8779 &mask_img, &img->mask))
8781 x_destroy_x_image (ximg);
8782 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8783 img->pixmap = None;
8784 goto error;
8787 /* Fill the X image and mask from PNG data. */
8788 init_color_table ();
8790 for (y = 0; y < height; ++y)
8792 png_byte *p = rows[y];
8794 for (x = 0; x < width; ++x)
8796 unsigned r, g, b;
8798 r = *p++ << 8;
8799 g = *p++ << 8;
8800 b = *p++ << 8;
8801 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8803 /* An alpha channel, aka mask channel, associates variable
8804 transparency with an image. Where other image formats
8805 support binary transparency---fully transparent or fully
8806 opaque---PNG allows up to 254 levels of partial transparency.
8807 The PNG library implements partial transparency by combining
8808 the image with a specified background color.
8810 I'm not sure how to handle this here nicely: because the
8811 background on which the image is displayed may change, for
8812 real alpha channel support, it would be necessary to create
8813 a new image for each possible background.
8815 What I'm doing now is that a mask is created if we have
8816 boolean transparency information. Otherwise I'm using
8817 the frame's background color to combine the image with. */
8819 if (channels == 4)
8821 if (mask_img)
8822 XPutPixel (mask_img, x, y, *p > 0);
8823 ++p;
8828 /* Remember colors allocated for this image. */
8829 img->colors = colors_in_color_table (&img->ncolors);
8830 free_color_table ();
8832 /* Clean up. */
8833 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8834 xfree (rows);
8835 xfree (pixels);
8837 img->width = width;
8838 img->height = height;
8840 /* Put the image into the pixmap, then free the X image and its buffer. */
8841 x_put_x_image (f, ximg, img->pixmap, width, height);
8842 x_destroy_x_image (ximg);
8844 /* Same for the mask. */
8845 if (mask_img)
8847 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8848 x_destroy_x_image (mask_img);
8851 UNGCPRO;
8852 return 1;
8855 #endif /* HAVE_PNG != 0 */
8859 /***********************************************************************
8860 JPEG
8861 ***********************************************************************/
8863 #if HAVE_JPEG
8865 /* Work around a warning about HAVE_STDLIB_H being redefined in
8866 jconfig.h. */
8867 #ifdef HAVE_STDLIB_H
8868 #define HAVE_STDLIB_H_1
8869 #undef HAVE_STDLIB_H
8870 #endif /* HAVE_STLIB_H */
8872 #include <jpeglib.h>
8873 #include <jerror.h>
8874 #include <setjmp.h>
8876 #ifdef HAVE_STLIB_H_1
8877 #define HAVE_STDLIB_H 1
8878 #endif
8880 static int jpeg_image_p P_ ((Lisp_Object object));
8881 static int jpeg_load P_ ((struct frame *f, struct image *img));
8883 /* The symbol `jpeg' identifying images of this type. */
8885 Lisp_Object Qjpeg;
8887 /* Indices of image specification fields in gs_format, below. */
8889 enum jpeg_keyword_index
8891 JPEG_TYPE,
8892 JPEG_DATA,
8893 JPEG_FILE,
8894 JPEG_ASCENT,
8895 JPEG_MARGIN,
8896 JPEG_RELIEF,
8897 JPEG_ALGORITHM,
8898 JPEG_HEURISTIC_MASK,
8899 JPEG_MASK,
8900 JPEG_LAST
8903 /* Vector of image_keyword structures describing the format
8904 of valid user-defined image specifications. */
8906 static struct image_keyword jpeg_format[JPEG_LAST] =
8908 {":type", IMAGE_SYMBOL_VALUE, 1},
8909 {":data", IMAGE_STRING_VALUE, 0},
8910 {":file", IMAGE_STRING_VALUE, 0},
8911 {":ascent", IMAGE_ASCENT_VALUE, 0},
8912 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8913 {":relief", IMAGE_INTEGER_VALUE, 0},
8914 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8915 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8916 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8919 /* Structure describing the image type `jpeg'. */
8921 static struct image_type jpeg_type =
8923 &Qjpeg,
8924 jpeg_image_p,
8925 jpeg_load,
8926 x_clear_image,
8927 NULL
8931 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8933 static int
8934 jpeg_image_p (object)
8935 Lisp_Object object;
8937 struct image_keyword fmt[JPEG_LAST];
8939 bcopy (jpeg_format, fmt, sizeof fmt);
8941 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8942 return 0;
8944 /* Must specify either the :data or :file keyword. */
8945 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8949 struct my_jpeg_error_mgr
8951 struct jpeg_error_mgr pub;
8952 jmp_buf setjmp_buffer;
8956 static void
8957 my_error_exit (cinfo)
8958 j_common_ptr cinfo;
8960 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8961 longjmp (mgr->setjmp_buffer, 1);
8965 /* Init source method for JPEG data source manager. Called by
8966 jpeg_read_header() before any data is actually read. See
8967 libjpeg.doc from the JPEG lib distribution. */
8969 static void
8970 our_init_source (cinfo)
8971 j_decompress_ptr cinfo;
8976 /* Fill input buffer method for JPEG data source manager. Called
8977 whenever more data is needed. We read the whole image in one step,
8978 so this only adds a fake end of input marker at the end. */
8980 static boolean
8981 our_fill_input_buffer (cinfo)
8982 j_decompress_ptr cinfo;
8984 /* Insert a fake EOI marker. */
8985 struct jpeg_source_mgr *src = cinfo->src;
8986 static JOCTET buffer[2];
8988 buffer[0] = (JOCTET) 0xFF;
8989 buffer[1] = (JOCTET) JPEG_EOI;
8991 src->next_input_byte = buffer;
8992 src->bytes_in_buffer = 2;
8993 return TRUE;
8997 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8998 is the JPEG data source manager. */
9000 static void
9001 our_skip_input_data (cinfo, num_bytes)
9002 j_decompress_ptr cinfo;
9003 long num_bytes;
9005 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9007 if (src)
9009 if (num_bytes > src->bytes_in_buffer)
9010 ERREXIT (cinfo, JERR_INPUT_EOF);
9012 src->bytes_in_buffer -= num_bytes;
9013 src->next_input_byte += num_bytes;
9018 /* Method to terminate data source. Called by
9019 jpeg_finish_decompress() after all data has been processed. */
9021 static void
9022 our_term_source (cinfo)
9023 j_decompress_ptr cinfo;
9028 /* Set up the JPEG lib for reading an image from DATA which contains
9029 LEN bytes. CINFO is the decompression info structure created for
9030 reading the image. */
9032 static void
9033 jpeg_memory_src (cinfo, data, len)
9034 j_decompress_ptr cinfo;
9035 JOCTET *data;
9036 unsigned int len;
9038 struct jpeg_source_mgr *src;
9040 if (cinfo->src == NULL)
9042 /* First time for this JPEG object? */
9043 cinfo->src = (struct jpeg_source_mgr *)
9044 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9045 sizeof (struct jpeg_source_mgr));
9046 src = (struct jpeg_source_mgr *) cinfo->src;
9047 src->next_input_byte = data;
9050 src = (struct jpeg_source_mgr *) cinfo->src;
9051 src->init_source = our_init_source;
9052 src->fill_input_buffer = our_fill_input_buffer;
9053 src->skip_input_data = our_skip_input_data;
9054 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9055 src->term_source = our_term_source;
9056 src->bytes_in_buffer = len;
9057 src->next_input_byte = data;
9061 /* Load image IMG for use on frame F. Patterned after example.c
9062 from the JPEG lib. */
9064 static int
9065 jpeg_load (f, img)
9066 struct frame *f;
9067 struct image *img;
9069 struct jpeg_decompress_struct cinfo;
9070 struct my_jpeg_error_mgr mgr;
9071 Lisp_Object file, specified_file;
9072 Lisp_Object specified_data;
9073 FILE * volatile fp = NULL;
9074 JSAMPARRAY buffer;
9075 int row_stride, x, y;
9076 XImage *ximg = NULL;
9077 int rc;
9078 unsigned long *colors;
9079 int width, height;
9080 struct gcpro gcpro1;
9082 /* Open the JPEG file. */
9083 specified_file = image_spec_value (img->spec, QCfile, NULL);
9084 specified_data = image_spec_value (img->spec, QCdata, NULL);
9085 file = Qnil;
9086 GCPRO1 (file);
9088 if (NILP (specified_data))
9090 file = x_find_image_file (specified_file);
9091 if (!STRINGP (file))
9093 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9094 UNGCPRO;
9095 return 0;
9098 fp = fopen (XSTRING (file)->data, "r");
9099 if (fp == NULL)
9101 image_error ("Cannot open `%s'", file, Qnil);
9102 UNGCPRO;
9103 return 0;
9107 /* Customize libjpeg's error handling to call my_error_exit when an
9108 error is detected. This function will perform a longjmp. */
9109 cinfo.err = jpeg_std_error (&mgr.pub);
9110 mgr.pub.error_exit = my_error_exit;
9112 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9114 if (rc == 1)
9116 /* Called from my_error_exit. Display a JPEG error. */
9117 char buffer[JMSG_LENGTH_MAX];
9118 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9119 image_error ("Error reading JPEG image `%s': %s", img->spec,
9120 build_string (buffer));
9123 /* Close the input file and destroy the JPEG object. */
9124 if (fp)
9125 fclose ((FILE *) fp);
9126 jpeg_destroy_decompress (&cinfo);
9128 /* If we already have an XImage, free that. */
9129 x_destroy_x_image (ximg);
9131 /* Free pixmap and colors. */
9132 x_clear_image (f, img);
9134 UNGCPRO;
9135 return 0;
9138 /* Create the JPEG decompression object. Let it read from fp.
9139 Read the JPEG image header. */
9140 jpeg_create_decompress (&cinfo);
9142 if (NILP (specified_data))
9143 jpeg_stdio_src (&cinfo, (FILE *) fp);
9144 else
9145 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
9146 STRING_BYTES (XSTRING (specified_data)));
9148 jpeg_read_header (&cinfo, TRUE);
9150 /* Customize decompression so that color quantization will be used.
9151 Start decompression. */
9152 cinfo.quantize_colors = TRUE;
9153 jpeg_start_decompress (&cinfo);
9154 width = img->width = cinfo.output_width;
9155 height = img->height = cinfo.output_height;
9157 /* Create X image and pixmap. */
9158 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9159 longjmp (mgr.setjmp_buffer, 2);
9161 /* Allocate colors. When color quantization is used,
9162 cinfo.actual_number_of_colors has been set with the number of
9163 colors generated, and cinfo.colormap is a two-dimensional array
9164 of color indices in the range 0..cinfo.actual_number_of_colors.
9165 No more than 255 colors will be generated. */
9167 int i, ir, ig, ib;
9169 if (cinfo.out_color_components > 2)
9170 ir = 0, ig = 1, ib = 2;
9171 else if (cinfo.out_color_components > 1)
9172 ir = 0, ig = 1, ib = 0;
9173 else
9174 ir = 0, ig = 0, ib = 0;
9176 /* Use the color table mechanism because it handles colors that
9177 cannot be allocated nicely. Such colors will be replaced with
9178 a default color, and we don't have to care about which colors
9179 can be freed safely, and which can't. */
9180 init_color_table ();
9181 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9182 * sizeof *colors);
9184 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9186 /* Multiply RGB values with 255 because X expects RGB values
9187 in the range 0..0xffff. */
9188 int r = cinfo.colormap[ir][i] << 8;
9189 int g = cinfo.colormap[ig][i] << 8;
9190 int b = cinfo.colormap[ib][i] << 8;
9191 colors[i] = lookup_rgb_color (f, r, g, b);
9194 /* Remember those colors actually allocated. */
9195 img->colors = colors_in_color_table (&img->ncolors);
9196 free_color_table ();
9199 /* Read pixels. */
9200 row_stride = width * cinfo.output_components;
9201 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9202 row_stride, 1);
9203 for (y = 0; y < height; ++y)
9205 jpeg_read_scanlines (&cinfo, buffer, 1);
9206 for (x = 0; x < cinfo.output_width; ++x)
9207 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9210 /* Clean up. */
9211 jpeg_finish_decompress (&cinfo);
9212 jpeg_destroy_decompress (&cinfo);
9213 if (fp)
9214 fclose ((FILE *) fp);
9216 /* Put the image into the pixmap. */
9217 x_put_x_image (f, ximg, img->pixmap, width, height);
9218 x_destroy_x_image (ximg);
9219 UNGCPRO;
9220 return 1;
9223 #endif /* HAVE_JPEG */
9227 /***********************************************************************
9228 TIFF
9229 ***********************************************************************/
9231 #if HAVE_TIFF
9233 #include <tiffio.h>
9235 static int tiff_image_p P_ ((Lisp_Object object));
9236 static int tiff_load P_ ((struct frame *f, struct image *img));
9238 /* The symbol `tiff' identifying images of this type. */
9240 Lisp_Object Qtiff;
9242 /* Indices of image specification fields in tiff_format, below. */
9244 enum tiff_keyword_index
9246 TIFF_TYPE,
9247 TIFF_DATA,
9248 TIFF_FILE,
9249 TIFF_ASCENT,
9250 TIFF_MARGIN,
9251 TIFF_RELIEF,
9252 TIFF_ALGORITHM,
9253 TIFF_HEURISTIC_MASK,
9254 TIFF_MASK,
9255 TIFF_LAST
9258 /* Vector of image_keyword structures describing the format
9259 of valid user-defined image specifications. */
9261 static struct image_keyword tiff_format[TIFF_LAST] =
9263 {":type", IMAGE_SYMBOL_VALUE, 1},
9264 {":data", IMAGE_STRING_VALUE, 0},
9265 {":file", IMAGE_STRING_VALUE, 0},
9266 {":ascent", IMAGE_ASCENT_VALUE, 0},
9267 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9268 {":relief", IMAGE_INTEGER_VALUE, 0},
9269 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9270 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9271 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9274 /* Structure describing the image type `tiff'. */
9276 static struct image_type tiff_type =
9278 &Qtiff,
9279 tiff_image_p,
9280 tiff_load,
9281 x_clear_image,
9282 NULL
9286 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9288 static int
9289 tiff_image_p (object)
9290 Lisp_Object object;
9292 struct image_keyword fmt[TIFF_LAST];
9293 bcopy (tiff_format, fmt, sizeof fmt);
9295 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9296 return 0;
9298 /* Must specify either the :data or :file keyword. */
9299 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9303 /* Reading from a memory buffer for TIFF images Based on the PNG
9304 memory source, but we have to provide a lot of extra functions.
9305 Blah.
9307 We really only need to implement read and seek, but I am not
9308 convinced that the TIFF library is smart enough not to destroy
9309 itself if we only hand it the function pointers we need to
9310 override. */
9312 typedef struct
9314 unsigned char *bytes;
9315 size_t len;
9316 int index;
9318 tiff_memory_source;
9321 static size_t
9322 tiff_read_from_memory (data, buf, size)
9323 thandle_t data;
9324 tdata_t buf;
9325 tsize_t size;
9327 tiff_memory_source *src = (tiff_memory_source *) data;
9329 if (size > src->len - src->index)
9330 return (size_t) -1;
9331 bcopy (src->bytes + src->index, buf, size);
9332 src->index += size;
9333 return size;
9337 static size_t
9338 tiff_write_from_memory (data, buf, size)
9339 thandle_t data;
9340 tdata_t buf;
9341 tsize_t size;
9343 return (size_t) -1;
9347 static toff_t
9348 tiff_seek_in_memory (data, off, whence)
9349 thandle_t data;
9350 toff_t off;
9351 int whence;
9353 tiff_memory_source *src = (tiff_memory_source *) data;
9354 int idx;
9356 switch (whence)
9358 case SEEK_SET: /* Go from beginning of source. */
9359 idx = off;
9360 break;
9362 case SEEK_END: /* Go from end of source. */
9363 idx = src->len + off;
9364 break;
9366 case SEEK_CUR: /* Go from current position. */
9367 idx = src->index + off;
9368 break;
9370 default: /* Invalid `whence'. */
9371 return -1;
9374 if (idx > src->len || idx < 0)
9375 return -1;
9377 src->index = idx;
9378 return src->index;
9382 static int
9383 tiff_close_memory (data)
9384 thandle_t data;
9386 /* NOOP */
9387 return 0;
9391 static int
9392 tiff_mmap_memory (data, pbase, psize)
9393 thandle_t data;
9394 tdata_t *pbase;
9395 toff_t *psize;
9397 /* It is already _IN_ memory. */
9398 return 0;
9402 static void
9403 tiff_unmap_memory (data, base, size)
9404 thandle_t data;
9405 tdata_t base;
9406 toff_t size;
9408 /* We don't need to do this. */
9412 static toff_t
9413 tiff_size_of_memory (data)
9414 thandle_t data;
9416 return ((tiff_memory_source *) data)->len;
9420 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9421 successful. */
9423 static int
9424 tiff_load (f, img)
9425 struct frame *f;
9426 struct image *img;
9428 Lisp_Object file, specified_file;
9429 Lisp_Object specified_data;
9430 TIFF *tiff;
9431 int width, height, x, y;
9432 uint32 *buf;
9433 int rc;
9434 XImage *ximg;
9435 struct gcpro gcpro1;
9436 tiff_memory_source memsrc;
9438 specified_file = image_spec_value (img->spec, QCfile, NULL);
9439 specified_data = image_spec_value (img->spec, QCdata, NULL);
9440 file = Qnil;
9441 GCPRO1 (file);
9443 if (NILP (specified_data))
9445 /* Read from a file */
9446 file = x_find_image_file (specified_file);
9447 if (!STRINGP (file))
9449 image_error ("Cannot find image file `%s'", file, Qnil);
9450 UNGCPRO;
9451 return 0;
9454 /* Try to open the image file. */
9455 tiff = TIFFOpen (XSTRING (file)->data, "r");
9456 if (tiff == NULL)
9458 image_error ("Cannot open `%s'", file, Qnil);
9459 UNGCPRO;
9460 return 0;
9463 else
9465 /* Memory source! */
9466 memsrc.bytes = XSTRING (specified_data)->data;
9467 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9468 memsrc.index = 0;
9470 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9471 (TIFFReadWriteProc) tiff_read_from_memory,
9472 (TIFFReadWriteProc) tiff_write_from_memory,
9473 tiff_seek_in_memory,
9474 tiff_close_memory,
9475 tiff_size_of_memory,
9476 tiff_mmap_memory,
9477 tiff_unmap_memory);
9479 if (!tiff)
9481 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9482 UNGCPRO;
9483 return 0;
9487 /* Get width and height of the image, and allocate a raster buffer
9488 of width x height 32-bit values. */
9489 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9490 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9491 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9493 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9494 TIFFClose (tiff);
9495 if (!rc)
9497 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9498 xfree (buf);
9499 UNGCPRO;
9500 return 0;
9503 /* Create the X image and pixmap. */
9504 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9506 xfree (buf);
9507 UNGCPRO;
9508 return 0;
9511 /* Initialize the color table. */
9512 init_color_table ();
9514 /* Process the pixel raster. Origin is in the lower-left corner. */
9515 for (y = 0; y < height; ++y)
9517 uint32 *row = buf + y * width;
9519 for (x = 0; x < width; ++x)
9521 uint32 abgr = row[x];
9522 int r = TIFFGetR (abgr) << 8;
9523 int g = TIFFGetG (abgr) << 8;
9524 int b = TIFFGetB (abgr) << 8;
9525 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9529 /* Remember the colors allocated for the image. Free the color table. */
9530 img->colors = colors_in_color_table (&img->ncolors);
9531 free_color_table ();
9533 /* Put the image into the pixmap, then free the X image and its buffer. */
9534 x_put_x_image (f, ximg, img->pixmap, width, height);
9535 x_destroy_x_image (ximg);
9536 xfree (buf);
9538 img->width = width;
9539 img->height = height;
9541 UNGCPRO;
9542 return 1;
9545 #endif /* HAVE_TIFF != 0 */
9549 /***********************************************************************
9551 ***********************************************************************/
9553 #if HAVE_GIF
9555 #include <gif_lib.h>
9557 static int gif_image_p P_ ((Lisp_Object object));
9558 static int gif_load P_ ((struct frame *f, struct image *img));
9560 /* The symbol `gif' identifying images of this type. */
9562 Lisp_Object Qgif;
9564 /* Indices of image specification fields in gif_format, below. */
9566 enum gif_keyword_index
9568 GIF_TYPE,
9569 GIF_DATA,
9570 GIF_FILE,
9571 GIF_ASCENT,
9572 GIF_MARGIN,
9573 GIF_RELIEF,
9574 GIF_ALGORITHM,
9575 GIF_HEURISTIC_MASK,
9576 GIF_MASK,
9577 GIF_IMAGE,
9578 GIF_LAST
9581 /* Vector of image_keyword structures describing the format
9582 of valid user-defined image specifications. */
9584 static struct image_keyword gif_format[GIF_LAST] =
9586 {":type", IMAGE_SYMBOL_VALUE, 1},
9587 {":data", IMAGE_STRING_VALUE, 0},
9588 {":file", IMAGE_STRING_VALUE, 0},
9589 {":ascent", IMAGE_ASCENT_VALUE, 0},
9590 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9591 {":relief", IMAGE_INTEGER_VALUE, 0},
9592 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9593 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9594 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9595 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9598 /* Structure describing the image type `gif'. */
9600 static struct image_type gif_type =
9602 &Qgif,
9603 gif_image_p,
9604 gif_load,
9605 x_clear_image,
9606 NULL
9610 /* Return non-zero if OBJECT is a valid GIF image specification. */
9612 static int
9613 gif_image_p (object)
9614 Lisp_Object object;
9616 struct image_keyword fmt[GIF_LAST];
9617 bcopy (gif_format, fmt, sizeof fmt);
9619 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9620 return 0;
9622 /* Must specify either the :data or :file keyword. */
9623 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9627 /* Reading a GIF image from memory
9628 Based on the PNG memory stuff to a certain extent. */
9630 typedef struct
9632 unsigned char *bytes;
9633 size_t len;
9634 int index;
9636 gif_memory_source;
9639 /* Make the current memory source available to gif_read_from_memory.
9640 It's done this way because not all versions of libungif support
9641 a UserData field in the GifFileType structure. */
9642 static gif_memory_source *current_gif_memory_src;
9644 static int
9645 gif_read_from_memory (file, buf, len)
9646 GifFileType *file;
9647 GifByteType *buf;
9648 int len;
9650 gif_memory_source *src = current_gif_memory_src;
9652 if (len > src->len - src->index)
9653 return -1;
9655 bcopy (src->bytes + src->index, buf, len);
9656 src->index += len;
9657 return len;
9661 /* Load GIF image IMG for use on frame F. Value is non-zero if
9662 successful. */
9664 static int
9665 gif_load (f, img)
9666 struct frame *f;
9667 struct image *img;
9669 Lisp_Object file, specified_file;
9670 Lisp_Object specified_data;
9671 int rc, width, height, x, y, i;
9672 XImage *ximg;
9673 ColorMapObject *gif_color_map;
9674 unsigned long pixel_colors[256];
9675 GifFileType *gif;
9676 struct gcpro gcpro1;
9677 Lisp_Object image;
9678 int ino, image_left, image_top, image_width, image_height;
9679 gif_memory_source memsrc;
9680 unsigned char *raster;
9682 specified_file = image_spec_value (img->spec, QCfile, NULL);
9683 specified_data = image_spec_value (img->spec, QCdata, NULL);
9684 file = Qnil;
9685 GCPRO1 (file);
9687 if (NILP (specified_data))
9689 file = x_find_image_file (specified_file);
9690 if (!STRINGP (file))
9692 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9693 UNGCPRO;
9694 return 0;
9697 /* Open the GIF file. */
9698 gif = DGifOpenFileName (XSTRING (file)->data);
9699 if (gif == NULL)
9701 image_error ("Cannot open `%s'", file, Qnil);
9702 UNGCPRO;
9703 return 0;
9706 else
9708 /* Read from memory! */
9709 current_gif_memory_src = &memsrc;
9710 memsrc.bytes = XSTRING (specified_data)->data;
9711 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9712 memsrc.index = 0;
9714 gif = DGifOpen(&memsrc, gif_read_from_memory);
9715 if (!gif)
9717 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9718 UNGCPRO;
9719 return 0;
9723 /* Read entire contents. */
9724 rc = DGifSlurp (gif);
9725 if (rc == GIF_ERROR)
9727 image_error ("Error reading `%s'", img->spec, Qnil);
9728 DGifCloseFile (gif);
9729 UNGCPRO;
9730 return 0;
9733 image = image_spec_value (img->spec, QCindex, NULL);
9734 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9735 if (ino >= gif->ImageCount)
9737 image_error ("Invalid image number `%s' in image `%s'",
9738 image, img->spec);
9739 DGifCloseFile (gif);
9740 UNGCPRO;
9741 return 0;
9744 width = img->width = gif->SWidth;
9745 height = img->height = gif->SHeight;
9747 /* Create the X image and pixmap. */
9748 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9750 DGifCloseFile (gif);
9751 UNGCPRO;
9752 return 0;
9755 /* Allocate colors. */
9756 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9757 if (!gif_color_map)
9758 gif_color_map = gif->SColorMap;
9759 init_color_table ();
9760 bzero (pixel_colors, sizeof pixel_colors);
9762 for (i = 0; i < gif_color_map->ColorCount; ++i)
9764 int r = gif_color_map->Colors[i].Red << 8;
9765 int g = gif_color_map->Colors[i].Green << 8;
9766 int b = gif_color_map->Colors[i].Blue << 8;
9767 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9770 img->colors = colors_in_color_table (&img->ncolors);
9771 free_color_table ();
9773 /* Clear the part of the screen image that are not covered by
9774 the image from the GIF file. Full animated GIF support
9775 requires more than can be done here (see the gif89 spec,
9776 disposal methods). Let's simply assume that the part
9777 not covered by a sub-image is in the frame's background color. */
9778 image_top = gif->SavedImages[ino].ImageDesc.Top;
9779 image_left = gif->SavedImages[ino].ImageDesc.Left;
9780 image_width = gif->SavedImages[ino].ImageDesc.Width;
9781 image_height = gif->SavedImages[ino].ImageDesc.Height;
9783 for (y = 0; y < image_top; ++y)
9784 for (x = 0; x < width; ++x)
9785 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9787 for (y = image_top + image_height; y < height; ++y)
9788 for (x = 0; x < width; ++x)
9789 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9791 for (y = image_top; y < image_top + image_height; ++y)
9793 for (x = 0; x < image_left; ++x)
9794 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9795 for (x = image_left + image_width; x < width; ++x)
9796 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9799 /* Read the GIF image into the X image. We use a local variable
9800 `raster' here because RasterBits below is a char *, and invites
9801 problems with bytes >= 0x80. */
9802 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9804 if (gif->SavedImages[ino].ImageDesc.Interlace)
9806 static int interlace_start[] = {0, 4, 2, 1};
9807 static int interlace_increment[] = {8, 8, 4, 2};
9808 int pass;
9809 int row = interlace_start[0];
9811 pass = 0;
9813 for (y = 0; y < image_height; y++)
9815 if (row >= image_height)
9817 row = interlace_start[++pass];
9818 while (row >= image_height)
9819 row = interlace_start[++pass];
9822 for (x = 0; x < image_width; x++)
9824 int i = raster[(y * image_width) + x];
9825 XPutPixel (ximg, x + image_left, row + image_top,
9826 pixel_colors[i]);
9829 row += interlace_increment[pass];
9832 else
9834 for (y = 0; y < image_height; ++y)
9835 for (x = 0; x < image_width; ++x)
9837 int i = raster[y * image_width + x];
9838 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9842 DGifCloseFile (gif);
9844 /* Put the image into the pixmap, then free the X image and its buffer. */
9845 x_put_x_image (f, ximg, img->pixmap, width, height);
9846 x_destroy_x_image (ximg);
9848 UNGCPRO;
9849 return 1;
9852 #endif /* HAVE_GIF != 0 */
9856 /***********************************************************************
9857 Ghostscript
9858 ***********************************************************************/
9860 static int gs_image_p P_ ((Lisp_Object object));
9861 static int gs_load P_ ((struct frame *f, struct image *img));
9862 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9864 /* The symbol `postscript' identifying images of this type. */
9866 Lisp_Object Qpostscript;
9868 /* Keyword symbols. */
9870 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9872 /* Indices of image specification fields in gs_format, below. */
9874 enum gs_keyword_index
9876 GS_TYPE,
9877 GS_PT_WIDTH,
9878 GS_PT_HEIGHT,
9879 GS_FILE,
9880 GS_LOADER,
9881 GS_BOUNDING_BOX,
9882 GS_ASCENT,
9883 GS_MARGIN,
9884 GS_RELIEF,
9885 GS_ALGORITHM,
9886 GS_HEURISTIC_MASK,
9887 GS_MASK,
9888 GS_LAST
9891 /* Vector of image_keyword structures describing the format
9892 of valid user-defined image specifications. */
9894 static struct image_keyword gs_format[GS_LAST] =
9896 {":type", IMAGE_SYMBOL_VALUE, 1},
9897 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9898 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9899 {":file", IMAGE_STRING_VALUE, 1},
9900 {":loader", IMAGE_FUNCTION_VALUE, 0},
9901 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9902 {":ascent", IMAGE_ASCENT_VALUE, 0},
9903 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9904 {":relief", IMAGE_INTEGER_VALUE, 0},
9905 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9906 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9907 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9910 /* Structure describing the image type `ghostscript'. */
9912 static struct image_type gs_type =
9914 &Qpostscript,
9915 gs_image_p,
9916 gs_load,
9917 gs_clear_image,
9918 NULL
9922 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9924 static void
9925 gs_clear_image (f, img)
9926 struct frame *f;
9927 struct image *img;
9929 /* IMG->data.ptr_val may contain a recorded colormap. */
9930 xfree (img->data.ptr_val);
9931 x_clear_image (f, img);
9935 /* Return non-zero if OBJECT is a valid Ghostscript image
9936 specification. */
9938 static int
9939 gs_image_p (object)
9940 Lisp_Object object;
9942 struct image_keyword fmt[GS_LAST];
9943 Lisp_Object tem;
9944 int i;
9946 bcopy (gs_format, fmt, sizeof fmt);
9948 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9949 return 0;
9951 /* Bounding box must be a list or vector containing 4 integers. */
9952 tem = fmt[GS_BOUNDING_BOX].value;
9953 if (CONSP (tem))
9955 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9956 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9957 return 0;
9958 if (!NILP (tem))
9959 return 0;
9961 else if (VECTORP (tem))
9963 if (XVECTOR (tem)->size != 4)
9964 return 0;
9965 for (i = 0; i < 4; ++i)
9966 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9967 return 0;
9969 else
9970 return 0;
9972 return 1;
9976 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9977 if successful. */
9979 static int
9980 gs_load (f, img)
9981 struct frame *f;
9982 struct image *img;
9984 char buffer[100];
9985 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9986 struct gcpro gcpro1, gcpro2;
9987 Lisp_Object frame;
9988 double in_width, in_height;
9989 Lisp_Object pixel_colors = Qnil;
9991 /* Compute pixel size of pixmap needed from the given size in the
9992 image specification. Sizes in the specification are in pt. 1 pt
9993 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9994 info. */
9995 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9996 in_width = XFASTINT (pt_width) / 72.0;
9997 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9998 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9999 in_height = XFASTINT (pt_height) / 72.0;
10000 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10002 /* Create the pixmap. */
10003 xassert (img->pixmap == None);
10004 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10005 img->width, img->height,
10006 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10008 if (!img->pixmap)
10010 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10011 return 0;
10014 /* Call the loader to fill the pixmap. It returns a process object
10015 if successful. We do not record_unwind_protect here because
10016 other places in redisplay like calling window scroll functions
10017 don't either. Let the Lisp loader use `unwind-protect' instead. */
10018 GCPRO2 (window_and_pixmap_id, pixel_colors);
10020 sprintf (buffer, "%lu %lu",
10021 (unsigned long) FRAME_X_WINDOW (f),
10022 (unsigned long) img->pixmap);
10023 window_and_pixmap_id = build_string (buffer);
10025 sprintf (buffer, "%lu %lu",
10026 FRAME_FOREGROUND_PIXEL (f),
10027 FRAME_BACKGROUND_PIXEL (f));
10028 pixel_colors = build_string (buffer);
10030 XSETFRAME (frame, f);
10031 loader = image_spec_value (img->spec, QCloader, NULL);
10032 if (NILP (loader))
10033 loader = intern ("gs-load-image");
10035 img->data.lisp_val = call6 (loader, frame, img->spec,
10036 make_number (img->width),
10037 make_number (img->height),
10038 window_and_pixmap_id,
10039 pixel_colors);
10040 UNGCPRO;
10041 return PROCESSP (img->data.lisp_val);
10045 /* Kill the Ghostscript process that was started to fill PIXMAP on
10046 frame F. Called from XTread_socket when receiving an event
10047 telling Emacs that Ghostscript has finished drawing. */
10049 void
10050 x_kill_gs_process (pixmap, f)
10051 Pixmap pixmap;
10052 struct frame *f;
10054 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10055 int class, i;
10056 struct image *img;
10058 /* Find the image containing PIXMAP. */
10059 for (i = 0; i < c->used; ++i)
10060 if (c->images[i]->pixmap == pixmap)
10061 break;
10063 /* Kill the GS process. We should have found PIXMAP in the image
10064 cache and its image should contain a process object. */
10065 xassert (i < c->used);
10066 img = c->images[i];
10067 xassert (PROCESSP (img->data.lisp_val));
10068 Fkill_process (img->data.lisp_val, Qnil);
10069 img->data.lisp_val = Qnil;
10071 /* On displays with a mutable colormap, figure out the colors
10072 allocated for the image by looking at the pixels of an XImage for
10073 img->pixmap. */
10074 class = FRAME_X_VISUAL (f)->class;
10075 if (class != StaticColor && class != StaticGray && class != TrueColor)
10077 XImage *ximg;
10079 BLOCK_INPUT;
10081 /* Try to get an XImage for img->pixmep. */
10082 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10083 0, 0, img->width, img->height, ~0, ZPixmap);
10084 if (ximg)
10086 int x, y;
10088 /* Initialize the color table. */
10089 init_color_table ();
10091 /* For each pixel of the image, look its color up in the
10092 color table. After having done so, the color table will
10093 contain an entry for each color used by the image. */
10094 for (y = 0; y < img->height; ++y)
10095 for (x = 0; x < img->width; ++x)
10097 unsigned long pixel = XGetPixel (ximg, x, y);
10098 lookup_pixel_color (f, pixel);
10101 /* Record colors in the image. Free color table and XImage. */
10102 img->colors = colors_in_color_table (&img->ncolors);
10103 free_color_table ();
10104 XDestroyImage (ximg);
10106 #if 0 /* This doesn't seem to be the case. If we free the colors
10107 here, we get a BadAccess later in x_clear_image when
10108 freeing the colors. */
10109 /* We have allocated colors once, but Ghostscript has also
10110 allocated colors on behalf of us. So, to get the
10111 reference counts right, free them once. */
10112 if (img->ncolors)
10113 x_free_colors (f, img->colors, img->ncolors);
10114 #endif
10116 else
10117 image_error ("Cannot get X image of `%s'; colors will not be freed",
10118 img->spec, Qnil);
10120 UNBLOCK_INPUT;
10123 /* Now that we have the pixmap, compute mask and transform the
10124 image if requested. */
10125 BLOCK_INPUT;
10126 postprocess_image (f, img);
10127 UNBLOCK_INPUT;
10132 /***********************************************************************
10133 Window properties
10134 ***********************************************************************/
10136 DEFUN ("x-change-window-property", Fx_change_window_property,
10137 Sx_change_window_property, 2, 3, 0,
10138 "Change window property PROP to VALUE on the X window of FRAME.\n\
10139 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
10140 selected frame. Value is VALUE.")
10141 (prop, value, frame)
10142 Lisp_Object frame, prop, value;
10144 struct frame *f = check_x_frame (frame);
10145 Atom prop_atom;
10147 CHECK_STRING (prop, 1);
10148 CHECK_STRING (value, 2);
10150 BLOCK_INPUT;
10151 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10152 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10153 prop_atom, XA_STRING, 8, PropModeReplace,
10154 XSTRING (value)->data, XSTRING (value)->size);
10156 /* Make sure the property is set when we return. */
10157 XFlush (FRAME_X_DISPLAY (f));
10158 UNBLOCK_INPUT;
10160 return value;
10164 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10165 Sx_delete_window_property, 1, 2, 0,
10166 "Remove window property PROP from X window of FRAME.\n\
10167 FRAME nil or omitted means use the selected frame. Value is PROP.")
10168 (prop, frame)
10169 Lisp_Object prop, frame;
10171 struct frame *f = check_x_frame (frame);
10172 Atom prop_atom;
10174 CHECK_STRING (prop, 1);
10175 BLOCK_INPUT;
10176 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10177 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10179 /* Make sure the property is removed when we return. */
10180 XFlush (FRAME_X_DISPLAY (f));
10181 UNBLOCK_INPUT;
10183 return prop;
10187 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10188 1, 2, 0,
10189 "Value is the value of window property PROP on FRAME.\n\
10190 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10191 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10192 value.")
10193 (prop, frame)
10194 Lisp_Object prop, frame;
10196 struct frame *f = check_x_frame (frame);
10197 Atom prop_atom;
10198 int rc;
10199 Lisp_Object prop_value = Qnil;
10200 char *tmp_data = NULL;
10201 Atom actual_type;
10202 int actual_format;
10203 unsigned long actual_size, bytes_remaining;
10205 CHECK_STRING (prop, 1);
10206 BLOCK_INPUT;
10207 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10208 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10209 prop_atom, 0, 0, False, XA_STRING,
10210 &actual_type, &actual_format, &actual_size,
10211 &bytes_remaining, (unsigned char **) &tmp_data);
10212 if (rc == Success)
10214 int size = bytes_remaining;
10216 XFree (tmp_data);
10217 tmp_data = NULL;
10219 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10220 prop_atom, 0, bytes_remaining,
10221 False, XA_STRING,
10222 &actual_type, &actual_format,
10223 &actual_size, &bytes_remaining,
10224 (unsigned char **) &tmp_data);
10225 if (rc == Success)
10226 prop_value = make_string (tmp_data, size);
10228 XFree (tmp_data);
10231 UNBLOCK_INPUT;
10232 return prop_value;
10237 /***********************************************************************
10238 Busy cursor
10239 ***********************************************************************/
10241 /* If non-null, an asynchronous timer that, when it expires, displays
10242 an hourglass cursor on all frames. */
10244 static struct atimer *hourglass_atimer;
10246 /* Non-zero means an hourglass cursor is currently shown. */
10248 static int hourglass_shown_p;
10250 /* Number of seconds to wait before displaying an hourglass cursor. */
10252 static Lisp_Object Vhourglass_delay;
10254 /* Default number of seconds to wait before displaying an hourglass
10255 cursor. */
10257 #define DEFAULT_HOURGLASS_DELAY 1
10259 /* Function prototypes. */
10261 static void show_hourglass P_ ((struct atimer *));
10262 static void hide_hourglass P_ ((void));
10265 /* Cancel a currently active hourglass timer, and start a new one. */
10267 void
10268 start_hourglass ()
10270 EMACS_TIME delay;
10271 int secs, usecs = 0;
10273 cancel_hourglass ();
10275 if (INTEGERP (Vhourglass_delay)
10276 && XINT (Vhourglass_delay) > 0)
10277 secs = XFASTINT (Vhourglass_delay);
10278 else if (FLOATP (Vhourglass_delay)
10279 && XFLOAT_DATA (Vhourglass_delay) > 0)
10281 Lisp_Object tem;
10282 tem = Ftruncate (Vhourglass_delay, Qnil);
10283 secs = XFASTINT (tem);
10284 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10286 else
10287 secs = DEFAULT_HOURGLASS_DELAY;
10289 EMACS_SET_SECS_USECS (delay, secs, usecs);
10290 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10291 show_hourglass, NULL);
10295 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10296 shown. */
10298 void
10299 cancel_hourglass ()
10301 if (hourglass_atimer)
10303 cancel_atimer (hourglass_atimer);
10304 hourglass_atimer = NULL;
10307 if (hourglass_shown_p)
10308 hide_hourglass ();
10312 /* Timer function of hourglass_atimer. TIMER is equal to
10313 hourglass_atimer.
10315 Display an hourglass pointer on all frames by mapping the frames'
10316 hourglass_window. Set the hourglass_p flag in the frames'
10317 output_data.x structure to indicate that an hourglass cursor is
10318 shown on the frames. */
10320 static void
10321 show_hourglass (timer)
10322 struct atimer *timer;
10324 /* The timer implementation will cancel this timer automatically
10325 after this function has run. Set hourglass_atimer to null
10326 so that we know the timer doesn't have to be canceled. */
10327 hourglass_atimer = NULL;
10329 if (!hourglass_shown_p)
10331 Lisp_Object rest, frame;
10333 BLOCK_INPUT;
10335 FOR_EACH_FRAME (rest, frame)
10337 struct frame *f = XFRAME (frame);
10339 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10341 Display *dpy = FRAME_X_DISPLAY (f);
10343 #ifdef USE_X_TOOLKIT
10344 if (f->output_data.x->widget)
10345 #else
10346 if (FRAME_OUTER_WINDOW (f))
10347 #endif
10349 f->output_data.x->hourglass_p = 1;
10351 if (!f->output_data.x->hourglass_window)
10353 unsigned long mask = CWCursor;
10354 XSetWindowAttributes attrs;
10356 attrs.cursor = f->output_data.x->hourglass_cursor;
10358 f->output_data.x->hourglass_window
10359 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10360 0, 0, 32000, 32000, 0, 0,
10361 InputOnly,
10362 CopyFromParent,
10363 mask, &attrs);
10366 XMapRaised (dpy, f->output_data.x->hourglass_window);
10367 XFlush (dpy);
10372 hourglass_shown_p = 1;
10373 UNBLOCK_INPUT;
10378 /* Hide the hourglass pointer on all frames, if it is currently
10379 shown. */
10381 static void
10382 hide_hourglass ()
10384 if (hourglass_shown_p)
10386 Lisp_Object rest, frame;
10388 BLOCK_INPUT;
10389 FOR_EACH_FRAME (rest, frame)
10391 struct frame *f = XFRAME (frame);
10393 if (FRAME_X_P (f)
10394 /* Watch out for newly created frames. */
10395 && f->output_data.x->hourglass_window)
10397 XUnmapWindow (FRAME_X_DISPLAY (f),
10398 f->output_data.x->hourglass_window);
10399 /* Sync here because XTread_socket looks at the
10400 hourglass_p flag that is reset to zero below. */
10401 XSync (FRAME_X_DISPLAY (f), False);
10402 f->output_data.x->hourglass_p = 0;
10406 hourglass_shown_p = 0;
10407 UNBLOCK_INPUT;
10413 /***********************************************************************
10414 Tool tips
10415 ***********************************************************************/
10417 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10418 Lisp_Object, Lisp_Object));
10419 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10420 Lisp_Object, int, int, int *, int *));
10422 /* The frame of a currently visible tooltip. */
10424 Lisp_Object tip_frame;
10426 /* If non-nil, a timer started that hides the last tooltip when it
10427 fires. */
10429 Lisp_Object tip_timer;
10430 Window tip_window;
10432 /* If non-nil, a vector of 3 elements containing the last args
10433 with which x-show-tip was called. See there. */
10435 Lisp_Object last_show_tip_args;
10438 static Lisp_Object
10439 unwind_create_tip_frame (frame)
10440 Lisp_Object frame;
10442 Lisp_Object deleted;
10444 deleted = unwind_create_frame (frame);
10445 if (EQ (deleted, Qt))
10447 tip_window = None;
10448 tip_frame = Qnil;
10451 return deleted;
10455 /* Create a frame for a tooltip on the display described by DPYINFO.
10456 PARMS is a list of frame parameters. TEXT is the string to
10457 display in the tip frame. Value is the frame.
10459 Note that functions called here, esp. x_default_parameter can
10460 signal errors, for instance when a specified color name is
10461 undefined. We have to make sure that we're in a consistent state
10462 when this happens. */
10464 static Lisp_Object
10465 x_create_tip_frame (dpyinfo, parms, text)
10466 struct x_display_info *dpyinfo;
10467 Lisp_Object parms, text;
10469 struct frame *f;
10470 Lisp_Object frame, tem;
10471 Lisp_Object name;
10472 long window_prompting = 0;
10473 int width, height;
10474 int count = BINDING_STACK_SIZE ();
10475 struct gcpro gcpro1, gcpro2, gcpro3;
10476 struct kboard *kb;
10477 int face_change_count_before = face_change_count;
10478 Lisp_Object buffer;
10479 struct buffer *old_buffer;
10481 check_x ();
10483 /* Use this general default value to start with until we know if
10484 this frame has a specified name. */
10485 Vx_resource_name = Vinvocation_name;
10487 #ifdef MULTI_KBOARD
10488 kb = dpyinfo->kboard;
10489 #else
10490 kb = &the_only_kboard;
10491 #endif
10493 /* Get the name of the frame to use for resource lookup. */
10494 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10495 if (!STRINGP (name)
10496 && !EQ (name, Qunbound)
10497 && !NILP (name))
10498 error ("Invalid frame name--not a string or nil");
10499 Vx_resource_name = name;
10501 frame = Qnil;
10502 GCPRO3 (parms, name, frame);
10503 f = make_frame (1);
10504 XSETFRAME (frame, f);
10506 buffer = Fget_buffer_create (build_string (" *tip*"));
10507 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10508 old_buffer = current_buffer;
10509 set_buffer_internal_1 (XBUFFER (buffer));
10510 Ferase_buffer ();
10511 Finsert (1, &text);
10512 set_buffer_internal_1 (old_buffer);
10514 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10515 record_unwind_protect (unwind_create_tip_frame, frame);
10517 /* By setting the output method, we're essentially saying that
10518 the frame is live, as per FRAME_LIVE_P. If we get a signal
10519 from this point on, x_destroy_window might screw up reference
10520 counts etc. */
10521 f->output_method = output_x_window;
10522 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10523 bzero (f->output_data.x, sizeof (struct x_output));
10524 f->output_data.x->icon_bitmap = -1;
10525 f->output_data.x->fontset = -1;
10526 f->output_data.x->scroll_bar_foreground_pixel = -1;
10527 f->output_data.x->scroll_bar_background_pixel = -1;
10528 f->icon_name = Qnil;
10529 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10530 #if GLYPH_DEBUG
10531 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
10532 dpyinfo_refcount = dpyinfo->reference_count;
10533 #endif /* GLYPH_DEBUG */
10534 #ifdef MULTI_KBOARD
10535 FRAME_KBOARD (f) = kb;
10536 #endif
10537 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10538 f->output_data.x->explicit_parent = 0;
10540 /* These colors will be set anyway later, but it's important
10541 to get the color reference counts right, so initialize them! */
10543 Lisp_Object black;
10544 struct gcpro gcpro1;
10546 black = build_string ("black");
10547 GCPRO1 (black);
10548 f->output_data.x->foreground_pixel
10549 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10550 f->output_data.x->background_pixel
10551 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10552 f->output_data.x->cursor_pixel
10553 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10554 f->output_data.x->cursor_foreground_pixel
10555 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10556 f->output_data.x->border_pixel
10557 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10558 f->output_data.x->mouse_pixel
10559 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10560 UNGCPRO;
10563 /* Set the name; the functions to which we pass f expect the name to
10564 be set. */
10565 if (EQ (name, Qunbound) || NILP (name))
10567 f->name = build_string (dpyinfo->x_id_name);
10568 f->explicit_name = 0;
10570 else
10572 f->name = name;
10573 f->explicit_name = 1;
10574 /* use the frame's title when getting resources for this frame. */
10575 specbind (Qx_resource_name, name);
10578 /* Extract the window parameters from the supplied values that are
10579 needed to determine window geometry. */
10581 Lisp_Object font;
10583 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10585 BLOCK_INPUT;
10586 /* First, try whatever font the caller has specified. */
10587 if (STRINGP (font))
10589 tem = Fquery_fontset (font, Qnil);
10590 if (STRINGP (tem))
10591 font = x_new_fontset (f, XSTRING (tem)->data);
10592 else
10593 font = x_new_font (f, XSTRING (font)->data);
10596 /* Try out a font which we hope has bold and italic variations. */
10597 if (!STRINGP (font))
10598 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10599 if (!STRINGP (font))
10600 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10601 if (! STRINGP (font))
10602 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10603 if (! STRINGP (font))
10604 /* This was formerly the first thing tried, but it finds too many fonts
10605 and takes too long. */
10606 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10607 /* If those didn't work, look for something which will at least work. */
10608 if (! STRINGP (font))
10609 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10610 UNBLOCK_INPUT;
10611 if (! STRINGP (font))
10612 font = build_string ("fixed");
10614 x_default_parameter (f, parms, Qfont, font,
10615 "font", "Font", RES_TYPE_STRING);
10618 x_default_parameter (f, parms, Qborder_width, make_number (2),
10619 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10621 /* This defaults to 2 in order to match xterm. We recognize either
10622 internalBorderWidth or internalBorder (which is what xterm calls
10623 it). */
10624 if (NILP (Fassq (Qinternal_border_width, parms)))
10626 Lisp_Object value;
10628 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10629 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10630 if (! EQ (value, Qunbound))
10631 parms = Fcons (Fcons (Qinternal_border_width, value),
10632 parms);
10635 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10636 "internalBorderWidth", "internalBorderWidth",
10637 RES_TYPE_NUMBER);
10639 /* Also do the stuff which must be set before the window exists. */
10640 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10641 "foreground", "Foreground", RES_TYPE_STRING);
10642 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10643 "background", "Background", RES_TYPE_STRING);
10644 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10645 "pointerColor", "Foreground", RES_TYPE_STRING);
10646 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10647 "cursorColor", "Foreground", RES_TYPE_STRING);
10648 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10649 "borderColor", "BorderColor", RES_TYPE_STRING);
10651 /* Init faces before x_default_parameter is called for scroll-bar
10652 parameters because that function calls x_set_scroll_bar_width,
10653 which calls change_frame_size, which calls Fset_window_buffer,
10654 which runs hooks, which call Fvertical_motion. At the end, we
10655 end up in init_iterator with a null face cache, which should not
10656 happen. */
10657 init_frame_faces (f);
10659 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10660 window_prompting = x_figure_window_size (f, parms);
10662 if (window_prompting & XNegative)
10664 if (window_prompting & YNegative)
10665 f->output_data.x->win_gravity = SouthEastGravity;
10666 else
10667 f->output_data.x->win_gravity = NorthEastGravity;
10669 else
10671 if (window_prompting & YNegative)
10672 f->output_data.x->win_gravity = SouthWestGravity;
10673 else
10674 f->output_data.x->win_gravity = NorthWestGravity;
10677 f->output_data.x->size_hint_flags = window_prompting;
10679 XSetWindowAttributes attrs;
10680 unsigned long mask;
10682 BLOCK_INPUT;
10683 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
10684 if (DoesSaveUnders (dpyinfo->screen))
10685 mask |= CWSaveUnder;
10687 /* Window managers look at the override-redirect flag to determine
10688 whether or net to give windows a decoration (Xlib spec, chapter
10689 3.2.8). */
10690 attrs.override_redirect = True;
10691 attrs.save_under = True;
10692 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10693 /* Arrange for getting MapNotify and UnmapNotify events. */
10694 attrs.event_mask = StructureNotifyMask;
10695 tip_window
10696 = FRAME_X_WINDOW (f)
10697 = XCreateWindow (FRAME_X_DISPLAY (f),
10698 FRAME_X_DISPLAY_INFO (f)->root_window,
10699 /* x, y, width, height */
10700 0, 0, 1, 1,
10701 /* Border. */
10703 CopyFromParent, InputOutput, CopyFromParent,
10704 mask, &attrs);
10705 UNBLOCK_INPUT;
10708 x_make_gc (f);
10710 x_default_parameter (f, parms, Qauto_raise, Qnil,
10711 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10712 x_default_parameter (f, parms, Qauto_lower, Qnil,
10713 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10714 x_default_parameter (f, parms, Qcursor_type, Qbox,
10715 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10717 /* Dimensions, especially f->height, must be done via change_frame_size.
10718 Change will not be effected unless different from the current
10719 f->height. */
10720 width = f->width;
10721 height = f->height;
10722 f->height = 0;
10723 SET_FRAME_WIDTH (f, 0);
10724 change_frame_size (f, height, width, 1, 0, 0);
10726 /* Set up faces after all frame parameters are known. This call
10727 also merges in face attributes specified for new frames.
10729 Frame parameters may be changed if .Xdefaults contains
10730 specifications for the default font. For example, if there is an
10731 `Emacs.default.attributeBackground: pink', the `background-color'
10732 attribute of the frame get's set, which let's the internal border
10733 of the tooltip frame appear in pink. Prevent this. */
10735 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
10737 /* Set tip_frame here, so that */
10738 tip_frame = frame;
10739 call1 (Qface_set_after_frame_default, frame);
10741 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
10742 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
10743 Qnil));
10746 f->no_split = 1;
10748 UNGCPRO;
10750 /* It is now ok to make the frame official even if we get an error
10751 below. And the frame needs to be on Vframe_list or making it
10752 visible won't work. */
10753 Vframe_list = Fcons (frame, Vframe_list);
10755 /* Now that the frame is official, it counts as a reference to
10756 its display. */
10757 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10759 /* Setting attributes of faces of the tooltip frame from resources
10760 and similar will increment face_change_count, which leads to the
10761 clearing of all current matrices. Since this isn't necessary
10762 here, avoid it by resetting face_change_count to the value it
10763 had before we created the tip frame. */
10764 face_change_count = face_change_count_before;
10766 /* Discard the unwind_protect. */
10767 return unbind_to (count, frame);
10771 /* Compute where to display tip frame F. PARMS is the list of frame
10772 parameters for F. DX and DY are specified offsets from the current
10773 location of the mouse. WIDTH and HEIGHT are the width and height
10774 of the tooltip. Return coordinates relative to the root window of
10775 the display in *ROOT_X, and *ROOT_Y. */
10777 static void
10778 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
10779 struct frame *f;
10780 Lisp_Object parms, dx, dy;
10781 int width, height;
10782 int *root_x, *root_y;
10784 Lisp_Object left, top;
10785 int win_x, win_y;
10786 Window root, child;
10787 unsigned pmask;
10789 /* User-specified position? */
10790 left = Fcdr (Fassq (Qleft, parms));
10791 top = Fcdr (Fassq (Qtop, parms));
10793 /* Move the tooltip window where the mouse pointer is. Resize and
10794 show it. */
10795 if (!INTEGERP (left) && !INTEGERP (top))
10797 BLOCK_INPUT;
10798 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10799 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
10800 UNBLOCK_INPUT;
10803 if (INTEGERP (top))
10804 *root_y = XINT (top);
10805 else if (*root_y + XINT (dy) - height < 0)
10806 *root_y -= XINT (dy);
10807 else
10809 *root_y -= height;
10810 *root_y += XINT (dy);
10813 if (INTEGERP (left))
10814 *root_x = XINT (left);
10815 else if (*root_x + XINT (dx) + width > FRAME_X_DISPLAY_INFO (f)->width)
10816 *root_x -= width + XINT (dx);
10817 else
10818 *root_x += XINT (dx);
10822 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10823 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10824 A tooltip window is a small X window displaying a string.\n\
10826 FRAME nil or omitted means use the selected frame.\n\
10828 PARMS is an optional list of frame parameters which can be\n\
10829 used to change the tooltip's appearance.\n\
10831 Automatically hide the tooltip after TIMEOUT seconds.\n\
10832 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10834 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10835 the tooltip is displayed at that x-position. Otherwise it is\n\
10836 displayed at the mouse position, with offset DX added (default is 5 if\n\
10837 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10838 parameter is specified, it determines the y-position of the tooltip\n\
10839 window, otherwise it is displayed at the mouse position, with offset\n\
10840 DY added (default is -10).")
10841 (string, frame, parms, timeout, dx, dy)
10842 Lisp_Object string, frame, parms, timeout, dx, dy;
10844 struct frame *f;
10845 struct window *w;
10846 Lisp_Object buffer, top, left;
10847 int root_x, root_y;
10848 struct buffer *old_buffer;
10849 struct text_pos pos;
10850 int i, width, height;
10851 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10852 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10853 int count = BINDING_STACK_SIZE ();
10855 specbind (Qinhibit_redisplay, Qt);
10857 GCPRO4 (string, parms, frame, timeout);
10859 CHECK_STRING (string, 0);
10860 f = check_x_frame (frame);
10861 if (NILP (timeout))
10862 timeout = make_number (5);
10863 else
10864 CHECK_NATNUM (timeout, 2);
10866 if (NILP (dx))
10867 dx = make_number (5);
10868 else
10869 CHECK_NUMBER (dx, 5);
10871 if (NILP (dy))
10872 dy = make_number (-10);
10873 else
10874 CHECK_NUMBER (dy, 6);
10876 if (NILP (last_show_tip_args))
10877 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
10879 if (!NILP (tip_frame))
10881 Lisp_Object last_string = AREF (last_show_tip_args, 0);
10882 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
10883 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
10885 if (EQ (frame, last_frame)
10886 && !NILP (Fequal (last_string, string))
10887 && !NILP (Fequal (last_parms, parms)))
10889 struct frame *f = XFRAME (tip_frame);
10891 /* Only DX and DY have changed. */
10892 if (!NILP (tip_timer))
10894 Lisp_Object timer = tip_timer;
10895 tip_timer = Qnil;
10896 call1 (Qcancel_timer, timer);
10899 BLOCK_INPUT;
10900 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
10901 PIXEL_HEIGHT (f), &root_x, &root_y);
10902 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10903 root_x, root_y);
10904 UNBLOCK_INPUT;
10905 goto start_timer;
10909 /* Hide a previous tip, if any. */
10910 Fx_hide_tip ();
10912 ASET (last_show_tip_args, 0, string);
10913 ASET (last_show_tip_args, 1, frame);
10914 ASET (last_show_tip_args, 2, parms);
10916 /* Add default values to frame parameters. */
10917 if (NILP (Fassq (Qname, parms)))
10918 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10919 if (NILP (Fassq (Qinternal_border_width, parms)))
10920 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10921 if (NILP (Fassq (Qborder_width, parms)))
10922 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10923 if (NILP (Fassq (Qborder_color, parms)))
10924 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10925 if (NILP (Fassq (Qbackground_color, parms)))
10926 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10927 parms);
10929 /* Create a frame for the tooltip, and record it in the global
10930 variable tip_frame. */
10931 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
10932 f = XFRAME (frame);
10934 /* Set up the frame's root window. Currently we use a size of 80
10935 columns x 40 lines. If someone wants to show a larger tip, he
10936 will loose. I don't think this is a realistic case. */
10937 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10938 w->left = w->top = make_number (0);
10939 w->width = make_number (80);
10940 w->height = make_number (40);
10941 adjust_glyphs (f);
10942 w->pseudo_window_p = 1;
10944 /* Display the tooltip text in a temporary buffer. */
10945 old_buffer = current_buffer;
10946 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
10947 clear_glyph_matrix (w->desired_matrix);
10948 clear_glyph_matrix (w->current_matrix);
10949 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10950 try_window (FRAME_ROOT_WINDOW (f), pos);
10952 /* Compute width and height of the tooltip. */
10953 width = height = 0;
10954 for (i = 0; i < w->desired_matrix->nrows; ++i)
10956 struct glyph_row *row = &w->desired_matrix->rows[i];
10957 struct glyph *last;
10958 int row_width;
10960 /* Stop at the first empty row at the end. */
10961 if (!row->enabled_p || !row->displays_text_p)
10962 break;
10964 /* Let the row go over the full width of the frame. */
10965 row->full_width_p = 1;
10967 /* There's a glyph at the end of rows that is used to place
10968 the cursor there. Don't include the width of this glyph. */
10969 if (row->used[TEXT_AREA])
10971 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10972 row_width = row->pixel_width - last->pixel_width;
10974 else
10975 row_width = row->pixel_width;
10977 height += row->height;
10978 width = max (width, row_width);
10981 /* Add the frame's internal border to the width and height the X
10982 window should have. */
10983 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10984 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10986 /* Move the tooltip window where the mouse pointer is. Resize and
10987 show it. */
10988 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
10990 BLOCK_INPUT;
10991 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10992 root_x, root_y, width, height);
10993 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10994 UNBLOCK_INPUT;
10996 /* Draw into the window. */
10997 w->must_be_updated_p = 1;
10998 update_single_window (w, 1);
11000 /* Restore original current buffer. */
11001 set_buffer_internal_1 (old_buffer);
11002 windows_or_buffers_changed = old_windows_or_buffers_changed;
11004 start_timer:
11005 /* Let the tip disappear after timeout seconds. */
11006 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11007 intern ("x-hide-tip"));
11009 UNGCPRO;
11010 return unbind_to (count, Qnil);
11014 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11015 "Hide the current tooltip window, if there is any.\n\
11016 Value is t is tooltip was open, nil otherwise.")
11019 int count;
11020 Lisp_Object deleted, frame, timer;
11021 struct gcpro gcpro1, gcpro2;
11023 /* Return quickly if nothing to do. */
11024 if (NILP (tip_timer) && NILP (tip_frame))
11025 return Qnil;
11027 frame = tip_frame;
11028 timer = tip_timer;
11029 GCPRO2 (frame, timer);
11030 tip_frame = tip_timer = deleted = Qnil;
11032 count = BINDING_STACK_SIZE ();
11033 specbind (Qinhibit_redisplay, Qt);
11034 specbind (Qinhibit_quit, Qt);
11036 if (!NILP (timer))
11037 call1 (Qcancel_timer, timer);
11039 if (FRAMEP (frame))
11041 Fdelete_frame (frame, Qnil);
11042 deleted = Qt;
11044 #ifdef USE_LUCID
11045 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11046 redisplay procedure is not called when a tip frame over menu
11047 items is unmapped. Redisplay the menu manually... */
11049 struct frame *f = SELECTED_FRAME ();
11050 Widget w = f->output_data.x->menubar_widget;
11051 extern void xlwmenu_redisplay P_ ((Widget));
11053 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11054 && w != NULL)
11056 BLOCK_INPUT;
11057 xlwmenu_redisplay (w);
11058 UNBLOCK_INPUT;
11061 #endif /* USE_LUCID */
11064 UNGCPRO;
11065 return unbind_to (count, deleted);
11070 /***********************************************************************
11071 File selection dialog
11072 ***********************************************************************/
11074 #ifdef USE_MOTIF
11076 /* Callback for "OK" and "Cancel" on file selection dialog. */
11078 static void
11079 file_dialog_cb (widget, client_data, call_data)
11080 Widget widget;
11081 XtPointer call_data, client_data;
11083 int *result = (int *) client_data;
11084 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11085 *result = cb->reason;
11089 /* Callback for unmapping a file selection dialog. This is used to
11090 capture the case where a dialog is closed via a window manager's
11091 closer button, for example. Using a XmNdestroyCallback didn't work
11092 in this case. */
11094 static void
11095 file_dialog_unmap_cb (widget, client_data, call_data)
11096 Widget widget;
11097 XtPointer call_data, client_data;
11099 int *result = (int *) client_data;
11100 *result = XmCR_CANCEL;
11104 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11105 "Read file name, prompting with PROMPT in directory DIR.\n\
11106 Use a file selection dialog.\n\
11107 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
11108 specified. Don't let the user enter a file name in the file\n\
11109 selection dialog's entry field, if MUSTMATCH is non-nil.")
11110 (prompt, dir, default_filename, mustmatch)
11111 Lisp_Object prompt, dir, default_filename, mustmatch;
11113 int result;
11114 struct frame *f = SELECTED_FRAME ();
11115 Lisp_Object file = Qnil;
11116 Widget dialog, text, list, help;
11117 Arg al[10];
11118 int ac = 0;
11119 extern XtAppContext Xt_app_con;
11120 char *title;
11121 XmString dir_xmstring, pattern_xmstring;
11122 int popup_activated_flag;
11123 int count = specpdl_ptr - specpdl;
11124 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11126 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11127 CHECK_STRING (prompt, 0);
11128 CHECK_STRING (dir, 1);
11130 /* Prevent redisplay. */
11131 specbind (Qinhibit_redisplay, Qt);
11133 BLOCK_INPUT;
11135 /* Create the dialog with PROMPT as title, using DIR as initial
11136 directory and using "*" as pattern. */
11137 dir = Fexpand_file_name (dir, Qnil);
11138 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
11139 pattern_xmstring = XmStringCreateLocalized ("*");
11141 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
11142 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11143 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11144 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11145 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11146 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11147 "fsb", al, ac);
11148 XmStringFree (dir_xmstring);
11149 XmStringFree (pattern_xmstring);
11151 /* Add callbacks for OK and Cancel. */
11152 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11153 (XtPointer) &result);
11154 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11155 (XtPointer) &result);
11156 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11157 (XtPointer) &result);
11159 /* Disable the help button since we can't display help. */
11160 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11161 XtSetSensitive (help, False);
11163 /* Mark OK button as default. */
11164 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11165 XmNshowAsDefault, True, NULL);
11167 /* If MUSTMATCH is non-nil, disable the file entry field of the
11168 dialog, so that the user must select a file from the files list
11169 box. We can't remove it because we wouldn't have a way to get at
11170 the result file name, then. */
11171 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11172 if (!NILP (mustmatch))
11174 Widget label;
11175 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11176 XtSetSensitive (text, False);
11177 XtSetSensitive (label, False);
11180 /* Manage the dialog, so that list boxes get filled. */
11181 XtManageChild (dialog);
11183 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11184 must include the path for this to work. */
11185 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11186 if (STRINGP (default_filename))
11188 XmString default_xmstring;
11189 int item_pos;
11191 default_xmstring
11192 = XmStringCreateLocalized (XSTRING (default_filename)->data);
11194 if (!XmListItemExists (list, default_xmstring))
11196 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11197 XmListAddItem (list, default_xmstring, 0);
11198 item_pos = 0;
11200 else
11201 item_pos = XmListItemPos (list, default_xmstring);
11202 XmStringFree (default_xmstring);
11204 /* Select the item and scroll it into view. */
11205 XmListSelectPos (list, item_pos, True);
11206 XmListSetPos (list, item_pos);
11209 /* Process events until the user presses Cancel or OK. */
11210 result = 0;
11211 while (result == 0)
11212 XtAppProcessEvent (Xt_app_con, XtIMAll);
11214 /* Get the result. */
11215 if (result == XmCR_OK)
11217 XmString text;
11218 String data;
11220 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11221 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11222 XmStringFree (text);
11223 file = build_string (data);
11224 XtFree (data);
11226 else
11227 file = Qnil;
11229 /* Clean up. */
11230 XtUnmanageChild (dialog);
11231 XtDestroyWidget (dialog);
11232 UNBLOCK_INPUT;
11233 UNGCPRO;
11235 /* Make "Cancel" equivalent to C-g. */
11236 if (NILP (file))
11237 Fsignal (Qquit, Qnil);
11239 return unbind_to (count, file);
11242 #endif /* USE_MOTIF */
11246 /***********************************************************************
11247 Keyboard
11248 ***********************************************************************/
11250 #ifdef HAVE_XKBGETKEYBOARD
11251 #include <X11/XKBlib.h>
11252 #include <X11/keysym.h>
11253 #endif
11255 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11256 Sx_backspace_delete_keys_p, 0, 1, 0,
11257 "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
11258 FRAME nil means use the selected frame.\n\
11259 Value is t if we know that both keys are present, and are mapped to the\n\
11260 usual X keysyms.")
11261 (frame)
11262 Lisp_Object frame;
11264 #ifdef HAVE_XKBGETKEYBOARD
11265 XkbDescPtr kb;
11266 struct frame *f = check_x_frame (frame);
11267 Display *dpy = FRAME_X_DISPLAY (f);
11268 Lisp_Object have_keys;
11269 int major, minor, op, event, error;
11271 BLOCK_INPUT;
11273 /* Check library version in case we're dynamically linked. */
11274 major = XkbMajorVersion;
11275 minor = XkbMinorVersion;
11276 if (!XkbLibraryVersion (&major, &minor))
11278 UNBLOCK_INPUT;
11279 return Qnil;
11282 /* Check that the server supports XKB. */
11283 major = XkbMajorVersion;
11284 minor = XkbMinorVersion;
11285 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11287 UNBLOCK_INPUT;
11288 return Qnil;
11291 have_keys = Qnil;
11292 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11293 if (kb)
11295 int delete_keycode = 0, backspace_keycode = 0, i;
11297 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11299 for (i = kb->min_key_code;
11300 (i < kb->max_key_code
11301 && (delete_keycode == 0 || backspace_keycode == 0));
11302 ++i)
11304 /* The XKB symbolic key names can be seen most easily
11305 in the PS file generated by `xkbprint -label name $DISPLAY'. */
11306 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11307 delete_keycode = i;
11308 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11309 backspace_keycode = i;
11312 XkbFreeNames (kb, 0, True);
11315 XkbFreeClientMap (kb, 0, True);
11317 if (delete_keycode
11318 && backspace_keycode
11319 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11320 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11321 have_keys = Qt;
11323 UNBLOCK_INPUT;
11324 return have_keys;
11325 #else /* not HAVE_XKBGETKEYBOARD */
11326 return Qnil;
11327 #endif /* not HAVE_XKBGETKEYBOARD */
11332 /***********************************************************************
11333 Initialization
11334 ***********************************************************************/
11336 void
11337 syms_of_xfns ()
11339 /* This is zero if not using X windows. */
11340 x_in_use = 0;
11342 /* The section below is built by the lisp expression at the top of the file,
11343 just above where these variables are declared. */
11344 /*&&& init symbols here &&&*/
11345 Qauto_raise = intern ("auto-raise");
11346 staticpro (&Qauto_raise);
11347 Qauto_lower = intern ("auto-lower");
11348 staticpro (&Qauto_lower);
11349 Qbar = intern ("bar");
11350 staticpro (&Qbar);
11351 Qborder_color = intern ("border-color");
11352 staticpro (&Qborder_color);
11353 Qborder_width = intern ("border-width");
11354 staticpro (&Qborder_width);
11355 Qbox = intern ("box");
11356 staticpro (&Qbox);
11357 Qcursor_color = intern ("cursor-color");
11358 staticpro (&Qcursor_color);
11359 Qcursor_type = intern ("cursor-type");
11360 staticpro (&Qcursor_type);
11361 Qgeometry = intern ("geometry");
11362 staticpro (&Qgeometry);
11363 Qicon_left = intern ("icon-left");
11364 staticpro (&Qicon_left);
11365 Qicon_top = intern ("icon-top");
11366 staticpro (&Qicon_top);
11367 Qicon_type = intern ("icon-type");
11368 staticpro (&Qicon_type);
11369 Qicon_name = intern ("icon-name");
11370 staticpro (&Qicon_name);
11371 Qinternal_border_width = intern ("internal-border-width");
11372 staticpro (&Qinternal_border_width);
11373 Qleft = intern ("left");
11374 staticpro (&Qleft);
11375 Qright = intern ("right");
11376 staticpro (&Qright);
11377 Qmouse_color = intern ("mouse-color");
11378 staticpro (&Qmouse_color);
11379 Qnone = intern ("none");
11380 staticpro (&Qnone);
11381 Qparent_id = intern ("parent-id");
11382 staticpro (&Qparent_id);
11383 Qscroll_bar_width = intern ("scroll-bar-width");
11384 staticpro (&Qscroll_bar_width);
11385 Qsuppress_icon = intern ("suppress-icon");
11386 staticpro (&Qsuppress_icon);
11387 Qundefined_color = intern ("undefined-color");
11388 staticpro (&Qundefined_color);
11389 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11390 staticpro (&Qvertical_scroll_bars);
11391 Qvisibility = intern ("visibility");
11392 staticpro (&Qvisibility);
11393 Qwindow_id = intern ("window-id");
11394 staticpro (&Qwindow_id);
11395 Qouter_window_id = intern ("outer-window-id");
11396 staticpro (&Qouter_window_id);
11397 Qx_frame_parameter = intern ("x-frame-parameter");
11398 staticpro (&Qx_frame_parameter);
11399 Qx_resource_name = intern ("x-resource-name");
11400 staticpro (&Qx_resource_name);
11401 Quser_position = intern ("user-position");
11402 staticpro (&Quser_position);
11403 Quser_size = intern ("user-size");
11404 staticpro (&Quser_size);
11405 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11406 staticpro (&Qscroll_bar_foreground);
11407 Qscroll_bar_background = intern ("scroll-bar-background");
11408 staticpro (&Qscroll_bar_background);
11409 Qscreen_gamma = intern ("screen-gamma");
11410 staticpro (&Qscreen_gamma);
11411 Qline_spacing = intern ("line-spacing");
11412 staticpro (&Qline_spacing);
11413 Qcenter = intern ("center");
11414 staticpro (&Qcenter);
11415 Qcompound_text = intern ("compound-text");
11416 staticpro (&Qcompound_text);
11417 Qcancel_timer = intern ("cancel-timer");
11418 staticpro (&Qcancel_timer);
11419 /* This is the end of symbol initialization. */
11421 /* Text property `display' should be nonsticky by default. */
11422 Vtext_property_default_nonsticky
11423 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11426 Qlaplace = intern ("laplace");
11427 staticpro (&Qlaplace);
11428 Qemboss = intern ("emboss");
11429 staticpro (&Qemboss);
11430 Qedge_detection = intern ("edge-detection");
11431 staticpro (&Qedge_detection);
11432 Qheuristic = intern ("heuristic");
11433 staticpro (&Qheuristic);
11434 QCmatrix = intern (":matrix");
11435 staticpro (&QCmatrix);
11436 QCcolor_adjustment = intern (":color-adjustment");
11437 staticpro (&QCcolor_adjustment);
11438 QCmask = intern (":mask");
11439 staticpro (&QCmask);
11441 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11442 staticpro (&Qface_set_after_frame_default);
11444 Fput (Qundefined_color, Qerror_conditions,
11445 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11446 Fput (Qundefined_color, Qerror_message,
11447 build_string ("Undefined color"));
11449 init_x_parm_symbols ();
11451 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11452 "Non-nil means always draw a cross over disabled images.\n\
11453 Disabled images are those having an `:conversion disabled' property.\n\
11454 A cross is always drawn on black & white displays.");
11455 cross_disabled_images = 0;
11457 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11458 "List of directories to search for bitmap files for X.");
11459 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11461 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11462 "The shape of the pointer when over text.\n\
11463 Changing the value does not affect existing frames\n\
11464 unless you set the mouse color.");
11465 Vx_pointer_shape = Qnil;
11467 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11468 "The name Emacs uses to look up X resources.\n\
11469 `x-get-resource' uses this as the first component of the instance name\n\
11470 when requesting resource values.\n\
11471 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11472 was invoked, or to the value specified with the `-name' or `-rn'\n\
11473 switches, if present.\n\
11475 It may be useful to bind this variable locally around a call\n\
11476 to `x-get-resource'. See also the variable `x-resource-class'.");
11477 Vx_resource_name = Qnil;
11479 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11480 "The class Emacs uses to look up X resources.\n\
11481 `x-get-resource' uses this as the first component of the instance class\n\
11482 when requesting resource values.\n\
11483 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11485 Setting this variable permanently is not a reasonable thing to do,\n\
11486 but binding this variable locally around a call to `x-get-resource'\n\
11487 is a reasonable practice. See also the variable `x-resource-name'.");
11488 Vx_resource_class = build_string (EMACS_CLASS);
11490 #if 0 /* This doesn't really do anything. */
11491 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11492 "The shape of the pointer when not over text.\n\
11493 This variable takes effect when you create a new frame\n\
11494 or when you set the mouse color.");
11495 #endif
11496 Vx_nontext_pointer_shape = Qnil;
11498 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
11499 "The shape of the pointer when Emacs is busy.\n\
11500 This variable takes effect when you create a new frame\n\
11501 or when you set the mouse color.");
11502 Vx_hourglass_pointer_shape = Qnil;
11504 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
11505 "Non-zero means Emacs displays an hourglass pointer on window systems.");
11506 display_hourglass_p = 1;
11508 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
11509 "*Seconds to wait before displaying an hourglass pointer.\n\
11510 Value must be an integer or float.");
11511 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
11513 #if 0 /* This doesn't really do anything. */
11514 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11515 "The shape of the pointer when over the mode line.\n\
11516 This variable takes effect when you create a new frame\n\
11517 or when you set the mouse color.");
11518 #endif
11519 Vx_mode_pointer_shape = Qnil;
11521 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11522 &Vx_sensitive_text_pointer_shape,
11523 "The shape of the pointer when over mouse-sensitive text.\n\
11524 This variable takes effect when you create a new frame\n\
11525 or when you set the mouse color.");
11526 Vx_sensitive_text_pointer_shape = Qnil;
11528 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11529 &Vx_window_horizontal_drag_shape,
11530 "Pointer shape to use for indicating a window can be dragged horizontally.\n\
11531 This variable takes effect when you create a new frame\n\
11532 or when you set the mouse color.");
11533 Vx_window_horizontal_drag_shape = Qnil;
11535 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11536 "A string indicating the foreground color of the cursor box.");
11537 Vx_cursor_fore_pixel = Qnil;
11539 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11540 "Non-nil if no X window manager is in use.\n\
11541 Emacs doesn't try to figure this out; this is always nil\n\
11542 unless you set it to something else.");
11543 /* We don't have any way to find this out, so set it to nil
11544 and maybe the user would like to set it to t. */
11545 Vx_no_window_manager = Qnil;
11547 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11548 &Vx_pixel_size_width_font_regexp,
11549 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11551 Since Emacs gets width of a font matching with this regexp from\n\
11552 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11553 such a font. This is especially effective for such large fonts as\n\
11554 Chinese, Japanese, and Korean.");
11555 Vx_pixel_size_width_font_regexp = Qnil;
11557 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11558 "Time after which cached images are removed from the cache.\n\
11559 When an image has not been displayed this many seconds, remove it\n\
11560 from the image cache. Value must be an integer or nil with nil\n\
11561 meaning don't clear the cache.");
11562 Vimage_cache_eviction_delay = make_number (30 * 60);
11564 #ifdef USE_X_TOOLKIT
11565 Fprovide (intern ("x-toolkit"));
11567 #ifdef USE_MOTIF
11568 Fprovide (intern ("motif"));
11570 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
11571 "Version info for LessTif/Motif.");
11572 Vmotif_version_string = build_string (XmVERSION_STRING);
11573 #endif /* USE_MOTIF */
11574 #endif /* USE_X_TOOLKIT */
11576 defsubr (&Sx_get_resource);
11578 /* X window properties. */
11579 defsubr (&Sx_change_window_property);
11580 defsubr (&Sx_delete_window_property);
11581 defsubr (&Sx_window_property);
11583 defsubr (&Sxw_display_color_p);
11584 defsubr (&Sx_display_grayscale_p);
11585 defsubr (&Sxw_color_defined_p);
11586 defsubr (&Sxw_color_values);
11587 defsubr (&Sx_server_max_request_size);
11588 defsubr (&Sx_server_vendor);
11589 defsubr (&Sx_server_version);
11590 defsubr (&Sx_display_pixel_width);
11591 defsubr (&Sx_display_pixel_height);
11592 defsubr (&Sx_display_mm_width);
11593 defsubr (&Sx_display_mm_height);
11594 defsubr (&Sx_display_screens);
11595 defsubr (&Sx_display_planes);
11596 defsubr (&Sx_display_color_cells);
11597 defsubr (&Sx_display_visual_class);
11598 defsubr (&Sx_display_backing_store);
11599 defsubr (&Sx_display_save_under);
11600 defsubr (&Sx_parse_geometry);
11601 defsubr (&Sx_create_frame);
11602 defsubr (&Sx_open_connection);
11603 defsubr (&Sx_close_connection);
11604 defsubr (&Sx_display_list);
11605 defsubr (&Sx_synchronize);
11606 defsubr (&Sx_focus_frame);
11607 defsubr (&Sx_backspace_delete_keys_p);
11609 /* Setting callback functions for fontset handler. */
11610 get_font_info_func = x_get_font_info;
11612 #if 0 /* This function pointer doesn't seem to be used anywhere.
11613 And the pointer assigned has the wrong type, anyway. */
11614 list_fonts_func = x_list_fonts;
11615 #endif
11617 load_font_func = x_load_font;
11618 find_ccl_program_func = x_find_ccl_program;
11619 query_font_func = x_query_font;
11620 set_frame_fontset_func = x_set_font;
11621 check_window_system_func = check_x;
11623 /* Images. */
11624 Qxbm = intern ("xbm");
11625 staticpro (&Qxbm);
11626 QCtype = intern (":type");
11627 staticpro (&QCtype);
11628 QCconversion = intern (":conversion");
11629 staticpro (&QCconversion);
11630 QCheuristic_mask = intern (":heuristic-mask");
11631 staticpro (&QCheuristic_mask);
11632 QCcolor_symbols = intern (":color-symbols");
11633 staticpro (&QCcolor_symbols);
11634 QCascent = intern (":ascent");
11635 staticpro (&QCascent);
11636 QCmargin = intern (":margin");
11637 staticpro (&QCmargin);
11638 QCrelief = intern (":relief");
11639 staticpro (&QCrelief);
11640 Qpostscript = intern ("postscript");
11641 staticpro (&Qpostscript);
11642 QCloader = intern (":loader");
11643 staticpro (&QCloader);
11644 QCbounding_box = intern (":bounding-box");
11645 staticpro (&QCbounding_box);
11646 QCpt_width = intern (":pt-width");
11647 staticpro (&QCpt_width);
11648 QCpt_height = intern (":pt-height");
11649 staticpro (&QCpt_height);
11650 QCindex = intern (":index");
11651 staticpro (&QCindex);
11652 Qpbm = intern ("pbm");
11653 staticpro (&Qpbm);
11655 #if HAVE_XPM
11656 Qxpm = intern ("xpm");
11657 staticpro (&Qxpm);
11658 #endif
11660 #if HAVE_JPEG
11661 Qjpeg = intern ("jpeg");
11662 staticpro (&Qjpeg);
11663 #endif
11665 #if HAVE_TIFF
11666 Qtiff = intern ("tiff");
11667 staticpro (&Qtiff);
11668 #endif
11670 #if HAVE_GIF
11671 Qgif = intern ("gif");
11672 staticpro (&Qgif);
11673 #endif
11675 #if HAVE_PNG
11676 Qpng = intern ("png");
11677 staticpro (&Qpng);
11678 #endif
11680 defsubr (&Sclear_image_cache);
11681 defsubr (&Simage_size);
11682 defsubr (&Simage_mask_p);
11684 hourglass_atimer = NULL;
11685 hourglass_shown_p = 0;
11687 defsubr (&Sx_show_tip);
11688 defsubr (&Sx_hide_tip);
11689 tip_timer = Qnil;
11690 staticpro (&tip_timer);
11691 tip_frame = Qnil;
11692 staticpro (&tip_frame);
11694 last_show_tip_args = Qnil;
11695 staticpro (&last_show_tip_args);
11697 #ifdef USE_MOTIF
11698 defsubr (&Sx_file_dialog);
11699 #endif
11703 void
11704 init_xfns ()
11706 image_types = NULL;
11707 Vimage_types = Qnil;
11709 define_image_type (&xbm_type);
11710 define_image_type (&gs_type);
11711 define_image_type (&pbm_type);
11713 #if HAVE_XPM
11714 define_image_type (&xpm_type);
11715 #endif
11717 #if HAVE_JPEG
11718 define_image_type (&jpeg_type);
11719 #endif
11721 #if HAVE_TIFF
11722 define_image_type (&tiff_type);
11723 #endif
11725 #if HAVE_GIF
11726 define_image_type (&gif_type);
11727 #endif
11729 #if HAVE_PNG
11730 define_image_type (&png_type);
11731 #endif
11734 #endif /* HAVE_X_WINDOWS */