Mention `delete-frame-functions' replacing `delete-frame-hook',
[emacs.git] / src / xfns.c
blobc20c0d0480d20c6297f25e33685177a40d757549
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
35 #include "lisp.h"
36 #include "xterm.h"
37 #include "frame.h"
38 #include "window.h"
39 #include "buffer.h"
40 #include "intervals.h"
41 #include "dispextern.h"
42 #include "keyboard.h"
43 #include "blockinput.h"
44 #include <epaths.h>
45 #include "charset.h"
46 #include "coding.h"
47 #include "fontset.h"
48 #include "systime.h"
49 #include "termhooks.h"
50 #include "atimer.h"
52 #ifdef HAVE_X_WINDOWS
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
58 #ifndef VMS
59 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
60 #include "bitmaps/gray.xbm"
61 #else
62 #include <X11/bitmaps/gray>
63 #endif
64 #else
65 #include "[.bitmaps]gray.xbm"
66 #endif
68 #ifdef USE_X_TOOLKIT
69 #include <X11/Shell.h>
71 #ifndef USE_MOTIF
72 #include <X11/Xaw/Paned.h>
73 #include <X11/Xaw/Label.h>
74 #endif /* USE_MOTIF */
76 #ifdef USG
77 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
78 #include <X11/Xos.h>
79 #define USG
80 #else
81 #include <X11/Xos.h>
82 #endif
84 #include "widget.h"
86 #include "../lwlib/lwlib.h"
88 #ifdef USE_MOTIF
89 #include <Xm/Xm.h>
90 #include <Xm/DialogS.h>
91 #include <Xm/FileSB.h>
92 #endif
94 /* Do the EDITRES protocol if running X11R5
95 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
98 #define HACK_EDITRES
99 extern void _XEditResCheckMessages ();
100 #endif /* R5 + Athena */
102 /* Unique id counter for widgets created by the Lucid Widget Library. */
104 extern LWLIB_ID widget_id_tick;
106 #ifdef USE_LUCID
107 /* This is part of a kludge--see lwlib/xlwmenu.c. */
108 extern XFontStruct *xlwmenu_default_font;
109 #endif
111 extern void free_frame_menubar ();
112 extern double atof ();
114 #ifdef USE_MOTIF
116 /* LessTif/Motif version info. */
118 static Lisp_Object Vmotif_version_string;
120 #endif /* USE_MOTIF */
122 #endif /* USE_X_TOOLKIT */
124 #ifdef HAVE_X11R4
125 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
126 #else
127 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
128 #endif
130 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
131 it, and including `bitmaps/gray' more than once is a problem when
132 config.h defines `static' as an empty replacement string. */
134 int gray_bitmap_width = gray_width;
135 int gray_bitmap_height = gray_height;
136 char *gray_bitmap_bits = gray_bits;
138 /* The name we're using in resource queries. Most often "emacs". */
140 Lisp_Object Vx_resource_name;
142 /* The application class we're using in resource queries.
143 Normally "Emacs". */
145 Lisp_Object Vx_resource_class;
147 /* Non-zero means we're allowed to display an hourglass cursor. */
149 int display_hourglass_p;
151 /* The background and shape of the mouse pointer, and shape when not
152 over text or in the modeline. */
154 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
155 Lisp_Object Vx_hourglass_pointer_shape;
157 /* The shape when over mouse-sensitive text. */
159 Lisp_Object Vx_sensitive_text_pointer_shape;
161 /* If non-nil, the pointer shape to indicate that windows can be
162 dragged horizontally. */
164 Lisp_Object Vx_window_horizontal_drag_shape;
166 /* Color of chars displayed in cursor box. */
168 Lisp_Object Vx_cursor_fore_pixel;
170 /* Nonzero if using X. */
172 static int x_in_use;
174 /* Non nil if no window manager is in use. */
176 Lisp_Object Vx_no_window_manager;
178 /* Search path for bitmap files. */
180 Lisp_Object Vx_bitmap_file_path;
182 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
184 Lisp_Object Vx_pixel_size_width_font_regexp;
186 Lisp_Object Qauto_raise;
187 Lisp_Object Qauto_lower;
188 Lisp_Object Qborder_color;
189 Lisp_Object Qborder_width;
190 extern Lisp_Object Qbox;
191 Lisp_Object Qcursor_color;
192 Lisp_Object Qcursor_type;
193 Lisp_Object Qgeometry;
194 Lisp_Object Qicon_left;
195 Lisp_Object Qicon_top;
196 Lisp_Object Qicon_type;
197 Lisp_Object Qicon_name;
198 Lisp_Object Qinternal_border_width;
199 Lisp_Object Qleft;
200 Lisp_Object Qright;
201 Lisp_Object Qmouse_color;
202 Lisp_Object Qnone;
203 Lisp_Object Qouter_window_id;
204 Lisp_Object Qparent_id;
205 Lisp_Object Qscroll_bar_width;
206 Lisp_Object Qsuppress_icon;
207 extern Lisp_Object Qtop;
208 Lisp_Object Qundefined_color;
209 Lisp_Object Qvertical_scroll_bars;
210 Lisp_Object Qvisibility;
211 Lisp_Object Qwindow_id;
212 Lisp_Object Qx_frame_parameter;
213 Lisp_Object Qx_resource_name;
214 Lisp_Object Quser_position;
215 Lisp_Object Quser_size;
216 extern Lisp_Object Qdisplay;
217 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
218 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
219 Lisp_Object Qcompound_text, Qcancel_timer;
220 Lisp_Object Qwait_for_wm;
221 Lisp_Object Qfullscreen;
222 Lisp_Object Qfullwidth;
223 Lisp_Object Qfullheight;
224 Lisp_Object Qfullboth;
226 /* The below are defined in frame.c. */
228 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
229 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
230 extern Lisp_Object Qtool_bar_lines;
232 extern Lisp_Object Vwindow_system_version;
234 Lisp_Object Qface_set_after_frame_default;
236 #if GLYPH_DEBUG
237 int image_cache_refcount, dpyinfo_refcount;
238 #endif
242 /* Error if we are not connected to X. */
244 void
245 check_x ()
247 if (! x_in_use)
248 error ("X windows are not in use or not initialized");
251 /* Nonzero if we can use mouse menus.
252 You should not call this unless HAVE_MENUS is defined. */
255 have_menus_p ()
257 return x_in_use;
260 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
261 and checking validity for X. */
263 FRAME_PTR
264 check_x_frame (frame)
265 Lisp_Object frame;
267 FRAME_PTR f;
269 if (NILP (frame))
270 frame = selected_frame;
271 CHECK_LIVE_FRAME (frame);
272 f = XFRAME (frame);
273 if (! FRAME_X_P (f))
274 error ("Non-X frame used");
275 return f;
278 /* Let the user specify an X display with a frame.
279 nil stands for the selected frame--or, if that is not an X frame,
280 the first X display on the list. */
282 static struct x_display_info *
283 check_x_display_info (frame)
284 Lisp_Object frame;
286 struct x_display_info *dpyinfo = NULL;
288 if (NILP (frame))
290 struct frame *sf = XFRAME (selected_frame);
292 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
293 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
294 else if (x_display_list != 0)
295 dpyinfo = x_display_list;
296 else
297 error ("X windows are not in use or not initialized");
299 else if (STRINGP (frame))
300 dpyinfo = x_display_info_for_name (frame);
301 else
303 FRAME_PTR f = check_x_frame (frame);
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 *) SDATA (file)))
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, Qnil, &found, Qnil);
647 if (fd < 0)
648 return -1;
649 emacs_close (fd);
651 filename = (char *) SDATA (found);
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 (SBYTES (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, SDATA (file));
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 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
732 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
733 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
734 static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
735 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
736 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
742 static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
743 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
744 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
745 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
746 Lisp_Object));
747 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
748 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
749 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
750 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
751 Lisp_Object));
752 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
759 Lisp_Object));
760 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
761 Lisp_Object));
762 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
763 Lisp_Object,
764 Lisp_Object,
765 char *, char *,
766 int));
767 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
768 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
769 Lisp_Object));
770 static void init_color_table P_ ((void));
771 static void free_color_table P_ ((void));
772 static unsigned long *colors_in_color_table P_ ((int *n));
773 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
774 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
778 static struct x_frame_parm_table x_frame_parms[] =
780 {"auto-raise", x_set_autoraise},
781 {"auto-lower", x_set_autolower},
782 {"background-color", x_set_background_color},
783 {"border-color", x_set_border_color},
784 {"border-width", x_set_border_width},
785 {"cursor-color", x_set_cursor_color},
786 {"cursor-type", x_set_cursor_type},
787 {"font", x_set_font},
788 {"foreground-color", x_set_foreground_color},
789 {"icon-name", x_set_icon_name},
790 {"icon-type", x_set_icon_type},
791 {"internal-border-width", x_set_internal_border_width},
792 {"menu-bar-lines", x_set_menu_bar_lines},
793 {"mouse-color", x_set_mouse_color},
794 {"name", x_explicitly_set_name},
795 {"scroll-bar-width", x_set_scroll_bar_width},
796 {"title", x_set_title},
797 {"unsplittable", x_set_unsplittable},
798 {"vertical-scroll-bars", x_set_vertical_scroll_bars},
799 {"visibility", x_set_visibility},
800 {"tool-bar-lines", x_set_tool_bar_lines},
801 {"scroll-bar-foreground", x_set_scroll_bar_foreground},
802 {"scroll-bar-background", x_set_scroll_bar_background},
803 {"screen-gamma", x_set_screen_gamma},
804 {"line-spacing", x_set_line_spacing},
805 {"left-fringe", x_set_fringe_width},
806 {"right-fringe", x_set_fringe_width},
807 {"wait-for-wm", x_set_wait_for_wm},
808 {"fullscreen", x_set_fullscreen},
812 /* Attach the `x-frame-parameter' properties to
813 the Lisp symbol names of parameters relevant to X. */
815 void
816 init_x_parm_symbols ()
818 int i;
820 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
821 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
822 make_number (i));
826 /* Really try to move where we want to be in case of fullscreen. Some WMs
827 moves the window where we tell them. Some (mwm, twm) moves the outer
828 window manager window there instead.
829 Try to compensate for those WM here. */
830 static void
831 x_fullscreen_move (f, new_top, new_left)
832 struct frame *f;
833 int new_top;
834 int new_left;
836 if (new_top != f->output_data.x->top_pos
837 || new_left != f->output_data.x->left_pos)
839 int move_x = new_left + f->output_data.x->x_pixels_outer_diff;
840 int move_y = new_top + f->output_data.x->y_pixels_outer_diff;
842 f->output_data.x->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
843 x_set_offset (f, move_x, move_y, 1);
847 /* Change the parameters of frame F as specified by ALIST.
848 If a parameter is not specially recognized, do nothing special;
849 otherwise call the `x_set_...' function for that parameter.
850 Except for certain geometry properties, always call store_frame_param
851 to store the new value in the parameter alist. */
853 void
854 x_set_frame_parameters (f, alist)
855 FRAME_PTR f;
856 Lisp_Object alist;
858 Lisp_Object tail;
860 /* If both of these parameters are present, it's more efficient to
861 set them both at once. So we wait until we've looked at the
862 entire list before we set them. */
863 int width, height;
865 /* Same here. */
866 Lisp_Object left, top;
868 /* Same with these. */
869 Lisp_Object icon_left, icon_top;
871 /* Record in these vectors all the parms specified. */
872 Lisp_Object *parms;
873 Lisp_Object *values;
874 int i, p;
875 int left_no_change = 0, top_no_change = 0;
876 int icon_left_no_change = 0, icon_top_no_change = 0;
877 int fullscreen_is_being_set = 0;
879 struct gcpro gcpro1, gcpro2;
881 i = 0;
882 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
883 i++;
885 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
886 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
888 /* Extract parm names and values into those vectors. */
890 i = 0;
891 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
893 Lisp_Object elt;
895 elt = Fcar (tail);
896 parms[i] = Fcar (elt);
897 values[i] = Fcdr (elt);
898 i++;
900 /* TAIL and ALIST are not used again below here. */
901 alist = tail = Qnil;
903 GCPRO2 (*parms, *values);
904 gcpro1.nvars = i;
905 gcpro2.nvars = i;
907 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
908 because their values appear in VALUES and strings are not valid. */
909 top = left = Qunbound;
910 icon_left = icon_top = Qunbound;
912 /* Provide default values for HEIGHT and WIDTH. */
913 if (FRAME_NEW_WIDTH (f))
914 width = FRAME_NEW_WIDTH (f);
915 else
916 width = FRAME_WIDTH (f);
918 if (FRAME_NEW_HEIGHT (f))
919 height = FRAME_NEW_HEIGHT (f);
920 else
921 height = FRAME_HEIGHT (f);
923 /* Process foreground_color and background_color before anything else.
924 They are independent of other properties, but other properties (e.g.,
925 cursor_color) are dependent upon them. */
926 /* Process default font as well, since fringe widths depends on it. */
927 /* Also, process fullscreen, width and height depend upon that */
928 for (p = 0; p < i; p++)
930 Lisp_Object prop, val;
932 prop = parms[p];
933 val = values[p];
934 if (EQ (prop, Qforeground_color)
935 || EQ (prop, Qbackground_color)
936 || EQ (prop, Qfont)
937 || EQ (prop, Qfullscreen))
939 register Lisp_Object param_index, old_value;
941 old_value = get_frame_param (f, prop);
942 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
944 if (NILP (Fequal (val, old_value)))
946 store_frame_param (f, prop, val);
948 param_index = Fget (prop, Qx_frame_parameter);
949 if (NATNUMP (param_index)
950 && (XFASTINT (param_index)
951 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
952 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
957 /* Now process them in reverse of specified order. */
958 for (i--; i >= 0; i--)
960 Lisp_Object prop, val;
962 prop = parms[i];
963 val = values[i];
965 if (EQ (prop, Qwidth) && NUMBERP (val))
966 width = XFASTINT (val);
967 else if (EQ (prop, Qheight) && NUMBERP (val))
968 height = XFASTINT (val);
969 else if (EQ (prop, Qtop))
970 top = val;
971 else if (EQ (prop, Qleft))
972 left = val;
973 else if (EQ (prop, Qicon_top))
974 icon_top = val;
975 else if (EQ (prop, Qicon_left))
976 icon_left = val;
977 else if (EQ (prop, Qforeground_color)
978 || EQ (prop, Qbackground_color)
979 || EQ (prop, Qfont)
980 || EQ (prop, Qfullscreen))
981 /* Processed above. */
982 continue;
983 else
985 register Lisp_Object param_index, old_value;
987 old_value = get_frame_param (f, prop);
989 store_frame_param (f, prop, val);
991 param_index = Fget (prop, Qx_frame_parameter);
992 if (NATNUMP (param_index)
993 && (XFASTINT (param_index)
994 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
995 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
999 /* Don't die if just one of these was set. */
1000 if (EQ (left, Qunbound))
1002 left_no_change = 1;
1003 if (f->output_data.x->left_pos < 0)
1004 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
1005 else
1006 XSETINT (left, f->output_data.x->left_pos);
1008 if (EQ (top, Qunbound))
1010 top_no_change = 1;
1011 if (f->output_data.x->top_pos < 0)
1012 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
1013 else
1014 XSETINT (top, f->output_data.x->top_pos);
1017 /* If one of the icon positions was not set, preserve or default it. */
1018 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
1020 icon_left_no_change = 1;
1021 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
1022 if (NILP (icon_left))
1023 XSETINT (icon_left, 0);
1025 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
1027 icon_top_no_change = 1;
1028 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
1029 if (NILP (icon_top))
1030 XSETINT (icon_top, 0);
1033 if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
1035 /* If the frame is visible already and the fullscreen parameter is
1036 being set, it is too late to set WM manager hints to specify
1037 size and position.
1038 Here we first get the width, height and position that applies to
1039 fullscreen. We then move the frame to the appropriate
1040 position. Resize of the frame is taken care of in the code after
1041 this if-statement. */
1042 int new_left, new_top;
1044 x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
1045 x_fullscreen_move (f, new_top, new_left);
1048 /* Don't set these parameters unless they've been explicitly
1049 specified. The window might be mapped or resized while we're in
1050 this function, and we don't want to override that unless the lisp
1051 code has asked for it.
1053 Don't set these parameters unless they actually differ from the
1054 window's current parameters; the window may not actually exist
1055 yet. */
1057 Lisp_Object frame;
1059 check_frame_size (f, &height, &width);
1061 XSETFRAME (frame, f);
1063 if (width != FRAME_WIDTH (f)
1064 || height != FRAME_HEIGHT (f)
1065 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1066 Fset_frame_size (frame, make_number (width), make_number (height));
1068 if ((!NILP (left) || !NILP (top))
1069 && ! (left_no_change && top_no_change)
1070 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1071 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1073 int leftpos = 0;
1074 int toppos = 0;
1076 /* Record the signs. */
1077 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1078 if (EQ (left, Qminus))
1079 f->output_data.x->size_hint_flags |= XNegative;
1080 else if (INTEGERP (left))
1082 leftpos = XINT (left);
1083 if (leftpos < 0)
1084 f->output_data.x->size_hint_flags |= XNegative;
1086 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1087 && CONSP (XCDR (left))
1088 && INTEGERP (XCAR (XCDR (left))))
1090 leftpos = - XINT (XCAR (XCDR (left)));
1091 f->output_data.x->size_hint_flags |= XNegative;
1093 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1094 && CONSP (XCDR (left))
1095 && INTEGERP (XCAR (XCDR (left))))
1097 leftpos = XINT (XCAR (XCDR (left)));
1100 if (EQ (top, Qminus))
1101 f->output_data.x->size_hint_flags |= YNegative;
1102 else if (INTEGERP (top))
1104 toppos = XINT (top);
1105 if (toppos < 0)
1106 f->output_data.x->size_hint_flags |= YNegative;
1108 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1109 && CONSP (XCDR (top))
1110 && INTEGERP (XCAR (XCDR (top))))
1112 toppos = - XINT (XCAR (XCDR (top)));
1113 f->output_data.x->size_hint_flags |= YNegative;
1115 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1116 && CONSP (XCDR (top))
1117 && INTEGERP (XCAR (XCDR (top))))
1119 toppos = XINT (XCAR (XCDR (top)));
1123 /* Store the numeric value of the position. */
1124 f->output_data.x->top_pos = toppos;
1125 f->output_data.x->left_pos = leftpos;
1127 f->output_data.x->win_gravity = NorthWestGravity;
1129 /* Actually set that position, and convert to absolute. */
1130 x_set_offset (f, leftpos, toppos, -1);
1133 if ((!NILP (icon_left) || !NILP (icon_top))
1134 && ! (icon_left_no_change && icon_top_no_change))
1135 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1138 UNGCPRO;
1141 /* Store the screen positions of frame F into XPTR and YPTR.
1142 These are the positions of the containing window manager window,
1143 not Emacs's own window. */
1145 void
1146 x_real_positions (f, xptr, yptr)
1147 FRAME_PTR f;
1148 int *xptr, *yptr;
1150 int win_x, win_y, outer_x, outer_y;
1151 int real_x = 0, real_y = 0;
1152 int had_errors = 0;
1153 Window win = f->output_data.x->parent_desc;
1155 int count;
1157 BLOCK_INPUT;
1159 count = x_catch_errors (FRAME_X_DISPLAY (f));
1161 if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
1162 win = FRAME_OUTER_WINDOW (f);
1164 /* This loop traverses up the containment tree until we hit the root
1165 window. Window managers may intersect many windows between our window
1166 and the root window. The window we find just before the root window
1167 should be the outer WM window. */
1168 for (;;)
1170 Window wm_window, rootw;
1171 Window *tmp_children;
1172 unsigned int tmp_nchildren;
1173 int success;
1175 success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
1176 &wm_window, &tmp_children, &tmp_nchildren);
1178 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
1180 /* Don't free tmp_children if XQueryTree failed. */
1181 if (! success)
1182 break;
1184 XFree ((char *) tmp_children);
1186 if (wm_window == rootw || had_errors)
1187 break;
1189 win = wm_window;
1192 if (! had_errors)
1194 int ign;
1195 Window child, rootw;
1197 /* Get the real coordinates for the WM window upper left corner */
1198 XGetGeometry (FRAME_X_DISPLAY (f), win,
1199 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
1201 /* Translate real coordinates to coordinates relative to our
1202 window. For our window, the upper left corner is 0, 0.
1203 Since the upper left corner of the WM window is outside
1204 our window, win_x and win_y will be negative:
1206 ------------------ ---> x
1207 | title |
1208 | ----------------- v y
1209 | | our window
1211 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1213 /* From-window, to-window. */
1214 FRAME_X_DISPLAY_INFO (f)->root_window,
1215 FRAME_X_WINDOW (f),
1217 /* From-position, to-position. */
1218 real_x, real_y, &win_x, &win_y,
1220 /* Child of win. */
1221 &child);
1223 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
1225 outer_x = win_x;
1226 outer_y = win_y;
1228 else
1230 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1232 /* From-window, to-window. */
1233 FRAME_X_DISPLAY_INFO (f)->root_window,
1234 FRAME_OUTER_WINDOW (f),
1236 /* From-position, to-position. */
1237 real_x, real_y, &outer_x, &outer_y,
1239 /* Child of win. */
1240 &child);
1243 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
1246 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1248 UNBLOCK_INPUT;
1250 if (had_errors) return;
1252 f->output_data.x->x_pixels_diff = -win_x;
1253 f->output_data.x->y_pixels_diff = -win_y;
1254 f->output_data.x->x_pixels_outer_diff = -outer_x;
1255 f->output_data.x->y_pixels_outer_diff = -outer_y;
1257 *xptr = real_x;
1258 *yptr = real_y;
1261 /* Insert a description of internally-recorded parameters of frame X
1262 into the parameter alist *ALISTPTR that is to be given to the user.
1263 Only parameters that are specific to the X window system
1264 and whose values are not correctly recorded in the frame's
1265 param_alist need to be considered here. */
1267 void
1268 x_report_frame_params (f, alistptr)
1269 struct frame *f;
1270 Lisp_Object *alistptr;
1272 char buf[16];
1273 Lisp_Object tem;
1275 /* Represent negative positions (off the top or left screen edge)
1276 in a way that Fmodify_frame_parameters will understand correctly. */
1277 XSETINT (tem, f->output_data.x->left_pos);
1278 if (f->output_data.x->left_pos >= 0)
1279 store_in_alist (alistptr, Qleft, tem);
1280 else
1281 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1283 XSETINT (tem, f->output_data.x->top_pos);
1284 if (f->output_data.x->top_pos >= 0)
1285 store_in_alist (alistptr, Qtop, tem);
1286 else
1287 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1289 store_in_alist (alistptr, Qborder_width,
1290 make_number (f->output_data.x->border_width));
1291 store_in_alist (alistptr, Qinternal_border_width,
1292 make_number (f->output_data.x->internal_border_width));
1293 store_in_alist (alistptr, Qleft_fringe,
1294 make_number (f->output_data.x->left_fringe_width));
1295 store_in_alist (alistptr, Qright_fringe,
1296 make_number (f->output_data.x->right_fringe_width));
1297 store_in_alist (alistptr, Qscroll_bar_width,
1298 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
1299 ? make_number (0)
1300 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
1301 ? make_number (FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
1302 /* nil means "use default width"
1303 for non-toolkit scroll bar.
1304 ruler-mode.el depends on this. */
1305 : Qnil));
1306 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1307 store_in_alist (alistptr, Qwindow_id,
1308 build_string (buf));
1309 #ifdef USE_X_TOOLKIT
1310 /* Tooltip frame may not have this widget. */
1311 if (f->output_data.x->widget)
1312 #endif
1313 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1314 store_in_alist (alistptr, Qouter_window_id,
1315 build_string (buf));
1316 store_in_alist (alistptr, Qicon_name, f->icon_name);
1317 FRAME_SAMPLE_VISIBILITY (f);
1318 store_in_alist (alistptr, Qvisibility,
1319 (FRAME_VISIBLE_P (f) ? Qt
1320 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1321 store_in_alist (alistptr, Qdisplay,
1322 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1324 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1325 tem = Qnil;
1326 else
1327 XSETFASTINT (tem, f->output_data.x->parent_desc);
1328 store_in_alist (alistptr, Qparent_id, tem);
1333 /* Gamma-correct COLOR on frame F. */
1335 void
1336 gamma_correct (f, color)
1337 struct frame *f;
1338 XColor *color;
1340 if (f->gamma)
1342 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1343 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1344 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1349 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1350 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1351 allocate the color. Value is zero if COLOR_NAME is invalid, or
1352 no color could be allocated. */
1355 x_defined_color (f, color_name, color, alloc_p)
1356 struct frame *f;
1357 char *color_name;
1358 XColor *color;
1359 int alloc_p;
1361 int success_p;
1362 Display *dpy = FRAME_X_DISPLAY (f);
1363 Colormap cmap = FRAME_X_COLORMAP (f);
1365 BLOCK_INPUT;
1366 success_p = XParseColor (dpy, cmap, color_name, color);
1367 if (success_p && alloc_p)
1368 success_p = x_alloc_nearest_color (f, cmap, color);
1369 UNBLOCK_INPUT;
1371 return success_p;
1375 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1376 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1377 Signal an error if color can't be allocated. */
1380 x_decode_color (f, color_name, mono_color)
1381 FRAME_PTR f;
1382 Lisp_Object color_name;
1383 int mono_color;
1385 XColor cdef;
1387 CHECK_STRING (color_name);
1389 #if 0 /* Don't do this. It's wrong when we're not using the default
1390 colormap, it makes freeing difficult, and it's probably not
1391 an important optimization. */
1392 if (strcmp (SDATA (color_name), "black") == 0)
1393 return BLACK_PIX_DEFAULT (f);
1394 else if (strcmp (SDATA (color_name), "white") == 0)
1395 return WHITE_PIX_DEFAULT (f);
1396 #endif
1398 /* Return MONO_COLOR for monochrome frames. */
1399 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1400 return mono_color;
1402 /* x_defined_color is responsible for coping with failures
1403 by looking for a near-miss. */
1404 if (x_defined_color (f, SDATA (color_name), &cdef, 1))
1405 return cdef.pixel;
1407 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1408 Fcons (color_name, Qnil)));
1409 return 0;
1414 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1415 the previous value of that parameter, NEW_VALUE is the new value. */
1417 static void
1418 x_set_line_spacing (f, new_value, old_value)
1419 struct frame *f;
1420 Lisp_Object new_value, old_value;
1422 if (NILP (new_value))
1423 f->extra_line_spacing = 0;
1424 else if (NATNUMP (new_value))
1425 f->extra_line_spacing = XFASTINT (new_value);
1426 else
1427 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1428 Fcons (new_value, Qnil)));
1429 if (FRAME_VISIBLE_P (f))
1430 redraw_frame (f);
1434 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
1435 the previous value of that parameter, NEW_VALUE is the new value.
1436 See also the comment of wait_for_wm in struct x_output. */
1438 static void
1439 x_set_wait_for_wm (f, new_value, old_value)
1440 struct frame *f;
1441 Lisp_Object new_value, old_value;
1443 f->output_data.x->wait_for_wm = !NILP (new_value);
1447 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
1448 the previous value of that parameter, NEW_VALUE is the new value. */
1450 static void
1451 x_set_fullscreen (f, new_value, old_value)
1452 struct frame *f;
1453 Lisp_Object new_value, old_value;
1455 if (NILP (new_value))
1456 f->output_data.x->want_fullscreen = FULLSCREEN_NONE;
1457 else if (EQ (new_value, Qfullboth))
1458 f->output_data.x->want_fullscreen = FULLSCREEN_BOTH;
1459 else if (EQ (new_value, Qfullwidth))
1460 f->output_data.x->want_fullscreen = FULLSCREEN_WIDTH;
1461 else if (EQ (new_value, Qfullheight))
1462 f->output_data.x->want_fullscreen = FULLSCREEN_HEIGHT;
1466 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1467 the previous value of that parameter, NEW_VALUE is the new
1468 value. */
1470 static void
1471 x_set_screen_gamma (f, new_value, old_value)
1472 struct frame *f;
1473 Lisp_Object new_value, old_value;
1475 if (NILP (new_value))
1476 f->gamma = 0;
1477 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1478 /* The value 0.4545 is the normal viewing gamma. */
1479 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1480 else
1481 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1482 Fcons (new_value, Qnil)));
1484 clear_face_cache (0);
1488 /* Functions called only from `x_set_frame_param'
1489 to set individual parameters.
1491 If FRAME_X_WINDOW (f) is 0,
1492 the frame is being created and its X-window does not exist yet.
1493 In that case, just record the parameter's new value
1494 in the standard place; do not attempt to change the window. */
1496 void
1497 x_set_foreground_color (f, arg, oldval)
1498 struct frame *f;
1499 Lisp_Object arg, oldval;
1501 struct x_output *x = f->output_data.x;
1502 unsigned long fg, old_fg;
1504 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1505 old_fg = x->foreground_pixel;
1506 x->foreground_pixel = fg;
1508 if (FRAME_X_WINDOW (f) != 0)
1510 Display *dpy = FRAME_X_DISPLAY (f);
1512 BLOCK_INPUT;
1513 XSetForeground (dpy, x->normal_gc, fg);
1514 XSetBackground (dpy, x->reverse_gc, fg);
1516 if (x->cursor_pixel == old_fg)
1518 unload_color (f, x->cursor_pixel);
1519 x->cursor_pixel = x_copy_color (f, fg);
1520 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1523 UNBLOCK_INPUT;
1525 update_face_from_frame_parameter (f, Qforeground_color, arg);
1527 if (FRAME_VISIBLE_P (f))
1528 redraw_frame (f);
1531 unload_color (f, old_fg);
1534 void
1535 x_set_background_color (f, arg, oldval)
1536 struct frame *f;
1537 Lisp_Object arg, oldval;
1539 struct x_output *x = f->output_data.x;
1540 unsigned long bg;
1542 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1543 unload_color (f, x->background_pixel);
1544 x->background_pixel = bg;
1546 if (FRAME_X_WINDOW (f) != 0)
1548 Display *dpy = FRAME_X_DISPLAY (f);
1550 BLOCK_INPUT;
1551 XSetBackground (dpy, x->normal_gc, bg);
1552 XSetForeground (dpy, x->reverse_gc, bg);
1553 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1554 XSetForeground (dpy, x->cursor_gc, bg);
1556 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1557 toolkit scroll bars. */
1559 Lisp_Object bar;
1560 for (bar = FRAME_SCROLL_BARS (f);
1561 !NILP (bar);
1562 bar = XSCROLL_BAR (bar)->next)
1564 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1565 XSetWindowBackground (dpy, window, bg);
1568 #endif /* USE_TOOLKIT_SCROLL_BARS */
1570 UNBLOCK_INPUT;
1571 update_face_from_frame_parameter (f, Qbackground_color, arg);
1573 if (FRAME_VISIBLE_P (f))
1574 redraw_frame (f);
1578 void
1579 x_set_mouse_color (f, arg, oldval)
1580 struct frame *f;
1581 Lisp_Object arg, oldval;
1583 struct x_output *x = f->output_data.x;
1584 Display *dpy = FRAME_X_DISPLAY (f);
1585 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1586 Cursor hourglass_cursor, horizontal_drag_cursor;
1587 int count;
1588 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1589 unsigned long mask_color = x->background_pixel;
1591 /* Don't let pointers be invisible. */
1592 if (mask_color == pixel)
1594 x_free_colors (f, &pixel, 1);
1595 pixel = x_copy_color (f, x->foreground_pixel);
1598 unload_color (f, x->mouse_pixel);
1599 x->mouse_pixel = pixel;
1601 BLOCK_INPUT;
1603 /* It's not okay to crash if the user selects a screwy cursor. */
1604 count = x_catch_errors (dpy);
1606 if (!NILP (Vx_pointer_shape))
1608 CHECK_NUMBER (Vx_pointer_shape);
1609 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1611 else
1612 cursor = XCreateFontCursor (dpy, XC_xterm);
1613 x_check_errors (dpy, "bad text pointer cursor: %s");
1615 if (!NILP (Vx_nontext_pointer_shape))
1617 CHECK_NUMBER (Vx_nontext_pointer_shape);
1618 nontext_cursor
1619 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1621 else
1622 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1623 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1625 if (!NILP (Vx_hourglass_pointer_shape))
1627 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1628 hourglass_cursor
1629 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1631 else
1632 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1633 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1635 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1636 if (!NILP (Vx_mode_pointer_shape))
1638 CHECK_NUMBER (Vx_mode_pointer_shape);
1639 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1641 else
1642 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1643 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1645 if (!NILP (Vx_sensitive_text_pointer_shape))
1647 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1648 cross_cursor
1649 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1651 else
1652 cross_cursor = XCreateFontCursor (dpy, XC_hand2);
1654 if (!NILP (Vx_window_horizontal_drag_shape))
1656 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1657 horizontal_drag_cursor
1658 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1660 else
1661 horizontal_drag_cursor
1662 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1664 /* Check and report errors with the above calls. */
1665 x_check_errors (dpy, "can't set cursor shape: %s");
1666 x_uncatch_errors (dpy, count);
1669 XColor fore_color, back_color;
1671 fore_color.pixel = x->mouse_pixel;
1672 x_query_color (f, &fore_color);
1673 back_color.pixel = mask_color;
1674 x_query_color (f, &back_color);
1676 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1677 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1678 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1679 XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
1680 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1681 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1684 if (FRAME_X_WINDOW (f) != 0)
1685 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1687 if (cursor != x->text_cursor
1688 && x->text_cursor != 0)
1689 XFreeCursor (dpy, x->text_cursor);
1690 x->text_cursor = cursor;
1692 if (nontext_cursor != x->nontext_cursor
1693 && x->nontext_cursor != 0)
1694 XFreeCursor (dpy, x->nontext_cursor);
1695 x->nontext_cursor = nontext_cursor;
1697 if (hourglass_cursor != x->hourglass_cursor
1698 && x->hourglass_cursor != 0)
1699 XFreeCursor (dpy, x->hourglass_cursor);
1700 x->hourglass_cursor = hourglass_cursor;
1702 if (mode_cursor != x->modeline_cursor
1703 && x->modeline_cursor != 0)
1704 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1705 x->modeline_cursor = mode_cursor;
1707 if (cross_cursor != x->cross_cursor
1708 && x->cross_cursor != 0)
1709 XFreeCursor (dpy, x->cross_cursor);
1710 x->cross_cursor = cross_cursor;
1712 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1713 && x->horizontal_drag_cursor != 0)
1714 XFreeCursor (dpy, x->horizontal_drag_cursor);
1715 x->horizontal_drag_cursor = horizontal_drag_cursor;
1717 XFlush (dpy);
1718 UNBLOCK_INPUT;
1720 update_face_from_frame_parameter (f, Qmouse_color, arg);
1723 void
1724 x_set_cursor_color (f, arg, oldval)
1725 struct frame *f;
1726 Lisp_Object arg, oldval;
1728 unsigned long fore_pixel, pixel;
1729 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1730 struct x_output *x = f->output_data.x;
1732 if (!NILP (Vx_cursor_fore_pixel))
1734 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1735 WHITE_PIX_DEFAULT (f));
1736 fore_pixel_allocated_p = 1;
1738 else
1739 fore_pixel = x->background_pixel;
1741 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1742 pixel_allocated_p = 1;
1744 /* Make sure that the cursor color differs from the background color. */
1745 if (pixel == x->background_pixel)
1747 if (pixel_allocated_p)
1749 x_free_colors (f, &pixel, 1);
1750 pixel_allocated_p = 0;
1753 pixel = x->mouse_pixel;
1754 if (pixel == fore_pixel)
1756 if (fore_pixel_allocated_p)
1758 x_free_colors (f, &fore_pixel, 1);
1759 fore_pixel_allocated_p = 0;
1761 fore_pixel = x->background_pixel;
1765 unload_color (f, x->cursor_foreground_pixel);
1766 if (!fore_pixel_allocated_p)
1767 fore_pixel = x_copy_color (f, fore_pixel);
1768 x->cursor_foreground_pixel = fore_pixel;
1770 unload_color (f, x->cursor_pixel);
1771 if (!pixel_allocated_p)
1772 pixel = x_copy_color (f, pixel);
1773 x->cursor_pixel = pixel;
1775 if (FRAME_X_WINDOW (f) != 0)
1777 BLOCK_INPUT;
1778 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1779 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1780 UNBLOCK_INPUT;
1782 if (FRAME_VISIBLE_P (f))
1784 x_update_cursor (f, 0);
1785 x_update_cursor (f, 1);
1789 update_face_from_frame_parameter (f, Qcursor_color, arg);
1792 /* Set the border-color of frame F to value described by ARG.
1793 ARG can be a string naming a color.
1794 The border-color is used for the border that is drawn by the X server.
1795 Note that this does not fully take effect if done before
1796 F has an x-window; it must be redone when the window is created.
1798 Note: this is done in two routines because of the way X10 works.
1800 Note: under X11, this is normally the province of the window manager,
1801 and so emacs' border colors may be overridden. */
1803 void
1804 x_set_border_color (f, arg, oldval)
1805 struct frame *f;
1806 Lisp_Object arg, oldval;
1808 int pix;
1810 CHECK_STRING (arg);
1811 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1812 x_set_border_pixel (f, pix);
1813 update_face_from_frame_parameter (f, Qborder_color, arg);
1816 /* Set the border-color of frame F to pixel value PIX.
1817 Note that this does not fully take effect if done before
1818 F has an x-window. */
1820 void
1821 x_set_border_pixel (f, pix)
1822 struct frame *f;
1823 int pix;
1825 unload_color (f, f->output_data.x->border_pixel);
1826 f->output_data.x->border_pixel = pix;
1828 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1830 BLOCK_INPUT;
1831 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1832 (unsigned long)pix);
1833 UNBLOCK_INPUT;
1835 if (FRAME_VISIBLE_P (f))
1836 redraw_frame (f);
1842 void
1843 x_set_cursor_type (f, arg, oldval)
1844 FRAME_PTR f;
1845 Lisp_Object arg, oldval;
1847 set_frame_cursor_types (f, arg);
1849 /* Make sure the cursor gets redrawn. */
1850 cursor_type_changed = 1;
1853 void
1854 x_set_icon_type (f, arg, oldval)
1855 struct frame *f;
1856 Lisp_Object arg, oldval;
1858 int result;
1860 if (STRINGP (arg))
1862 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1863 return;
1865 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1866 return;
1868 BLOCK_INPUT;
1869 if (NILP (arg))
1870 result = x_text_icon (f,
1871 (char *) SDATA ((!NILP (f->icon_name)
1872 ? f->icon_name
1873 : f->name)));
1874 else
1875 result = x_bitmap_icon (f, arg);
1877 if (result)
1879 UNBLOCK_INPUT;
1880 error ("No icon window available");
1883 XFlush (FRAME_X_DISPLAY (f));
1884 UNBLOCK_INPUT;
1887 /* Return non-nil if frame F wants a bitmap icon. */
1889 Lisp_Object
1890 x_icon_type (f)
1891 FRAME_PTR f;
1893 Lisp_Object tem;
1895 tem = assq_no_quit (Qicon_type, f->param_alist);
1896 if (CONSP (tem))
1897 return XCDR (tem);
1898 else
1899 return Qnil;
1902 void
1903 x_set_icon_name (f, arg, oldval)
1904 struct frame *f;
1905 Lisp_Object arg, oldval;
1907 int result;
1909 if (STRINGP (arg))
1911 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1912 return;
1914 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1915 return;
1917 f->icon_name = arg;
1919 if (f->output_data.x->icon_bitmap != 0)
1920 return;
1922 BLOCK_INPUT;
1924 result = x_text_icon (f,
1925 (char *) SDATA ((!NILP (f->icon_name)
1926 ? f->icon_name
1927 : !NILP (f->title)
1928 ? f->title
1929 : f->name)));
1931 if (result)
1933 UNBLOCK_INPUT;
1934 error ("No icon window available");
1937 XFlush (FRAME_X_DISPLAY (f));
1938 UNBLOCK_INPUT;
1941 void
1942 x_set_font (f, arg, oldval)
1943 struct frame *f;
1944 Lisp_Object arg, oldval;
1946 Lisp_Object result;
1947 Lisp_Object fontset_name;
1948 Lisp_Object frame;
1949 int old_fontset = f->output_data.x->fontset;
1951 CHECK_STRING (arg);
1953 fontset_name = Fquery_fontset (arg, Qnil);
1955 BLOCK_INPUT;
1956 result = (STRINGP (fontset_name)
1957 ? x_new_fontset (f, SDATA (fontset_name))
1958 : x_new_font (f, SDATA (arg)));
1959 UNBLOCK_INPUT;
1961 if (EQ (result, Qnil))
1962 error ("Font `%s' is not defined", SDATA (arg));
1963 else if (EQ (result, Qt))
1964 error ("The characters of the given font have varying widths");
1965 else if (STRINGP (result))
1967 if (STRINGP (fontset_name))
1969 /* Fontset names are built from ASCII font names, so the
1970 names may be equal despite there was a change. */
1971 if (old_fontset == f->output_data.x->fontset)
1972 return;
1974 else if (!NILP (Fequal (result, oldval)))
1975 return;
1977 store_frame_param (f, Qfont, result);
1978 recompute_basic_faces (f);
1980 else
1981 abort ();
1983 do_pending_window_change (0);
1985 /* Don't call `face-set-after-frame-default' when faces haven't been
1986 initialized yet. This is the case when called from
1987 Fx_create_frame. In that case, the X widget or window doesn't
1988 exist either, and we can end up in x_report_frame_params with a
1989 null widget which gives a segfault. */
1990 if (FRAME_FACE_CACHE (f))
1992 XSETFRAME (frame, f);
1993 call1 (Qface_set_after_frame_default, frame);
1997 static void
1998 x_set_fringe_width (f, new_value, old_value)
1999 struct frame *f;
2000 Lisp_Object new_value, old_value;
2002 x_compute_fringe_widths (f, 1);
2005 void
2006 x_set_border_width (f, arg, oldval)
2007 struct frame *f;
2008 Lisp_Object arg, oldval;
2010 CHECK_NUMBER (arg);
2012 if (XINT (arg) == f->output_data.x->border_width)
2013 return;
2015 if (FRAME_X_WINDOW (f) != 0)
2016 error ("Cannot change the border width of a window");
2018 f->output_data.x->border_width = XINT (arg);
2021 void
2022 x_set_internal_border_width (f, arg, oldval)
2023 struct frame *f;
2024 Lisp_Object arg, oldval;
2026 int old = f->output_data.x->internal_border_width;
2028 CHECK_NUMBER (arg);
2029 f->output_data.x->internal_border_width = XINT (arg);
2030 if (f->output_data.x->internal_border_width < 0)
2031 f->output_data.x->internal_border_width = 0;
2033 #ifdef USE_X_TOOLKIT
2034 if (f->output_data.x->edit_widget)
2035 widget_store_internal_border (f->output_data.x->edit_widget);
2036 #endif
2038 if (f->output_data.x->internal_border_width == old)
2039 return;
2041 if (FRAME_X_WINDOW (f) != 0)
2043 x_set_window_size (f, 0, f->width, f->height);
2044 SET_FRAME_GARBAGED (f);
2045 do_pending_window_change (0);
2047 else
2048 SET_FRAME_GARBAGED (f);
2051 void
2052 x_set_visibility (f, value, oldval)
2053 struct frame *f;
2054 Lisp_Object value, oldval;
2056 Lisp_Object frame;
2057 XSETFRAME (frame, f);
2059 if (NILP (value))
2060 Fmake_frame_invisible (frame, Qt);
2061 else if (EQ (value, Qicon))
2062 Ficonify_frame (frame);
2063 else
2064 Fmake_frame_visible (frame);
2068 /* Change window heights in windows rooted in WINDOW by N lines. */
2070 static void
2071 x_change_window_heights (window, n)
2072 Lisp_Object window;
2073 int n;
2075 struct window *w = XWINDOW (window);
2077 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2078 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2080 if (INTEGERP (w->orig_top))
2081 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2082 if (INTEGERP (w->orig_height))
2083 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2085 /* Handle just the top child in a vertical split. */
2086 if (!NILP (w->vchild))
2087 x_change_window_heights (w->vchild, n);
2089 /* Adjust all children in a horizontal split. */
2090 for (window = w->hchild; !NILP (window); window = w->next)
2092 w = XWINDOW (window);
2093 x_change_window_heights (window, n);
2097 void
2098 x_set_menu_bar_lines (f, value, oldval)
2099 struct frame *f;
2100 Lisp_Object value, oldval;
2102 int nlines;
2103 #ifndef USE_X_TOOLKIT
2104 int olines = FRAME_MENU_BAR_LINES (f);
2105 #endif
2107 /* Right now, menu bars don't work properly in minibuf-only frames;
2108 most of the commands try to apply themselves to the minibuffer
2109 frame itself, and get an error because you can't switch buffers
2110 in or split the minibuffer window. */
2111 if (FRAME_MINIBUF_ONLY_P (f))
2112 return;
2114 if (INTEGERP (value))
2115 nlines = XINT (value);
2116 else
2117 nlines = 0;
2119 /* Make sure we redisplay all windows in this frame. */
2120 windows_or_buffers_changed++;
2122 #ifdef USE_X_TOOLKIT
2123 FRAME_MENU_BAR_LINES (f) = 0;
2124 if (nlines)
2126 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2127 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
2128 /* Make sure next redisplay shows the menu bar. */
2129 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
2131 else
2133 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2134 free_frame_menubar (f);
2135 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2136 if (FRAME_X_P (f))
2137 f->output_data.x->menubar_widget = 0;
2139 #else /* not USE_X_TOOLKIT */
2140 FRAME_MENU_BAR_LINES (f) = nlines;
2141 x_change_window_heights (f->root_window, nlines - olines);
2142 #endif /* not USE_X_TOOLKIT */
2143 adjust_glyphs (f);
2147 /* Set the number of lines used for the tool bar of frame F to VALUE.
2148 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2149 is the old number of tool bar lines. This function changes the
2150 height of all windows on frame F to match the new tool bar height.
2151 The frame's height doesn't change. */
2153 void
2154 x_set_tool_bar_lines (f, value, oldval)
2155 struct frame *f;
2156 Lisp_Object value, oldval;
2158 int delta, nlines, root_height;
2159 Lisp_Object root_window;
2161 /* Treat tool bars like menu bars. */
2162 if (FRAME_MINIBUF_ONLY_P (f))
2163 return;
2165 /* Use VALUE only if an integer >= 0. */
2166 if (INTEGERP (value) && XINT (value) >= 0)
2167 nlines = XFASTINT (value);
2168 else
2169 nlines = 0;
2171 /* Make sure we redisplay all windows in this frame. */
2172 ++windows_or_buffers_changed;
2174 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2176 /* Don't resize the tool-bar to more than we have room for. */
2177 root_window = FRAME_ROOT_WINDOW (f);
2178 root_height = XINT (XWINDOW (root_window)->height);
2179 if (root_height - delta < 1)
2181 delta = root_height - 1;
2182 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2185 FRAME_TOOL_BAR_LINES (f) = nlines;
2186 x_change_window_heights (root_window, delta);
2187 adjust_glyphs (f);
2189 /* We also have to make sure that the internal border at the top of
2190 the frame, below the menu bar or tool bar, is redrawn when the
2191 tool bar disappears. This is so because the internal border is
2192 below the tool bar if one is displayed, but is below the menu bar
2193 if there isn't a tool bar. The tool bar draws into the area
2194 below the menu bar. */
2195 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2197 updating_frame = f;
2198 clear_frame ();
2199 clear_current_matrices (f);
2200 updating_frame = NULL;
2203 /* If the tool bar gets smaller, the internal border below it
2204 has to be cleared. It was formerly part of the display
2205 of the larger tool bar, and updating windows won't clear it. */
2206 if (delta < 0)
2208 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2209 int width = PIXEL_WIDTH (f);
2210 int y = nlines * CANON_Y_UNIT (f);
2212 BLOCK_INPUT;
2213 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2214 0, y, width, height, False);
2215 UNBLOCK_INPUT;
2217 if (WINDOWP (f->tool_bar_window))
2218 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2223 /* Set the foreground color for scroll bars on frame F to VALUE.
2224 VALUE should be a string, a color name. If it isn't a string or
2225 isn't a valid color name, do nothing. OLDVAL is the old value of
2226 the frame parameter. */
2228 void
2229 x_set_scroll_bar_foreground (f, value, oldval)
2230 struct frame *f;
2231 Lisp_Object value, oldval;
2233 unsigned long pixel;
2235 if (STRINGP (value))
2236 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2237 else
2238 pixel = -1;
2240 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2241 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2243 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2244 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2246 /* Remove all scroll bars because they have wrong colors. */
2247 if (condemn_scroll_bars_hook)
2248 (*condemn_scroll_bars_hook) (f);
2249 if (judge_scroll_bars_hook)
2250 (*judge_scroll_bars_hook) (f);
2252 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2253 redraw_frame (f);
2258 /* Set the background color for scroll bars on frame F to VALUE VALUE
2259 should be a string, a color name. If it isn't a string or isn't a
2260 valid color name, do nothing. OLDVAL is the old value of the frame
2261 parameter. */
2263 void
2264 x_set_scroll_bar_background (f, value, oldval)
2265 struct frame *f;
2266 Lisp_Object value, oldval;
2268 unsigned long pixel;
2270 if (STRINGP (value))
2271 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2272 else
2273 pixel = -1;
2275 if (f->output_data.x->scroll_bar_background_pixel != -1)
2276 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2278 #ifdef USE_TOOLKIT_SCROLL_BARS
2279 /* Scrollbar shadow colors. */
2280 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
2282 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
2283 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2285 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
2287 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
2288 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2290 #endif /* USE_TOOLKIT_SCROLL_BARS */
2292 f->output_data.x->scroll_bar_background_pixel = pixel;
2293 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2295 /* Remove all scroll bars because they have wrong colors. */
2296 if (condemn_scroll_bars_hook)
2297 (*condemn_scroll_bars_hook) (f);
2298 if (judge_scroll_bars_hook)
2299 (*judge_scroll_bars_hook) (f);
2301 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2302 redraw_frame (f);
2307 /* Encode Lisp string STRING as a text in a format appropriate for
2308 XICCC (X Inter Client Communication Conventions).
2310 If STRING contains only ASCII characters, do no conversion and
2311 return the string data of STRING. Otherwise, encode the text by
2312 CODING_SYSTEM, and return a newly allocated memory area which
2313 should be freed by `xfree' by a caller.
2315 SELECTIONP non-zero means the string is being encoded for an X
2316 selection, so it is safe to run pre-write conversions (which
2317 may run Lisp code).
2319 Store the byte length of resulting text in *TEXT_BYTES.
2321 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2322 which means that the `encoding' of the result can be `STRING'.
2323 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2324 the result should be `COMPOUND_TEXT'. */
2326 unsigned char *
2327 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
2328 Lisp_Object string, coding_system;
2329 int *text_bytes, *stringp;
2330 int selectionp;
2332 unsigned char *str = SDATA (string);
2333 int chars = SCHARS (string);
2334 int bytes = SBYTES (string);
2335 int charset_info;
2336 int bufsize;
2337 unsigned char *buf;
2338 struct coding_system coding;
2339 extern Lisp_Object Qcompound_text_with_extensions;
2341 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2342 if (charset_info == 0)
2344 /* No multibyte character in OBJ. We need not encode it. */
2345 *text_bytes = bytes;
2346 *stringp = 1;
2347 return str;
2350 setup_coding_system (coding_system, &coding);
2351 if (selectionp
2352 && SYMBOLP (coding.pre_write_conversion)
2353 && !NILP (Ffboundp (coding.pre_write_conversion)))
2355 string = run_pre_post_conversion_on_str (string, &coding, 1);
2356 str = SDATA (string);
2357 chars = SCHARS (string);
2358 bytes = SBYTES (string);
2360 coding.src_multibyte = 1;
2361 coding.dst_multibyte = 0;
2362 coding.mode |= CODING_MODE_LAST_BLOCK;
2363 if (coding.type == coding_type_iso2022)
2364 coding.flags |= CODING_FLAG_ISO_SAFE;
2365 /* We suppress producing escape sequences for composition. */
2366 coding.composing = COMPOSITION_DISABLED;
2367 bufsize = encoding_buffer_size (&coding, bytes);
2368 buf = (unsigned char *) xmalloc (bufsize);
2369 encode_coding (&coding, str, buf, bytes, bufsize);
2370 *text_bytes = coding.produced;
2371 *stringp = (charset_info == 1
2372 || (!EQ (coding_system, Qcompound_text)
2373 && !EQ (coding_system, Qcompound_text_with_extensions)));
2374 return buf;
2378 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2379 x_id_name.
2381 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2382 name; if NAME is a string, set F's name to NAME and set
2383 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2385 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2386 suggesting a new name, which lisp code should override; if
2387 F->explicit_name is set, ignore the new name; otherwise, set it. */
2389 void
2390 x_set_name (f, name, explicit)
2391 struct frame *f;
2392 Lisp_Object name;
2393 int explicit;
2395 /* Make sure that requests from lisp code override requests from
2396 Emacs redisplay code. */
2397 if (explicit)
2399 /* If we're switching from explicit to implicit, we had better
2400 update the mode lines and thereby update the title. */
2401 if (f->explicit_name && NILP (name))
2402 update_mode_lines = 1;
2404 f->explicit_name = ! NILP (name);
2406 else if (f->explicit_name)
2407 return;
2409 /* If NAME is nil, set the name to the x_id_name. */
2410 if (NILP (name))
2412 /* Check for no change needed in this very common case
2413 before we do any consing. */
2414 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2415 SDATA (f->name)))
2416 return;
2417 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2419 else
2420 CHECK_STRING (name);
2422 /* Don't change the name if it's already NAME. */
2423 if (! NILP (Fstring_equal (name, f->name)))
2424 return;
2426 f->name = name;
2428 /* For setting the frame title, the title parameter should override
2429 the name parameter. */
2430 if (! NILP (f->title))
2431 name = f->title;
2433 if (FRAME_X_WINDOW (f))
2435 BLOCK_INPUT;
2436 #ifdef HAVE_X11R4
2438 XTextProperty text, icon;
2439 int bytes, stringp;
2440 Lisp_Object coding_system;
2442 coding_system = Vlocale_coding_system;
2443 if (NILP (coding_system))
2444 coding_system = Qcompound_text;
2445 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2446 text.encoding = (stringp ? XA_STRING
2447 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2448 text.format = 8;
2449 text.nitems = bytes;
2451 if (NILP (f->icon_name))
2453 icon = text;
2455 else
2457 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2458 &bytes, &stringp);
2459 icon.encoding = (stringp ? XA_STRING
2460 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2461 icon.format = 8;
2462 icon.nitems = bytes;
2464 #ifdef USE_X_TOOLKIT
2465 XSetWMName (FRAME_X_DISPLAY (f),
2466 XtWindow (f->output_data.x->widget), &text);
2467 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2468 &icon);
2469 #else /* not USE_X_TOOLKIT */
2470 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2471 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2472 #endif /* not USE_X_TOOLKIT */
2473 if (!NILP (f->icon_name)
2474 && icon.value != SDATA (f->icon_name))
2475 xfree (icon.value);
2476 if (text.value != SDATA (name))
2477 xfree (text.value);
2479 #else /* not HAVE_X11R4 */
2480 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2481 SDATA (name));
2482 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2483 SDATA (name));
2484 #endif /* not HAVE_X11R4 */
2485 UNBLOCK_INPUT;
2489 /* This function should be called when the user's lisp code has
2490 specified a name for the frame; the name will override any set by the
2491 redisplay code. */
2492 void
2493 x_explicitly_set_name (f, arg, oldval)
2494 FRAME_PTR f;
2495 Lisp_Object arg, oldval;
2497 x_set_name (f, arg, 1);
2500 /* This function should be called by Emacs redisplay code to set the
2501 name; names set this way will never override names set by the user's
2502 lisp code. */
2503 void
2504 x_implicitly_set_name (f, arg, oldval)
2505 FRAME_PTR f;
2506 Lisp_Object arg, oldval;
2508 x_set_name (f, arg, 0);
2511 /* Change the title of frame F to NAME.
2512 If NAME is nil, use the frame name as the title.
2514 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2515 name; if NAME is a string, set F's name to NAME and set
2516 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2518 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2519 suggesting a new name, which lisp code should override; if
2520 F->explicit_name is set, ignore the new name; otherwise, set it. */
2522 void
2523 x_set_title (f, name, old_name)
2524 struct frame *f;
2525 Lisp_Object name, old_name;
2527 /* Don't change the title if it's already NAME. */
2528 if (EQ (name, f->title))
2529 return;
2531 update_mode_lines = 1;
2533 f->title = name;
2535 if (NILP (name))
2536 name = f->name;
2537 else
2538 CHECK_STRING (name);
2540 if (FRAME_X_WINDOW (f))
2542 BLOCK_INPUT;
2543 #ifdef HAVE_X11R4
2545 XTextProperty text, icon;
2546 int bytes, stringp;
2547 Lisp_Object coding_system;
2549 coding_system = Vlocale_coding_system;
2550 if (NILP (coding_system))
2551 coding_system = Qcompound_text;
2552 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
2553 text.encoding = (stringp ? XA_STRING
2554 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2555 text.format = 8;
2556 text.nitems = bytes;
2558 if (NILP (f->icon_name))
2560 icon = text;
2562 else
2564 icon.value = x_encode_text (f->icon_name, coding_system, 0,
2565 &bytes, &stringp);
2566 icon.encoding = (stringp ? XA_STRING
2567 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2568 icon.format = 8;
2569 icon.nitems = bytes;
2571 #ifdef USE_X_TOOLKIT
2572 XSetWMName (FRAME_X_DISPLAY (f),
2573 XtWindow (f->output_data.x->widget), &text);
2574 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2575 &icon);
2576 #else /* not USE_X_TOOLKIT */
2577 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2578 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2579 #endif /* not USE_X_TOOLKIT */
2580 if (!NILP (f->icon_name)
2581 && icon.value != SDATA (f->icon_name))
2582 xfree (icon.value);
2583 if (text.value != SDATA (name))
2584 xfree (text.value);
2586 #else /* not HAVE_X11R4 */
2587 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2588 SDATA (name));
2589 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2590 SDATA (name));
2591 #endif /* not HAVE_X11R4 */
2592 UNBLOCK_INPUT;
2596 void
2597 x_set_autoraise (f, arg, oldval)
2598 struct frame *f;
2599 Lisp_Object arg, oldval;
2601 f->auto_raise = !EQ (Qnil, arg);
2604 void
2605 x_set_autolower (f, arg, oldval)
2606 struct frame *f;
2607 Lisp_Object arg, oldval;
2609 f->auto_lower = !EQ (Qnil, arg);
2612 void
2613 x_set_unsplittable (f, arg, oldval)
2614 struct frame *f;
2615 Lisp_Object arg, oldval;
2617 f->no_split = !NILP (arg);
2620 void
2621 x_set_vertical_scroll_bars (f, arg, oldval)
2622 struct frame *f;
2623 Lisp_Object arg, oldval;
2625 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2626 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2627 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2628 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2630 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2631 = (NILP (arg)
2632 ? vertical_scroll_bar_none
2633 : EQ (Qright, arg)
2634 ? vertical_scroll_bar_right
2635 : vertical_scroll_bar_left);
2637 /* We set this parameter before creating the X window for the
2638 frame, so we can get the geometry right from the start.
2639 However, if the window hasn't been created yet, we shouldn't
2640 call x_set_window_size. */
2641 if (FRAME_X_WINDOW (f))
2642 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2643 do_pending_window_change (0);
2647 void
2648 x_set_scroll_bar_width (f, arg, oldval)
2649 struct frame *f;
2650 Lisp_Object arg, oldval;
2652 int wid = FONT_WIDTH (f->output_data.x->font);
2654 if (NILP (arg))
2656 #ifdef USE_TOOLKIT_SCROLL_BARS
2657 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2658 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2659 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2660 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2661 #else
2662 /* Make the actual width at least 14 pixels and a multiple of a
2663 character width. */
2664 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2666 /* Use all of that space (aside from required margins) for the
2667 scroll bar. */
2668 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2669 #endif
2671 if (FRAME_X_WINDOW (f))
2672 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2673 do_pending_window_change (0);
2675 else if (INTEGERP (arg) && XINT (arg) > 0
2676 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2678 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2679 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2681 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2682 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2683 if (FRAME_X_WINDOW (f))
2684 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2687 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2688 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2689 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2694 /* Subroutines of creating an X frame. */
2696 /* Make sure that Vx_resource_name is set to a reasonable value.
2697 Fix it up, or set it to `emacs' if it is too hopeless. */
2699 static void
2700 validate_x_resource_name ()
2702 int len = 0;
2703 /* Number of valid characters in the resource name. */
2704 int good_count = 0;
2705 /* Number of invalid characters in the resource name. */
2706 int bad_count = 0;
2707 Lisp_Object new;
2708 int i;
2710 if (!STRINGP (Vx_resource_class))
2711 Vx_resource_class = build_string (EMACS_CLASS);
2713 if (STRINGP (Vx_resource_name))
2715 unsigned char *p = SDATA (Vx_resource_name);
2716 int i;
2718 len = SBYTES (Vx_resource_name);
2720 /* Only letters, digits, - and _ are valid in resource names.
2721 Count the valid characters and count the invalid ones. */
2722 for (i = 0; i < len; i++)
2724 int c = p[i];
2725 if (! ((c >= 'a' && c <= 'z')
2726 || (c >= 'A' && c <= 'Z')
2727 || (c >= '0' && c <= '9')
2728 || c == '-' || c == '_'))
2729 bad_count++;
2730 else
2731 good_count++;
2734 else
2735 /* Not a string => completely invalid. */
2736 bad_count = 5, good_count = 0;
2738 /* If name is valid already, return. */
2739 if (bad_count == 0)
2740 return;
2742 /* If name is entirely invalid, or nearly so, use `emacs'. */
2743 if (good_count == 0
2744 || (good_count == 1 && bad_count > 0))
2746 Vx_resource_name = build_string ("emacs");
2747 return;
2750 /* Name is partly valid. Copy it and replace the invalid characters
2751 with underscores. */
2753 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2755 for (i = 0; i < len; i++)
2757 int c = SREF (new, i);
2758 if (! ((c >= 'a' && c <= 'z')
2759 || (c >= 'A' && c <= 'Z')
2760 || (c >= '0' && c <= '9')
2761 || c == '-' || c == '_'))
2762 SSET (new, i, '_');
2767 extern char *x_get_string_resource ();
2769 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2770 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
2771 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
2772 class, where INSTANCE is the name under which Emacs was invoked, or
2773 the name specified by the `-name' or `-rn' command-line arguments.
2775 The optional arguments COMPONENT and SUBCLASS add to the key and the
2776 class, respectively. You must specify both of them or neither.
2777 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
2778 and the class is `Emacs.CLASS.SUBCLASS'. */)
2779 (attribute, class, component, subclass)
2780 Lisp_Object attribute, class, component, subclass;
2782 register char *value;
2783 char *name_key;
2784 char *class_key;
2786 check_x ();
2788 CHECK_STRING (attribute);
2789 CHECK_STRING (class);
2791 if (!NILP (component))
2792 CHECK_STRING (component);
2793 if (!NILP (subclass))
2794 CHECK_STRING (subclass);
2795 if (NILP (component) != NILP (subclass))
2796 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2798 validate_x_resource_name ();
2800 /* Allocate space for the components, the dots which separate them,
2801 and the final '\0'. Make them big enough for the worst case. */
2802 name_key = (char *) alloca (SBYTES (Vx_resource_name)
2803 + (STRINGP (component)
2804 ? SBYTES (component) : 0)
2805 + SBYTES (attribute)
2806 + 3);
2808 class_key = (char *) alloca (SBYTES (Vx_resource_class)
2809 + SBYTES (class)
2810 + (STRINGP (subclass)
2811 ? SBYTES (subclass) : 0)
2812 + 3);
2814 /* Start with emacs.FRAMENAME for the name (the specific one)
2815 and with `Emacs' for the class key (the general one). */
2816 strcpy (name_key, SDATA (Vx_resource_name));
2817 strcpy (class_key, SDATA (Vx_resource_class));
2819 strcat (class_key, ".");
2820 strcat (class_key, SDATA (class));
2822 if (!NILP (component))
2824 strcat (class_key, ".");
2825 strcat (class_key, SDATA (subclass));
2827 strcat (name_key, ".");
2828 strcat (name_key, SDATA (component));
2831 strcat (name_key, ".");
2832 strcat (name_key, SDATA (attribute));
2834 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2835 name_key, class_key);
2837 if (value != (char *) 0)
2838 return build_string (value);
2839 else
2840 return Qnil;
2843 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2845 Lisp_Object
2846 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2847 struct x_display_info *dpyinfo;
2848 Lisp_Object attribute, class, component, subclass;
2850 register char *value;
2851 char *name_key;
2852 char *class_key;
2854 CHECK_STRING (attribute);
2855 CHECK_STRING (class);
2857 if (!NILP (component))
2858 CHECK_STRING (component);
2859 if (!NILP (subclass))
2860 CHECK_STRING (subclass);
2861 if (NILP (component) != NILP (subclass))
2862 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2864 validate_x_resource_name ();
2866 /* Allocate space for the components, the dots which separate them,
2867 and the final '\0'. Make them big enough for the worst case. */
2868 name_key = (char *) alloca (SBYTES (Vx_resource_name)
2869 + (STRINGP (component)
2870 ? SBYTES (component) : 0)
2871 + SBYTES (attribute)
2872 + 3);
2874 class_key = (char *) alloca (SBYTES (Vx_resource_class)
2875 + SBYTES (class)
2876 + (STRINGP (subclass)
2877 ? SBYTES (subclass) : 0)
2878 + 3);
2880 /* Start with emacs.FRAMENAME for the name (the specific one)
2881 and with `Emacs' for the class key (the general one). */
2882 strcpy (name_key, SDATA (Vx_resource_name));
2883 strcpy (class_key, SDATA (Vx_resource_class));
2885 strcat (class_key, ".");
2886 strcat (class_key, SDATA (class));
2888 if (!NILP (component))
2890 strcat (class_key, ".");
2891 strcat (class_key, SDATA (subclass));
2893 strcat (name_key, ".");
2894 strcat (name_key, SDATA (component));
2897 strcat (name_key, ".");
2898 strcat (name_key, SDATA (attribute));
2900 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2902 if (value != (char *) 0)
2903 return build_string (value);
2904 else
2905 return Qnil;
2908 /* Used when C code wants a resource value. */
2910 char *
2911 x_get_resource_string (attribute, class)
2912 char *attribute, *class;
2914 char *name_key;
2915 char *class_key;
2916 struct frame *sf = SELECTED_FRAME ();
2918 /* Allocate space for the components, the dots which separate them,
2919 and the final '\0'. */
2920 name_key = (char *) alloca (SBYTES (Vinvocation_name)
2921 + strlen (attribute) + 2);
2922 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2923 + strlen (class) + 2);
2925 sprintf (name_key, "%s.%s",
2926 SDATA (Vinvocation_name),
2927 attribute);
2928 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2930 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2931 name_key, class_key);
2934 /* Types we might convert a resource string into. */
2935 enum resource_types
2937 RES_TYPE_NUMBER,
2938 RES_TYPE_FLOAT,
2939 RES_TYPE_BOOLEAN,
2940 RES_TYPE_STRING,
2941 RES_TYPE_SYMBOL
2944 /* Return the value of parameter PARAM.
2946 First search ALIST, then Vdefault_frame_alist, then the X defaults
2947 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2949 Convert the resource to the type specified by desired_type.
2951 If no default is specified, return Qunbound. If you call
2952 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2953 and don't let it get stored in any Lisp-visible variables! */
2955 static Lisp_Object
2956 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2957 struct x_display_info *dpyinfo;
2958 Lisp_Object alist, param;
2959 char *attribute;
2960 char *class;
2961 enum resource_types type;
2963 register Lisp_Object tem;
2965 tem = Fassq (param, alist);
2966 if (EQ (tem, Qnil))
2967 tem = Fassq (param, Vdefault_frame_alist);
2968 if (EQ (tem, Qnil))
2971 if (attribute)
2973 tem = display_x_get_resource (dpyinfo,
2974 build_string (attribute),
2975 build_string (class),
2976 Qnil, Qnil);
2978 if (NILP (tem))
2979 return Qunbound;
2981 switch (type)
2983 case RES_TYPE_NUMBER:
2984 return make_number (atoi (SDATA (tem)));
2986 case RES_TYPE_FLOAT:
2987 return make_float (atof (SDATA (tem)));
2989 case RES_TYPE_BOOLEAN:
2990 tem = Fdowncase (tem);
2991 if (!strcmp (SDATA (tem), "on")
2992 || !strcmp (SDATA (tem), "true"))
2993 return Qt;
2994 else
2995 return Qnil;
2997 case RES_TYPE_STRING:
2998 return tem;
3000 case RES_TYPE_SYMBOL:
3001 /* As a special case, we map the values `true' and `on'
3002 to Qt, and `false' and `off' to Qnil. */
3004 Lisp_Object lower;
3005 lower = Fdowncase (tem);
3006 if (!strcmp (SDATA (lower), "on")
3007 || !strcmp (SDATA (lower), "true"))
3008 return Qt;
3009 else if (!strcmp (SDATA (lower), "off")
3010 || !strcmp (SDATA (lower), "false"))
3011 return Qnil;
3012 else
3013 return Fintern (tem, Qnil);
3016 default:
3017 abort ();
3020 else
3021 return Qunbound;
3023 return Fcdr (tem);
3026 /* Like x_get_arg, but also record the value in f->param_alist. */
3028 static Lisp_Object
3029 x_get_and_record_arg (f, alist, param, attribute, class, type)
3030 struct frame *f;
3031 Lisp_Object alist, param;
3032 char *attribute;
3033 char *class;
3034 enum resource_types type;
3036 Lisp_Object value;
3038 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
3039 attribute, class, type);
3040 if (! NILP (value))
3041 store_frame_param (f, param, value);
3043 return value;
3046 /* Record in frame F the specified or default value according to ALIST
3047 of the parameter named PROP (a Lisp symbol).
3048 If no value is specified for PROP, look for an X default for XPROP
3049 on the frame named NAME.
3050 If that is not found either, use the value DEFLT. */
3052 static Lisp_Object
3053 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
3054 struct frame *f;
3055 Lisp_Object alist;
3056 Lisp_Object prop;
3057 Lisp_Object deflt;
3058 char *xprop;
3059 char *xclass;
3060 enum resource_types type;
3062 Lisp_Object tem;
3064 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
3065 if (EQ (tem, Qunbound))
3066 tem = deflt;
3067 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3068 return tem;
3072 /* Record in frame F the specified or default value according to ALIST
3073 of the parameter named PROP (a Lisp symbol). If no value is
3074 specified for PROP, look for an X default for XPROP on the frame
3075 named NAME. If that is not found either, use the value DEFLT. */
3077 static Lisp_Object
3078 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
3079 foreground_p)
3080 struct frame *f;
3081 Lisp_Object alist;
3082 Lisp_Object prop;
3083 char *xprop;
3084 char *xclass;
3085 int foreground_p;
3087 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3088 Lisp_Object tem;
3090 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
3091 if (EQ (tem, Qunbound))
3093 #ifdef USE_TOOLKIT_SCROLL_BARS
3095 /* See if an X resource for the scroll bar color has been
3096 specified. */
3097 tem = display_x_get_resource (dpyinfo,
3098 build_string (foreground_p
3099 ? "foreground"
3100 : "background"),
3101 empty_string,
3102 build_string ("verticalScrollBar"),
3103 empty_string);
3104 if (!STRINGP (tem))
3106 /* If nothing has been specified, scroll bars will use a
3107 toolkit-dependent default. Because these defaults are
3108 difficult to get at without actually creating a scroll
3109 bar, use nil to indicate that no color has been
3110 specified. */
3111 tem = Qnil;
3114 #else /* not USE_TOOLKIT_SCROLL_BARS */
3116 tem = Qnil;
3118 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3121 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
3122 return tem;
3127 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
3128 doc: /* Parse an X-style geometry string STRING.
3129 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
3130 The properties returned may include `top', `left', `height', and `width'.
3131 The value of `left' or `top' may be an integer,
3132 or a list (+ N) meaning N pixels relative to top/left corner,
3133 or a list (- N) meaning -N pixels relative to bottom/right corner. */)
3134 (string)
3135 Lisp_Object string;
3137 int geometry, x, y;
3138 unsigned int width, height;
3139 Lisp_Object result;
3141 CHECK_STRING (string);
3143 geometry = XParseGeometry ((char *) SDATA (string),
3144 &x, &y, &width, &height);
3146 #if 0
3147 if (!!(geometry & XValue) != !!(geometry & YValue))
3148 error ("Must specify both x and y position, or neither");
3149 #endif
3151 result = Qnil;
3152 if (geometry & XValue)
3154 Lisp_Object element;
3156 if (x >= 0 && (geometry & XNegative))
3157 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
3158 else if (x < 0 && ! (geometry & XNegative))
3159 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
3160 else
3161 element = Fcons (Qleft, make_number (x));
3162 result = Fcons (element, result);
3165 if (geometry & YValue)
3167 Lisp_Object element;
3169 if (y >= 0 && (geometry & YNegative))
3170 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
3171 else if (y < 0 && ! (geometry & YNegative))
3172 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
3173 else
3174 element = Fcons (Qtop, make_number (y));
3175 result = Fcons (element, result);
3178 if (geometry & WidthValue)
3179 result = Fcons (Fcons (Qwidth, make_number (width)), result);
3180 if (geometry & HeightValue)
3181 result = Fcons (Fcons (Qheight, make_number (height)), result);
3183 return result;
3186 /* Calculate the desired size and position of this window,
3187 and return the flags saying which aspects were specified.
3189 This function does not make the coordinates positive. */
3191 #define DEFAULT_ROWS 40
3192 #define DEFAULT_COLS 80
3194 static int
3195 x_figure_window_size (f, parms)
3196 struct frame *f;
3197 Lisp_Object parms;
3199 register Lisp_Object tem0, tem1, tem2;
3200 long window_prompting = 0;
3201 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3203 /* Default values if we fall through.
3204 Actually, if that happens we should get
3205 window manager prompting. */
3206 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3207 f->height = DEFAULT_ROWS;
3208 /* Window managers expect that if program-specified
3209 positions are not (0,0), they're intentional, not defaults. */
3210 f->output_data.x->top_pos = 0;
3211 f->output_data.x->left_pos = 0;
3213 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3214 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3215 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3216 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3218 if (!EQ (tem0, Qunbound))
3220 CHECK_NUMBER (tem0);
3221 f->height = XINT (tem0);
3223 if (!EQ (tem1, Qunbound))
3225 CHECK_NUMBER (tem1);
3226 SET_FRAME_WIDTH (f, XINT (tem1));
3228 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3229 window_prompting |= USSize;
3230 else
3231 window_prompting |= PSize;
3234 f->output_data.x->vertical_scroll_bar_extra
3235 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3237 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3239 x_compute_fringe_widths (f, 0);
3241 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3242 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3244 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3245 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3246 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3247 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3249 if (EQ (tem0, Qminus))
3251 f->output_data.x->top_pos = 0;
3252 window_prompting |= YNegative;
3254 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3255 && CONSP (XCDR (tem0))
3256 && INTEGERP (XCAR (XCDR (tem0))))
3258 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3259 window_prompting |= YNegative;
3261 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3262 && CONSP (XCDR (tem0))
3263 && INTEGERP (XCAR (XCDR (tem0))))
3265 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3267 else if (EQ (tem0, Qunbound))
3268 f->output_data.x->top_pos = 0;
3269 else
3271 CHECK_NUMBER (tem0);
3272 f->output_data.x->top_pos = XINT (tem0);
3273 if (f->output_data.x->top_pos < 0)
3274 window_prompting |= YNegative;
3277 if (EQ (tem1, Qminus))
3279 f->output_data.x->left_pos = 0;
3280 window_prompting |= XNegative;
3282 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3283 && CONSP (XCDR (tem1))
3284 && INTEGERP (XCAR (XCDR (tem1))))
3286 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3287 window_prompting |= XNegative;
3289 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3290 && CONSP (XCDR (tem1))
3291 && INTEGERP (XCAR (XCDR (tem1))))
3293 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3295 else if (EQ (tem1, Qunbound))
3296 f->output_data.x->left_pos = 0;
3297 else
3299 CHECK_NUMBER (tem1);
3300 f->output_data.x->left_pos = XINT (tem1);
3301 if (f->output_data.x->left_pos < 0)
3302 window_prompting |= XNegative;
3305 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3306 window_prompting |= USPosition;
3307 else
3308 window_prompting |= PPosition;
3311 if (f->output_data.x->want_fullscreen != FULLSCREEN_NONE)
3313 int left, top;
3314 int width, height;
3316 /* It takes both for some WM:s to place it where we want */
3317 window_prompting = USPosition | PPosition;
3318 x_fullscreen_adjust (f, &width, &height, &top, &left);
3319 f->width = width;
3320 f->height = height;
3321 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3322 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3323 f->output_data.x->left_pos = left;
3324 f->output_data.x->top_pos = top;
3327 return window_prompting;
3330 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3332 Status
3333 XSetWMProtocols (dpy, w, protocols, count)
3334 Display *dpy;
3335 Window w;
3336 Atom *protocols;
3337 int count;
3339 Atom prop;
3340 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3341 if (prop == None) return False;
3342 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3343 (unsigned char *) protocols, count);
3344 return True;
3346 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3348 #ifdef USE_X_TOOLKIT
3350 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3351 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3352 already be present because of the toolkit (Motif adds some of them,
3353 for example, but Xt doesn't). */
3355 static void
3356 hack_wm_protocols (f, widget)
3357 FRAME_PTR f;
3358 Widget widget;
3360 Display *dpy = XtDisplay (widget);
3361 Window w = XtWindow (widget);
3362 int need_delete = 1;
3363 int need_focus = 1;
3364 int need_save = 1;
3366 BLOCK_INPUT;
3368 Atom type, *atoms = 0;
3369 int format = 0;
3370 unsigned long nitems = 0;
3371 unsigned long bytes_after;
3373 if ((XGetWindowProperty (dpy, w,
3374 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3375 (long)0, (long)100, False, XA_ATOM,
3376 &type, &format, &nitems, &bytes_after,
3377 (unsigned char **) &atoms)
3378 == Success)
3379 && format == 32 && type == XA_ATOM)
3380 while (nitems > 0)
3382 nitems--;
3383 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3384 need_delete = 0;
3385 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3386 need_focus = 0;
3387 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3388 need_save = 0;
3390 if (atoms) XFree ((char *) atoms);
3393 Atom props [10];
3394 int count = 0;
3395 if (need_delete)
3396 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3397 if (need_focus)
3398 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3399 if (need_save)
3400 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3401 if (count)
3402 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3403 XA_ATOM, 32, PropModeAppend,
3404 (unsigned char *) props, count);
3406 UNBLOCK_INPUT;
3408 #endif
3412 /* Support routines for XIC (X Input Context). */
3414 #ifdef HAVE_X_I18N
3416 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3417 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3420 /* Supported XIM styles, ordered by preferenc. */
3422 static XIMStyle supported_xim_styles[] =
3424 XIMPreeditPosition | XIMStatusArea,
3425 XIMPreeditPosition | XIMStatusNothing,
3426 XIMPreeditPosition | XIMStatusNone,
3427 XIMPreeditNothing | XIMStatusArea,
3428 XIMPreeditNothing | XIMStatusNothing,
3429 XIMPreeditNothing | XIMStatusNone,
3430 XIMPreeditNone | XIMStatusArea,
3431 XIMPreeditNone | XIMStatusNothing,
3432 XIMPreeditNone | XIMStatusNone,
3437 /* Create an X fontset on frame F with base font name
3438 BASE_FONTNAME.. */
3440 static XFontSet
3441 xic_create_xfontset (f, base_fontname)
3442 struct frame *f;
3443 char *base_fontname;
3445 XFontSet xfs;
3446 char **missing_list;
3447 int missing_count;
3448 char *def_string;
3450 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3451 base_fontname, &missing_list,
3452 &missing_count, &def_string);
3453 if (missing_list)
3454 XFreeStringList (missing_list);
3456 /* No need to free def_string. */
3457 return xfs;
3461 /* Value is the best input style, given user preferences USER (already
3462 checked to be supported by Emacs), and styles supported by the
3463 input method XIM. */
3465 static XIMStyle
3466 best_xim_style (user, xim)
3467 XIMStyles *user;
3468 XIMStyles *xim;
3470 int i, j;
3472 for (i = 0; i < user->count_styles; ++i)
3473 for (j = 0; j < xim->count_styles; ++j)
3474 if (user->supported_styles[i] == xim->supported_styles[j])
3475 return user->supported_styles[i];
3477 /* Return the default style. */
3478 return XIMPreeditNothing | XIMStatusNothing;
3481 /* Create XIC for frame F. */
3483 static XIMStyle xic_style;
3485 void
3486 create_frame_xic (f)
3487 struct frame *f;
3489 XIM xim;
3490 XIC xic = NULL;
3491 XFontSet xfs = NULL;
3493 if (FRAME_XIC (f))
3494 return;
3496 xim = FRAME_X_XIM (f);
3497 if (xim)
3499 XRectangle s_area;
3500 XPoint spot;
3501 XVaNestedList preedit_attr;
3502 XVaNestedList status_attr;
3503 char *base_fontname;
3504 int fontset;
3506 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3507 spot.x = 0; spot.y = 1;
3508 /* Create X fontset. */
3509 fontset = FRAME_FONTSET (f);
3510 if (fontset < 0)
3511 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3512 else
3514 /* Determine the base fontname from the ASCII font name of
3515 FONTSET. */
3516 char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
3517 char *p = ascii_font;
3518 int i;
3520 for (i = 0; *p; p++)
3521 if (*p == '-') i++;
3522 if (i != 14)
3523 /* As the font name doesn't conform to XLFD, we can't
3524 modify it to get a suitable base fontname for the
3525 frame. */
3526 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3527 else
3529 int len = strlen (ascii_font) + 1;
3530 char *p1 = NULL;
3532 for (i = 0, p = ascii_font; i < 8; p++)
3534 if (*p == '-')
3536 i++;
3537 if (i == 3)
3538 p1 = p + 1;
3541 base_fontname = (char *) alloca (len);
3542 bzero (base_fontname, len);
3543 strcpy (base_fontname, "-*-*-");
3544 bcopy (p1, base_fontname + 5, p - p1);
3545 strcat (base_fontname, "*-*-*-*-*-*-*");
3548 xfs = xic_create_xfontset (f, base_fontname);
3550 /* Determine XIC style. */
3551 if (xic_style == 0)
3553 XIMStyles supported_list;
3554 supported_list.count_styles = (sizeof supported_xim_styles
3555 / sizeof supported_xim_styles[0]);
3556 supported_list.supported_styles = supported_xim_styles;
3557 xic_style = best_xim_style (&supported_list,
3558 FRAME_X_XIM_STYLES (f));
3561 preedit_attr = XVaCreateNestedList (0,
3562 XNFontSet, xfs,
3563 XNForeground,
3564 FRAME_FOREGROUND_PIXEL (f),
3565 XNBackground,
3566 FRAME_BACKGROUND_PIXEL (f),
3567 (xic_style & XIMPreeditPosition
3568 ? XNSpotLocation
3569 : NULL),
3570 &spot,
3571 NULL);
3572 status_attr = XVaCreateNestedList (0,
3573 XNArea,
3574 &s_area,
3575 XNFontSet,
3576 xfs,
3577 XNForeground,
3578 FRAME_FOREGROUND_PIXEL (f),
3579 XNBackground,
3580 FRAME_BACKGROUND_PIXEL (f),
3581 NULL);
3583 xic = XCreateIC (xim,
3584 XNInputStyle, xic_style,
3585 XNClientWindow, FRAME_X_WINDOW(f),
3586 XNFocusWindow, FRAME_X_WINDOW(f),
3587 XNStatusAttributes, status_attr,
3588 XNPreeditAttributes, preedit_attr,
3589 NULL);
3590 XFree (preedit_attr);
3591 XFree (status_attr);
3594 FRAME_XIC (f) = xic;
3595 FRAME_XIC_STYLE (f) = xic_style;
3596 FRAME_XIC_FONTSET (f) = xfs;
3600 /* Destroy XIC and free XIC fontset of frame F, if any. */
3602 void
3603 free_frame_xic (f)
3604 struct frame *f;
3606 if (FRAME_XIC (f) == NULL)
3607 return;
3609 XDestroyIC (FRAME_XIC (f));
3610 if (FRAME_XIC_FONTSET (f))
3611 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3613 FRAME_XIC (f) = NULL;
3614 FRAME_XIC_FONTSET (f) = NULL;
3618 /* Place preedit area for XIC of window W's frame to specified
3619 pixel position X/Y. X and Y are relative to window W. */
3621 void
3622 xic_set_preeditarea (w, x, y)
3623 struct window *w;
3624 int x, y;
3626 struct frame *f = XFRAME (w->frame);
3627 XVaNestedList attr;
3628 XPoint spot;
3630 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3631 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3632 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3633 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3634 XFree (attr);
3638 /* Place status area for XIC in bottom right corner of frame F.. */
3640 void
3641 xic_set_statusarea (f)
3642 struct frame *f;
3644 XIC xic = FRAME_XIC (f);
3645 XVaNestedList attr;
3646 XRectangle area;
3647 XRectangle *needed;
3649 /* Negotiate geometry of status area. If input method has existing
3650 status area, use its current size. */
3651 area.x = area.y = area.width = area.height = 0;
3652 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3653 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3654 XFree (attr);
3656 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3657 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3658 XFree (attr);
3660 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3662 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3663 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3664 XFree (attr);
3667 area.width = needed->width;
3668 area.height = needed->height;
3669 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3670 area.y = (PIXEL_HEIGHT (f) - area.height
3671 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3672 XFree (needed);
3674 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3675 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3676 XFree (attr);
3680 /* Set X fontset for XIC of frame F, using base font name
3681 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3683 void
3684 xic_set_xfontset (f, base_fontname)
3685 struct frame *f;
3686 char *base_fontname;
3688 XVaNestedList attr;
3689 XFontSet xfs;
3691 xfs = xic_create_xfontset (f, base_fontname);
3693 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3694 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3695 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3696 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3697 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3698 XFree (attr);
3700 if (FRAME_XIC_FONTSET (f))
3701 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3702 FRAME_XIC_FONTSET (f) = xfs;
3705 #endif /* HAVE_X_I18N */
3709 #ifdef USE_X_TOOLKIT
3711 /* Create and set up the X widget for frame F. */
3713 static void
3714 x_window (f, window_prompting, minibuffer_only)
3715 struct frame *f;
3716 long window_prompting;
3717 int minibuffer_only;
3719 XClassHint class_hints;
3720 XSetWindowAttributes attributes;
3721 unsigned long attribute_mask;
3722 Widget shell_widget;
3723 Widget pane_widget;
3724 Widget frame_widget;
3725 Arg al [25];
3726 int ac;
3728 BLOCK_INPUT;
3730 /* Use the resource name as the top-level widget name
3731 for looking up resources. Make a non-Lisp copy
3732 for the window manager, so GC relocation won't bother it.
3734 Elsewhere we specify the window name for the window manager. */
3737 char *str = (char *) SDATA (Vx_resource_name);
3738 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3739 strcpy (f->namebuf, str);
3742 ac = 0;
3743 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3744 XtSetArg (al[ac], XtNinput, 1); ac++;
3745 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3746 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3747 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3748 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3749 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3750 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3751 applicationShellWidgetClass,
3752 FRAME_X_DISPLAY (f), al, ac);
3754 f->output_data.x->widget = shell_widget;
3755 /* maybe_set_screen_title_format (shell_widget); */
3757 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3758 (widget_value *) NULL,
3759 shell_widget, False,
3760 (lw_callback) NULL,
3761 (lw_callback) NULL,
3762 (lw_callback) NULL,
3763 (lw_callback) NULL);
3765 ac = 0;
3766 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3767 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3768 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3769 XtSetValues (pane_widget, al, ac);
3770 f->output_data.x->column_widget = pane_widget;
3772 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3773 the emacs screen when changing menubar. This reduces flickering. */
3775 ac = 0;
3776 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3777 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3778 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3779 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3780 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3781 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3782 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3783 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3784 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3785 al, ac);
3787 f->output_data.x->edit_widget = frame_widget;
3789 XtManageChild (frame_widget);
3791 /* Do some needed geometry management. */
3793 int len;
3794 char *tem, shell_position[32];
3795 Arg al[2];
3796 int ac = 0;
3797 int extra_borders = 0;
3798 int menubar_size
3799 = (f->output_data.x->menubar_widget
3800 ? (f->output_data.x->menubar_widget->core.height
3801 + f->output_data.x->menubar_widget->core.border_width)
3802 : 0);
3804 #if 0 /* Experimentally, we now get the right results
3805 for -geometry -0-0 without this. 24 Aug 96, rms. */
3806 if (FRAME_EXTERNAL_MENU_BAR (f))
3808 Dimension ibw = 0;
3809 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3810 menubar_size += ibw;
3812 #endif
3814 f->output_data.x->menubar_height = menubar_size;
3816 #ifndef USE_LUCID
3817 /* Motif seems to need this amount added to the sizes
3818 specified for the shell widget. The Athena/Lucid widgets don't.
3819 Both conclusions reached experimentally. -- rms. */
3820 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3821 &extra_borders, NULL);
3822 extra_borders *= 2;
3823 #endif
3825 /* Convert our geometry parameters into a geometry string
3826 and specify it.
3827 Note that we do not specify here whether the position
3828 is a user-specified or program-specified one.
3829 We pass that information later, in x_wm_set_size_hints. */
3831 int left = f->output_data.x->left_pos;
3832 int xneg = window_prompting & XNegative;
3833 int top = f->output_data.x->top_pos;
3834 int yneg = window_prompting & YNegative;
3835 if (xneg)
3836 left = -left;
3837 if (yneg)
3838 top = -top;
3840 if (window_prompting & USPosition)
3841 sprintf (shell_position, "=%dx%d%c%d%c%d",
3842 PIXEL_WIDTH (f) + extra_borders,
3843 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3844 (xneg ? '-' : '+'), left,
3845 (yneg ? '-' : '+'), top);
3846 else
3847 sprintf (shell_position, "=%dx%d",
3848 PIXEL_WIDTH (f) + extra_borders,
3849 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3852 len = strlen (shell_position) + 1;
3853 /* We don't free this because we don't know whether
3854 it is safe to free it while the frame exists.
3855 It isn't worth the trouble of arranging to free it
3856 when the frame is deleted. */
3857 tem = (char *) xmalloc (len);
3858 strncpy (tem, shell_position, len);
3859 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3860 XtSetValues (shell_widget, al, ac);
3863 XtManageChild (pane_widget);
3864 XtRealizeWidget (shell_widget);
3866 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3868 validate_x_resource_name ();
3870 class_hints.res_name = (char *) SDATA (Vx_resource_name);
3871 class_hints.res_class = (char *) SDATA (Vx_resource_class);
3872 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3874 #ifdef HAVE_X_I18N
3875 FRAME_XIC (f) = NULL;
3876 #ifdef USE_XIM
3877 create_frame_xic (f);
3878 #endif
3879 #endif
3881 f->output_data.x->wm_hints.input = True;
3882 f->output_data.x->wm_hints.flags |= InputHint;
3883 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3884 &f->output_data.x->wm_hints);
3886 hack_wm_protocols (f, shell_widget);
3888 #ifdef HACK_EDITRES
3889 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3890 #endif
3892 /* Do a stupid property change to force the server to generate a
3893 PropertyNotify event so that the event_stream server timestamp will
3894 be initialized to something relevant to the time we created the window.
3896 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3897 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3898 XA_ATOM, 32, PropModeAppend,
3899 (unsigned char*) NULL, 0);
3901 /* Make all the standard events reach the Emacs frame. */
3902 attributes.event_mask = STANDARD_EVENT_SET;
3904 #ifdef HAVE_X_I18N
3905 if (FRAME_XIC (f))
3907 /* XIM server might require some X events. */
3908 unsigned long fevent = NoEventMask;
3909 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3910 attributes.event_mask |= fevent;
3912 #endif /* HAVE_X_I18N */
3914 attribute_mask = CWEventMask;
3915 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3916 attribute_mask, &attributes);
3918 XtMapWidget (frame_widget);
3920 /* x_set_name normally ignores requests to set the name if the
3921 requested name is the same as the current name. This is the one
3922 place where that assumption isn't correct; f->name is set, but
3923 the X server hasn't been told. */
3925 Lisp_Object name;
3926 int explicit = f->explicit_name;
3928 f->explicit_name = 0;
3929 name = f->name;
3930 f->name = Qnil;
3931 x_set_name (f, name, explicit);
3934 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3935 f->output_data.x->text_cursor);
3937 UNBLOCK_INPUT;
3939 /* This is a no-op, except under Motif. Make sure main areas are
3940 set to something reasonable, in case we get an error later. */
3941 lw_set_main_areas (pane_widget, 0, frame_widget);
3944 #else /* not USE_X_TOOLKIT */
3946 /* Create and set up the X window for frame F. */
3948 void
3949 x_window (f)
3950 struct frame *f;
3953 XClassHint class_hints;
3954 XSetWindowAttributes attributes;
3955 unsigned long attribute_mask;
3957 attributes.background_pixel = f->output_data.x->background_pixel;
3958 attributes.border_pixel = f->output_data.x->border_pixel;
3959 attributes.bit_gravity = StaticGravity;
3960 attributes.backing_store = NotUseful;
3961 attributes.save_under = True;
3962 attributes.event_mask = STANDARD_EVENT_SET;
3963 attributes.colormap = FRAME_X_COLORMAP (f);
3964 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3965 | CWColormap);
3967 BLOCK_INPUT;
3968 FRAME_X_WINDOW (f)
3969 = XCreateWindow (FRAME_X_DISPLAY (f),
3970 f->output_data.x->parent_desc,
3971 f->output_data.x->left_pos,
3972 f->output_data.x->top_pos,
3973 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3974 f->output_data.x->border_width,
3975 CopyFromParent, /* depth */
3976 InputOutput, /* class */
3977 FRAME_X_VISUAL (f),
3978 attribute_mask, &attributes);
3980 #ifdef HAVE_X_I18N
3981 #ifdef USE_XIM
3982 create_frame_xic (f);
3983 if (FRAME_XIC (f))
3985 /* XIM server might require some X events. */
3986 unsigned long fevent = NoEventMask;
3987 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3988 attributes.event_mask |= fevent;
3989 attribute_mask = CWEventMask;
3990 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3991 attribute_mask, &attributes);
3993 #endif
3994 #endif /* HAVE_X_I18N */
3996 validate_x_resource_name ();
3998 class_hints.res_name = (char *) SDATA (Vx_resource_name);
3999 class_hints.res_class = (char *) SDATA (Vx_resource_class);
4000 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
4002 /* The menubar is part of the ordinary display;
4003 it does not count in addition to the height of the window. */
4004 f->output_data.x->menubar_height = 0;
4006 /* This indicates that we use the "Passive Input" input model.
4007 Unless we do this, we don't get the Focus{In,Out} events that we
4008 need to draw the cursor correctly. Accursed bureaucrats.
4009 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
4011 f->output_data.x->wm_hints.input = True;
4012 f->output_data.x->wm_hints.flags |= InputHint;
4013 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4014 &f->output_data.x->wm_hints);
4015 f->output_data.x->wm_hints.icon_pixmap = None;
4017 /* Request "save yourself" and "delete window" commands from wm. */
4019 Atom protocols[2];
4020 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
4021 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
4022 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
4025 /* x_set_name normally ignores requests to set the name if the
4026 requested name is the same as the current name. This is the one
4027 place where that assumption isn't correct; f->name is set, but
4028 the X server hasn't been told. */
4030 Lisp_Object name;
4031 int explicit = f->explicit_name;
4033 f->explicit_name = 0;
4034 name = f->name;
4035 f->name = Qnil;
4036 x_set_name (f, name, explicit);
4039 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4040 f->output_data.x->text_cursor);
4042 UNBLOCK_INPUT;
4044 if (FRAME_X_WINDOW (f) == 0)
4045 error ("Unable to create window");
4048 #endif /* not USE_X_TOOLKIT */
4050 /* Handle the icon stuff for this window. Perhaps later we might
4051 want an x_set_icon_position which can be called interactively as
4052 well. */
4054 static void
4055 x_icon (f, parms)
4056 struct frame *f;
4057 Lisp_Object parms;
4059 Lisp_Object icon_x, icon_y;
4060 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4062 /* Set the position of the icon. Note that twm groups all
4063 icons in an icon window. */
4064 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4065 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4066 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
4068 CHECK_NUMBER (icon_x);
4069 CHECK_NUMBER (icon_y);
4071 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
4072 error ("Both left and top icon corners of icon must be specified");
4074 BLOCK_INPUT;
4076 if (! EQ (icon_x, Qunbound))
4077 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
4079 /* Start up iconic or window? */
4080 x_wm_set_window_state
4081 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
4082 Qicon)
4083 ? IconicState
4084 : NormalState));
4086 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
4087 ? f->icon_name
4088 : f->name)));
4090 UNBLOCK_INPUT;
4093 /* Make the GCs needed for this window, setting the
4094 background, border and mouse colors; also create the
4095 mouse cursor and the gray border tile. */
4097 static char cursor_bits[] =
4099 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4105 static void
4106 x_make_gc (f)
4107 struct frame *f;
4109 XGCValues gc_values;
4111 BLOCK_INPUT;
4113 /* Create the GCs of this frame.
4114 Note that many default values are used. */
4116 /* Normal video */
4117 gc_values.font = f->output_data.x->font->fid;
4118 gc_values.foreground = f->output_data.x->foreground_pixel;
4119 gc_values.background = f->output_data.x->background_pixel;
4120 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
4121 f->output_data.x->normal_gc
4122 = XCreateGC (FRAME_X_DISPLAY (f),
4123 FRAME_X_WINDOW (f),
4124 GCLineWidth | GCFont | GCForeground | GCBackground,
4125 &gc_values);
4127 /* Reverse video style. */
4128 gc_values.foreground = f->output_data.x->background_pixel;
4129 gc_values.background = f->output_data.x->foreground_pixel;
4130 f->output_data.x->reverse_gc
4131 = XCreateGC (FRAME_X_DISPLAY (f),
4132 FRAME_X_WINDOW (f),
4133 GCFont | GCForeground | GCBackground | GCLineWidth,
4134 &gc_values);
4136 /* Cursor has cursor-color background, background-color foreground. */
4137 gc_values.foreground = f->output_data.x->background_pixel;
4138 gc_values.background = f->output_data.x->cursor_pixel;
4139 gc_values.fill_style = FillOpaqueStippled;
4140 gc_values.stipple
4141 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
4142 FRAME_X_DISPLAY_INFO (f)->root_window,
4143 cursor_bits, 16, 16);
4144 f->output_data.x->cursor_gc
4145 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4146 (GCFont | GCForeground | GCBackground
4147 | GCFillStyle /* | GCStipple */ | GCLineWidth),
4148 &gc_values);
4150 /* Reliefs. */
4151 f->output_data.x->white_relief.gc = 0;
4152 f->output_data.x->black_relief.gc = 0;
4154 /* Create the gray border tile used when the pointer is not in
4155 the frame. Since this depends on the frame's pixel values,
4156 this must be done on a per-frame basis. */
4157 f->output_data.x->border_tile
4158 = (XCreatePixmapFromBitmapData
4159 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4160 gray_bits, gray_width, gray_height,
4161 f->output_data.x->foreground_pixel,
4162 f->output_data.x->background_pixel,
4163 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4165 UNBLOCK_INPUT;
4169 /* Free what was was allocated in x_make_gc. */
4171 void
4172 x_free_gcs (f)
4173 struct frame *f;
4175 Display *dpy = FRAME_X_DISPLAY (f);
4177 BLOCK_INPUT;
4179 if (f->output_data.x->normal_gc)
4181 XFreeGC (dpy, f->output_data.x->normal_gc);
4182 f->output_data.x->normal_gc = 0;
4185 if (f->output_data.x->reverse_gc)
4187 XFreeGC (dpy, f->output_data.x->reverse_gc);
4188 f->output_data.x->reverse_gc = 0;
4191 if (f->output_data.x->cursor_gc)
4193 XFreeGC (dpy, f->output_data.x->cursor_gc);
4194 f->output_data.x->cursor_gc = 0;
4197 if (f->output_data.x->border_tile)
4199 XFreePixmap (dpy, f->output_data.x->border_tile);
4200 f->output_data.x->border_tile = 0;
4203 UNBLOCK_INPUT;
4207 /* Handler for signals raised during x_create_frame and
4208 x_create_top_frame. FRAME is the frame which is partially
4209 constructed. */
4211 static Lisp_Object
4212 unwind_create_frame (frame)
4213 Lisp_Object frame;
4215 struct frame *f = XFRAME (frame);
4217 /* If frame is ``official'', nothing to do. */
4218 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4220 #if GLYPH_DEBUG
4221 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4222 #endif
4224 x_free_frame_resources (f);
4226 /* Check that reference counts are indeed correct. */
4227 xassert (dpyinfo->reference_count == dpyinfo_refcount);
4228 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4229 return Qt;
4232 return Qnil;
4236 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4237 1, 1, 0,
4238 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
4239 Returns an Emacs frame object.
4240 ALIST is an alist of frame parameters.
4241 If the parameters specify that the frame should not have a minibuffer,
4242 and do not specify a specific minibuffer window to use,
4243 then `default-minibuffer-frame' must be a frame whose minibuffer can
4244 be shared by the new frame.
4246 This function is an internal primitive--use `make-frame' instead. */)
4247 (parms)
4248 Lisp_Object parms;
4250 struct frame *f;
4251 Lisp_Object frame, tem;
4252 Lisp_Object name;
4253 int minibuffer_only = 0;
4254 long window_prompting = 0;
4255 int width, height;
4256 int count = SPECPDL_INDEX ();
4257 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4258 Lisp_Object display;
4259 struct x_display_info *dpyinfo = NULL;
4260 Lisp_Object parent;
4261 struct kboard *kb;
4263 check_x ();
4265 /* Use this general default value to start with
4266 until we know if this frame has a specified name. */
4267 Vx_resource_name = Vinvocation_name;
4269 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
4270 if (EQ (display, Qunbound))
4271 display = Qnil;
4272 dpyinfo = check_x_display_info (display);
4273 #ifdef MULTI_KBOARD
4274 kb = dpyinfo->kboard;
4275 #else
4276 kb = &the_only_kboard;
4277 #endif
4279 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4280 if (!STRINGP (name)
4281 && ! EQ (name, Qunbound)
4282 && ! NILP (name))
4283 error ("Invalid frame name--not a string or nil");
4285 if (STRINGP (name))
4286 Vx_resource_name = name;
4288 /* See if parent window is specified. */
4289 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4290 if (EQ (parent, Qunbound))
4291 parent = Qnil;
4292 if (! NILP (parent))
4293 CHECK_NUMBER (parent);
4295 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4296 /* No need to protect DISPLAY because that's not used after passing
4297 it to make_frame_without_minibuffer. */
4298 frame = Qnil;
4299 GCPRO4 (parms, parent, name, frame);
4300 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4301 RES_TYPE_SYMBOL);
4302 if (EQ (tem, Qnone) || NILP (tem))
4303 f = make_frame_without_minibuffer (Qnil, kb, display);
4304 else if (EQ (tem, Qonly))
4306 f = make_minibuffer_frame ();
4307 minibuffer_only = 1;
4309 else if (WINDOWP (tem))
4310 f = make_frame_without_minibuffer (tem, kb, display);
4311 else
4312 f = make_frame (1);
4314 XSETFRAME (frame, f);
4316 /* Note that X Windows does support scroll bars. */
4317 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4319 f->output_method = output_x_window;
4320 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4321 bzero (f->output_data.x, sizeof (struct x_output));
4322 f->output_data.x->icon_bitmap = -1;
4323 f->output_data.x->fontset = -1;
4324 f->output_data.x->scroll_bar_foreground_pixel = -1;
4325 f->output_data.x->scroll_bar_background_pixel = -1;
4326 #ifdef USE_TOOLKIT_SCROLL_BARS
4327 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4328 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4329 #endif /* USE_TOOLKIT_SCROLL_BARS */
4330 record_unwind_protect (unwind_create_frame, frame);
4332 f->icon_name
4333 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4334 RES_TYPE_STRING);
4335 if (! STRINGP (f->icon_name))
4336 f->icon_name = Qnil;
4338 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4339 #if GLYPH_DEBUG
4340 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
4341 dpyinfo_refcount = dpyinfo->reference_count;
4342 #endif /* GLYPH_DEBUG */
4343 #ifdef MULTI_KBOARD
4344 FRAME_KBOARD (f) = kb;
4345 #endif
4347 /* These colors will be set anyway later, but it's important
4348 to get the color reference counts right, so initialize them! */
4350 Lisp_Object black;
4351 struct gcpro gcpro1;
4353 /* Function x_decode_color can signal an error. Make
4354 sure to initialize color slots so that we won't try
4355 to free colors we haven't allocated. */
4356 f->output_data.x->foreground_pixel = -1;
4357 f->output_data.x->background_pixel = -1;
4358 f->output_data.x->cursor_pixel = -1;
4359 f->output_data.x->cursor_foreground_pixel = -1;
4360 f->output_data.x->border_pixel = -1;
4361 f->output_data.x->mouse_pixel = -1;
4363 black = build_string ("black");
4364 GCPRO1 (black);
4365 f->output_data.x->foreground_pixel
4366 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4367 f->output_data.x->background_pixel
4368 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4369 f->output_data.x->cursor_pixel
4370 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4371 f->output_data.x->cursor_foreground_pixel
4372 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4373 f->output_data.x->border_pixel
4374 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4375 f->output_data.x->mouse_pixel
4376 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4377 UNGCPRO;
4380 /* Specify the parent under which to make this X window. */
4382 if (!NILP (parent))
4384 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4385 f->output_data.x->explicit_parent = 1;
4387 else
4389 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4390 f->output_data.x->explicit_parent = 0;
4393 /* Set the name; the functions to which we pass f expect the name to
4394 be set. */
4395 if (EQ (name, Qunbound) || NILP (name))
4397 f->name = build_string (dpyinfo->x_id_name);
4398 f->explicit_name = 0;
4400 else
4402 f->name = name;
4403 f->explicit_name = 1;
4404 /* use the frame's title when getting resources for this frame. */
4405 specbind (Qx_resource_name, name);
4408 /* Extract the window parameters from the supplied values
4409 that are needed to determine window geometry. */
4411 Lisp_Object font;
4413 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4415 BLOCK_INPUT;
4416 /* First, try whatever font the caller has specified. */
4417 if (STRINGP (font))
4419 tem = Fquery_fontset (font, Qnil);
4420 if (STRINGP (tem))
4421 font = x_new_fontset (f, SDATA (tem));
4422 else
4423 font = x_new_font (f, SDATA (font));
4426 /* Try out a font which we hope has bold and italic variations. */
4427 if (!STRINGP (font))
4428 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4429 if (!STRINGP (font))
4430 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4431 if (! STRINGP (font))
4432 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4433 if (! STRINGP (font))
4434 /* This was formerly the first thing tried, but it finds too many fonts
4435 and takes too long. */
4436 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4437 /* If those didn't work, look for something which will at least work. */
4438 if (! STRINGP (font))
4439 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4440 UNBLOCK_INPUT;
4441 if (! STRINGP (font))
4442 font = build_string ("fixed");
4444 x_default_parameter (f, parms, Qfont, font,
4445 "font", "Font", RES_TYPE_STRING);
4448 #ifdef USE_LUCID
4449 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4450 whereby it fails to get any font. */
4451 xlwmenu_default_font = f->output_data.x->font;
4452 #endif
4454 x_default_parameter (f, parms, Qborder_width, make_number (2),
4455 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4457 /* This defaults to 1 in order to match xterm. We recognize either
4458 internalBorderWidth or internalBorder (which is what xterm calls
4459 it). */
4460 if (NILP (Fassq (Qinternal_border_width, parms)))
4462 Lisp_Object value;
4464 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4465 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4466 if (! EQ (value, Qunbound))
4467 parms = Fcons (Fcons (Qinternal_border_width, value),
4468 parms);
4470 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4471 "internalBorderWidth", "internalBorderWidth",
4472 RES_TYPE_NUMBER);
4473 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4474 "verticalScrollBars", "ScrollBars",
4475 RES_TYPE_SYMBOL);
4477 /* Also do the stuff which must be set before the window exists. */
4478 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4479 "foreground", "Foreground", RES_TYPE_STRING);
4480 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4481 "background", "Background", RES_TYPE_STRING);
4482 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4483 "pointerColor", "Foreground", RES_TYPE_STRING);
4484 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4485 "cursorColor", "Foreground", RES_TYPE_STRING);
4486 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4487 "borderColor", "BorderColor", RES_TYPE_STRING);
4488 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4489 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4490 x_default_parameter (f, parms, Qline_spacing, Qnil,
4491 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4492 x_default_parameter (f, parms, Qleft_fringe, Qnil,
4493 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4494 x_default_parameter (f, parms, Qright_fringe, Qnil,
4495 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4497 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4498 "scrollBarForeground",
4499 "ScrollBarForeground", 1);
4500 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4501 "scrollBarBackground",
4502 "ScrollBarBackground", 0);
4504 /* Init faces before x_default_parameter is called for scroll-bar
4505 parameters because that function calls x_set_scroll_bar_width,
4506 which calls change_frame_size, which calls Fset_window_buffer,
4507 which runs hooks, which call Fvertical_motion. At the end, we
4508 end up in init_iterator with a null face cache, which should not
4509 happen. */
4510 init_frame_faces (f);
4512 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4513 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4514 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4515 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4516 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4517 "bufferPredicate", "BufferPredicate",
4518 RES_TYPE_SYMBOL);
4519 x_default_parameter (f, parms, Qtitle, Qnil,
4520 "title", "Title", RES_TYPE_STRING);
4521 x_default_parameter (f, parms, Qwait_for_wm, Qt,
4522 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4523 x_default_parameter (f, parms, Qfullscreen, Qnil,
4524 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4526 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4528 /* Add the tool-bar height to the initial frame height so that the
4529 user gets a text display area of the size he specified with -g or
4530 via .Xdefaults. Later changes of the tool-bar height don't
4531 change the frame size. This is done so that users can create
4532 tall Emacs frames without having to guess how tall the tool-bar
4533 will get. */
4534 if (FRAME_TOOL_BAR_LINES (f))
4536 int margin, relief, bar_height;
4538 relief = (tool_bar_button_relief >= 0
4539 ? tool_bar_button_relief
4540 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4542 if (INTEGERP (Vtool_bar_button_margin)
4543 && XINT (Vtool_bar_button_margin) > 0)
4544 margin = XFASTINT (Vtool_bar_button_margin);
4545 else if (CONSP (Vtool_bar_button_margin)
4546 && INTEGERP (XCDR (Vtool_bar_button_margin))
4547 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
4548 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4549 else
4550 margin = 0;
4552 bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4553 f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4556 /* Compute the size of the X window. */
4557 window_prompting = x_figure_window_size (f, parms);
4559 if (window_prompting & XNegative)
4561 if (window_prompting & YNegative)
4562 f->output_data.x->win_gravity = SouthEastGravity;
4563 else
4564 f->output_data.x->win_gravity = NorthEastGravity;
4566 else
4568 if (window_prompting & YNegative)
4569 f->output_data.x->win_gravity = SouthWestGravity;
4570 else
4571 f->output_data.x->win_gravity = NorthWestGravity;
4574 f->output_data.x->size_hint_flags = window_prompting;
4576 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4577 f->no_split = minibuffer_only || EQ (tem, Qt);
4579 /* Create the X widget or window. */
4580 #ifdef USE_X_TOOLKIT
4581 x_window (f, window_prompting, minibuffer_only);
4582 #else
4583 x_window (f);
4584 #endif
4586 x_icon (f, parms);
4587 x_make_gc (f);
4589 /* Now consider the frame official. */
4590 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4591 Vframe_list = Fcons (frame, Vframe_list);
4593 /* We need to do this after creating the X window, so that the
4594 icon-creation functions can say whose icon they're describing. */
4595 x_default_parameter (f, parms, Qicon_type, Qnil,
4596 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4598 x_default_parameter (f, parms, Qauto_raise, Qnil,
4599 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4600 x_default_parameter (f, parms, Qauto_lower, Qnil,
4601 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4602 x_default_parameter (f, parms, Qcursor_type, Qbox,
4603 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4604 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4605 "scrollBarWidth", "ScrollBarWidth",
4606 RES_TYPE_NUMBER);
4608 /* Dimensions, especially f->height, must be done via change_frame_size.
4609 Change will not be effected unless different from the current
4610 f->height. */
4611 width = f->width;
4612 height = f->height;
4614 f->height = 0;
4615 SET_FRAME_WIDTH (f, 0);
4616 change_frame_size (f, height, width, 1, 0, 0);
4618 /* Set up faces after all frame parameters are known. This call
4619 also merges in face attributes specified for new frames. If we
4620 don't do this, the `menu' face for instance won't have the right
4621 colors, and the menu bar won't appear in the specified colors for
4622 new frames. */
4623 call1 (Qface_set_after_frame_default, frame);
4625 #ifdef USE_X_TOOLKIT
4626 /* Create the menu bar. */
4627 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4629 /* If this signals an error, we haven't set size hints for the
4630 frame and we didn't make it visible. */
4631 initialize_frame_menubar (f);
4633 /* This is a no-op, except under Motif where it arranges the
4634 main window for the widgets on it. */
4635 lw_set_main_areas (f->output_data.x->column_widget,
4636 f->output_data.x->menubar_widget,
4637 f->output_data.x->edit_widget);
4639 #endif /* USE_X_TOOLKIT */
4641 /* Tell the server what size and position, etc, we want, and how
4642 badly we want them. This should be done after we have the menu
4643 bar so that its size can be taken into account. */
4644 BLOCK_INPUT;
4645 x_wm_set_size_hint (f, window_prompting, 0);
4646 UNBLOCK_INPUT;
4648 /* Make the window appear on the frame and enable display, unless
4649 the caller says not to. However, with explicit parent, Emacs
4650 cannot control visibility, so don't try. */
4651 if (! f->output_data.x->explicit_parent)
4653 Lisp_Object visibility;
4655 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4656 RES_TYPE_SYMBOL);
4657 if (EQ (visibility, Qunbound))
4658 visibility = Qt;
4660 if (EQ (visibility, Qicon))
4661 x_iconify_frame (f);
4662 else if (! NILP (visibility))
4663 x_make_frame_visible (f);
4664 else
4665 /* Must have been Qnil. */
4669 UNGCPRO;
4671 /* Make sure windows on this frame appear in calls to next-window
4672 and similar functions. */
4673 Vwindow_list = Qnil;
4675 return unbind_to (count, frame);
4679 /* FRAME is used only to get a handle on the X display. We don't pass the
4680 display info directly because we're called from frame.c, which doesn't
4681 know about that structure. */
4683 Lisp_Object
4684 x_get_focus_frame (frame)
4685 struct frame *frame;
4687 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4688 Lisp_Object xfocus;
4689 if (! dpyinfo->x_focus_frame)
4690 return Qnil;
4692 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4693 return xfocus;
4697 /* In certain situations, when the window manager follows a
4698 click-to-focus policy, there seems to be no way around calling
4699 XSetInputFocus to give another frame the input focus .
4701 In an ideal world, XSetInputFocus should generally be avoided so
4702 that applications don't interfere with the window manager's focus
4703 policy. But I think it's okay to use when it's clearly done
4704 following a user-command. */
4706 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4707 doc: /* Set the input focus to FRAME.
4708 FRAME nil means use the selected frame. */)
4709 (frame)
4710 Lisp_Object frame;
4712 struct frame *f = check_x_frame (frame);
4713 Display *dpy = FRAME_X_DISPLAY (f);
4714 int count;
4716 BLOCK_INPUT;
4717 count = x_catch_errors (dpy);
4718 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4719 RevertToParent, CurrentTime);
4720 x_uncatch_errors (dpy, count);
4721 UNBLOCK_INPUT;
4723 return Qnil;
4727 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4728 doc: /* Internal function called by `color-defined-p', which see. */)
4729 (color, frame)
4730 Lisp_Object color, frame;
4732 XColor foo;
4733 FRAME_PTR f = check_x_frame (frame);
4735 CHECK_STRING (color);
4737 if (x_defined_color (f, SDATA (color), &foo, 0))
4738 return Qt;
4739 else
4740 return Qnil;
4743 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4744 doc: /* Internal function called by `color-values', which see. */)
4745 (color, frame)
4746 Lisp_Object color, frame;
4748 XColor foo;
4749 FRAME_PTR f = check_x_frame (frame);
4751 CHECK_STRING (color);
4753 if (x_defined_color (f, SDATA (color), &foo, 0))
4755 Lisp_Object rgb[3];
4757 rgb[0] = make_number (foo.red);
4758 rgb[1] = make_number (foo.green);
4759 rgb[2] = make_number (foo.blue);
4760 return Flist (3, rgb);
4762 else
4763 return Qnil;
4766 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4767 doc: /* Internal function called by `display-color-p', which see. */)
4768 (display)
4769 Lisp_Object display;
4771 struct x_display_info *dpyinfo = check_x_display_info (display);
4773 if (dpyinfo->n_planes <= 2)
4774 return Qnil;
4776 switch (dpyinfo->visual->class)
4778 case StaticColor:
4779 case PseudoColor:
4780 case TrueColor:
4781 case DirectColor:
4782 return Qt;
4784 default:
4785 return Qnil;
4789 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4790 0, 1, 0,
4791 doc: /* Return t if the X display supports shades of gray.
4792 Note that color displays do support shades of gray.
4793 The optional argument DISPLAY specifies which display to ask about.
4794 DISPLAY should be either a frame or a display name (a string).
4795 If omitted or nil, that stands for the selected frame's display. */)
4796 (display)
4797 Lisp_Object display;
4799 struct x_display_info *dpyinfo = check_x_display_info (display);
4801 if (dpyinfo->n_planes <= 1)
4802 return Qnil;
4804 switch (dpyinfo->visual->class)
4806 case StaticColor:
4807 case PseudoColor:
4808 case TrueColor:
4809 case DirectColor:
4810 case StaticGray:
4811 case GrayScale:
4812 return Qt;
4814 default:
4815 return Qnil;
4819 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4820 0, 1, 0,
4821 doc: /* Returns the width in pixels of the X display DISPLAY.
4822 The optional argument DISPLAY specifies which display to ask about.
4823 DISPLAY should be either a frame or a display name (a string).
4824 If omitted or nil, that stands for the selected frame's display. */)
4825 (display)
4826 Lisp_Object display;
4828 struct x_display_info *dpyinfo = check_x_display_info (display);
4830 return make_number (dpyinfo->width);
4833 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4834 Sx_display_pixel_height, 0, 1, 0,
4835 doc: /* Returns the height in pixels of the X display DISPLAY.
4836 The optional argument DISPLAY specifies which display to ask about.
4837 DISPLAY should be either a frame or a display name (a string).
4838 If omitted or nil, that stands for the selected frame's display. */)
4839 (display)
4840 Lisp_Object display;
4842 struct x_display_info *dpyinfo = check_x_display_info (display);
4844 return make_number (dpyinfo->height);
4847 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4848 0, 1, 0,
4849 doc: /* Returns the number of bitplanes of the X display DISPLAY.
4850 The optional argument DISPLAY specifies which display to ask about.
4851 DISPLAY should be either a frame or a display name (a string).
4852 If omitted or nil, that stands for the selected frame's display. */)
4853 (display)
4854 Lisp_Object display;
4856 struct x_display_info *dpyinfo = check_x_display_info (display);
4858 return make_number (dpyinfo->n_planes);
4861 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4862 0, 1, 0,
4863 doc: /* Returns the number of color cells of the X display DISPLAY.
4864 The optional argument DISPLAY specifies which display to ask about.
4865 DISPLAY should be either a frame or a display name (a string).
4866 If omitted or nil, that stands for the selected frame's display. */)
4867 (display)
4868 Lisp_Object display;
4870 struct x_display_info *dpyinfo = check_x_display_info (display);
4872 return make_number (DisplayCells (dpyinfo->display,
4873 XScreenNumberOfScreen (dpyinfo->screen)));
4876 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4877 Sx_server_max_request_size,
4878 0, 1, 0,
4879 doc: /* Returns the maximum request size of the X server of display DISPLAY.
4880 The optional argument DISPLAY specifies which display to ask about.
4881 DISPLAY should be either a frame or a display name (a string).
4882 If omitted or nil, that stands for the selected frame's display. */)
4883 (display)
4884 Lisp_Object display;
4886 struct x_display_info *dpyinfo = check_x_display_info (display);
4888 return make_number (MAXREQUEST (dpyinfo->display));
4891 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4892 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
4893 The optional argument DISPLAY specifies which display to ask about.
4894 DISPLAY should be either a frame or a display name (a string).
4895 If omitted or nil, that stands for the selected frame's display. */)
4896 (display)
4897 Lisp_Object display;
4899 struct x_display_info *dpyinfo = check_x_display_info (display);
4900 char *vendor = ServerVendor (dpyinfo->display);
4902 if (! vendor) vendor = "";
4903 return build_string (vendor);
4906 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4907 doc: /* Returns the version numbers of the X server of display DISPLAY.
4908 The value is a list of three integers: the major and minor
4909 version numbers of the X Protocol in use, and the vendor-specific release
4910 number. See also the function `x-server-vendor'.
4912 The optional argument DISPLAY specifies which display to ask about.
4913 DISPLAY should be either a frame or a display name (a string).
4914 If omitted or nil, that stands for the selected frame's display. */)
4915 (display)
4916 Lisp_Object display;
4918 struct x_display_info *dpyinfo = check_x_display_info (display);
4919 Display *dpy = dpyinfo->display;
4921 return Fcons (make_number (ProtocolVersion (dpy)),
4922 Fcons (make_number (ProtocolRevision (dpy)),
4923 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4926 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4927 doc: /* Return the number of screens on the X server of display DISPLAY.
4928 The optional argument DISPLAY specifies which display to ask about.
4929 DISPLAY should be either a frame or a display name (a string).
4930 If omitted or nil, that stands for the selected frame's display. */)
4931 (display)
4932 Lisp_Object display;
4934 struct x_display_info *dpyinfo = check_x_display_info (display);
4936 return make_number (ScreenCount (dpyinfo->display));
4939 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4940 doc: /* Return the height in millimeters of the X display DISPLAY.
4941 The optional argument DISPLAY specifies which display to ask about.
4942 DISPLAY should be either a frame or a display name (a string).
4943 If omitted or nil, that stands for the selected frame's display. */)
4944 (display)
4945 Lisp_Object display;
4947 struct x_display_info *dpyinfo = check_x_display_info (display);
4949 return make_number (HeightMMOfScreen (dpyinfo->screen));
4952 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4953 doc: /* Return the width in millimeters of the X display DISPLAY.
4954 The optional argument DISPLAY specifies which display to ask about.
4955 DISPLAY should be either a frame or a display name (a string).
4956 If omitted or nil, that stands for the selected frame's display. */)
4957 (display)
4958 Lisp_Object display;
4960 struct x_display_info *dpyinfo = check_x_display_info (display);
4962 return make_number (WidthMMOfScreen (dpyinfo->screen));
4965 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4966 Sx_display_backing_store, 0, 1, 0,
4967 doc: /* Returns an indication of whether X display DISPLAY does backing store.
4968 The value may be `always', `when-mapped', or `not-useful'.
4969 The optional argument DISPLAY specifies which display to ask about.
4970 DISPLAY should be either a frame or a display name (a string).
4971 If omitted or nil, that stands for the selected frame's display. */)
4972 (display)
4973 Lisp_Object display;
4975 struct x_display_info *dpyinfo = check_x_display_info (display);
4976 Lisp_Object result;
4978 switch (DoesBackingStore (dpyinfo->screen))
4980 case Always:
4981 result = intern ("always");
4982 break;
4984 case WhenMapped:
4985 result = intern ("when-mapped");
4986 break;
4988 case NotUseful:
4989 result = intern ("not-useful");
4990 break;
4992 default:
4993 error ("Strange value for BackingStore parameter of screen");
4994 result = Qnil;
4997 return result;
5000 DEFUN ("x-display-visual-class", Fx_display_visual_class,
5001 Sx_display_visual_class, 0, 1, 0,
5002 doc: /* Return the visual class of the X display DISPLAY.
5003 The value is one of the symbols `static-gray', `gray-scale',
5004 `static-color', `pseudo-color', `true-color', or `direct-color'.
5006 The optional argument DISPLAY specifies which display to ask about.
5007 DISPLAY should be either a frame or a display name (a string).
5008 If omitted or nil, that stands for the selected frame's display. */)
5009 (display)
5010 Lisp_Object display;
5012 struct x_display_info *dpyinfo = check_x_display_info (display);
5013 Lisp_Object result;
5015 switch (dpyinfo->visual->class)
5017 case StaticGray:
5018 result = intern ("static-gray");
5019 break;
5020 case GrayScale:
5021 result = intern ("gray-scale");
5022 break;
5023 case StaticColor:
5024 result = intern ("static-color");
5025 break;
5026 case PseudoColor:
5027 result = intern ("pseudo-color");
5028 break;
5029 case TrueColor:
5030 result = intern ("true-color");
5031 break;
5032 case DirectColor:
5033 result = intern ("direct-color");
5034 break;
5035 default:
5036 error ("Display has an unknown visual class");
5037 result = Qnil;
5040 return result;
5043 DEFUN ("x-display-save-under", Fx_display_save_under,
5044 Sx_display_save_under, 0, 1, 0,
5045 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
5046 The optional argument DISPLAY specifies which display to ask about.
5047 DISPLAY should be either a frame or a display name (a string).
5048 If omitted or nil, that stands for the selected frame's display. */)
5049 (display)
5050 Lisp_Object display;
5052 struct x_display_info *dpyinfo = check_x_display_info (display);
5054 if (DoesSaveUnders (dpyinfo->screen) == True)
5055 return Qt;
5056 else
5057 return Qnil;
5061 x_pixel_width (f)
5062 register struct frame *f;
5064 return PIXEL_WIDTH (f);
5068 x_pixel_height (f)
5069 register struct frame *f;
5071 return PIXEL_HEIGHT (f);
5075 x_char_width (f)
5076 register struct frame *f;
5078 return FONT_WIDTH (f->output_data.x->font);
5082 x_char_height (f)
5083 register struct frame *f;
5085 return f->output_data.x->line_height;
5089 x_screen_planes (f)
5090 register struct frame *f;
5092 return FRAME_X_DISPLAY_INFO (f)->n_planes;
5097 /************************************************************************
5098 X Displays
5099 ************************************************************************/
5102 /* Mapping visual names to visuals. */
5104 static struct visual_class
5106 char *name;
5107 int class;
5109 visual_classes[] =
5111 {"StaticGray", StaticGray},
5112 {"GrayScale", GrayScale},
5113 {"StaticColor", StaticColor},
5114 {"PseudoColor", PseudoColor},
5115 {"TrueColor", TrueColor},
5116 {"DirectColor", DirectColor},
5117 {NULL, 0}
5121 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5123 /* Value is the screen number of screen SCR. This is a substitute for
5124 the X function with the same name when that doesn't exist. */
5127 XScreenNumberOfScreen (scr)
5128 register Screen *scr;
5130 Display *dpy = scr->display;
5131 int i;
5133 for (i = 0; i < dpy->nscreens; ++i)
5134 if (scr == dpy->screens + i)
5135 break;
5137 return i;
5140 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5143 /* Select the visual that should be used on display DPYINFO. Set
5144 members of DPYINFO appropriately. Called from x_term_init. */
5146 void
5147 select_visual (dpyinfo)
5148 struct x_display_info *dpyinfo;
5150 Display *dpy = dpyinfo->display;
5151 Screen *screen = dpyinfo->screen;
5152 Lisp_Object value;
5154 /* See if a visual is specified. */
5155 value = display_x_get_resource (dpyinfo,
5156 build_string ("visualClass"),
5157 build_string ("VisualClass"),
5158 Qnil, Qnil);
5159 if (STRINGP (value))
5161 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5162 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5163 depth, a decimal number. NAME is compared with case ignored. */
5164 char *s = (char *) alloca (SBYTES (value) + 1);
5165 char *dash;
5166 int i, class = -1;
5167 XVisualInfo vinfo;
5169 strcpy (s, SDATA (value));
5170 dash = index (s, '-');
5171 if (dash)
5173 dpyinfo->n_planes = atoi (dash + 1);
5174 *dash = '\0';
5176 else
5177 /* We won't find a matching visual with depth 0, so that
5178 an error will be printed below. */
5179 dpyinfo->n_planes = 0;
5181 /* Determine the visual class. */
5182 for (i = 0; visual_classes[i].name; ++i)
5183 if (xstricmp (s, visual_classes[i].name) == 0)
5185 class = visual_classes[i].class;
5186 break;
5189 /* Look up a matching visual for the specified class. */
5190 if (class == -1
5191 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5192 dpyinfo->n_planes, class, &vinfo))
5193 fatal ("Invalid visual specification `%s'", SDATA (value));
5195 dpyinfo->visual = vinfo.visual;
5197 else
5199 int n_visuals;
5200 XVisualInfo *vinfo, vinfo_template;
5202 dpyinfo->visual = DefaultVisualOfScreen (screen);
5204 #ifdef HAVE_X11R4
5205 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5206 #else
5207 vinfo_template.visualid = dpyinfo->visual->visualid;
5208 #endif
5209 vinfo_template.screen = XScreenNumberOfScreen (screen);
5210 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5211 &vinfo_template, &n_visuals);
5212 if (n_visuals != 1)
5213 fatal ("Can't get proper X visual info");
5215 dpyinfo->n_planes = vinfo->depth;
5216 XFree ((char *) vinfo);
5221 /* Return the X display structure for the display named NAME.
5222 Open a new connection if necessary. */
5224 struct x_display_info *
5225 x_display_info_for_name (name)
5226 Lisp_Object name;
5228 Lisp_Object names;
5229 struct x_display_info *dpyinfo;
5231 CHECK_STRING (name);
5233 if (! EQ (Vwindow_system, intern ("x")))
5234 error ("Not using X Windows");
5236 for (dpyinfo = x_display_list, names = x_display_name_list;
5237 dpyinfo;
5238 dpyinfo = dpyinfo->next, names = XCDR (names))
5240 Lisp_Object tem;
5241 tem = Fstring_equal (XCAR (XCAR (names)), name);
5242 if (!NILP (tem))
5243 return dpyinfo;
5246 /* Use this general default value to start with. */
5247 Vx_resource_name = Vinvocation_name;
5249 validate_x_resource_name ();
5251 dpyinfo = x_term_init (name, (char *)0,
5252 (char *) SDATA (Vx_resource_name));
5254 if (dpyinfo == 0)
5255 error ("Cannot connect to X server %s", SDATA (name));
5257 x_in_use = 1;
5258 XSETFASTINT (Vwindow_system_version, 11);
5260 return dpyinfo;
5264 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5265 1, 3, 0,
5266 doc: /* Open a connection to an X server.
5267 DISPLAY is the name of the display to connect to.
5268 Optional second arg XRM-STRING is a string of resources in xrdb format.
5269 If the optional third arg MUST-SUCCEED is non-nil,
5270 terminate Emacs if we can't open the connection. */)
5271 (display, xrm_string, must_succeed)
5272 Lisp_Object display, xrm_string, must_succeed;
5274 unsigned char *xrm_option;
5275 struct x_display_info *dpyinfo;
5277 CHECK_STRING (display);
5278 if (! NILP (xrm_string))
5279 CHECK_STRING (xrm_string);
5281 if (! EQ (Vwindow_system, intern ("x")))
5282 error ("Not using X Windows");
5284 if (! NILP (xrm_string))
5285 xrm_option = (unsigned char *) SDATA (xrm_string);
5286 else
5287 xrm_option = (unsigned char *) 0;
5289 validate_x_resource_name ();
5291 /* This is what opens the connection and sets x_current_display.
5292 This also initializes many symbols, such as those used for input. */
5293 dpyinfo = x_term_init (display, xrm_option,
5294 (char *) SDATA (Vx_resource_name));
5296 if (dpyinfo == 0)
5298 if (!NILP (must_succeed))
5299 fatal ("Cannot connect to X server %s.\n\
5300 Check the DISPLAY environment variable or use `-d'.\n\
5301 Also use the `xauth' program to verify that you have the proper\n\
5302 authorization information needed to connect the X server.\n\
5303 An insecure way to solve the problem may be to use `xhost'.\n",
5304 SDATA (display));
5305 else
5306 error ("Cannot connect to X server %s", SDATA (display));
5309 x_in_use = 1;
5311 XSETFASTINT (Vwindow_system_version, 11);
5312 return Qnil;
5315 DEFUN ("x-close-connection", Fx_close_connection,
5316 Sx_close_connection, 1, 1, 0,
5317 doc: /* Close the connection to DISPLAY's X server.
5318 For DISPLAY, specify either a frame or a display name (a string).
5319 If DISPLAY is nil, that stands for the selected frame's display. */)
5320 (display)
5321 Lisp_Object display;
5323 struct x_display_info *dpyinfo = check_x_display_info (display);
5324 int i;
5326 if (dpyinfo->reference_count > 0)
5327 error ("Display still has frames on it");
5329 BLOCK_INPUT;
5330 /* Free the fonts in the font table. */
5331 for (i = 0; i < dpyinfo->n_fonts; i++)
5332 if (dpyinfo->font_table[i].name)
5334 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
5335 xfree (dpyinfo->font_table[i].full_name);
5336 xfree (dpyinfo->font_table[i].name);
5337 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
5340 x_destroy_all_bitmaps (dpyinfo);
5341 XSetCloseDownMode (dpyinfo->display, DestroyAll);
5343 #ifdef USE_X_TOOLKIT
5344 XtCloseDisplay (dpyinfo->display);
5345 #else
5346 XCloseDisplay (dpyinfo->display);
5347 #endif
5349 x_delete_display (dpyinfo);
5350 UNBLOCK_INPUT;
5352 return Qnil;
5355 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5356 doc: /* Return the list of display names that Emacs has connections to. */)
5359 Lisp_Object tail, result;
5361 result = Qnil;
5362 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5363 result = Fcons (XCAR (XCAR (tail)), result);
5365 return result;
5368 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5369 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5370 If ON is nil, allow buffering of requests.
5371 Turning on synchronization prohibits the Xlib routines from buffering
5372 requests and seriously degrades performance, but makes debugging much
5373 easier.
5374 The optional second argument DISPLAY specifies which display to act on.
5375 DISPLAY should be either a frame or a display name (a string).
5376 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
5377 (on, display)
5378 Lisp_Object display, on;
5380 struct x_display_info *dpyinfo = check_x_display_info (display);
5382 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5384 return Qnil;
5387 /* Wait for responses to all X commands issued so far for frame F. */
5389 void
5390 x_sync (f)
5391 FRAME_PTR f;
5393 BLOCK_INPUT;
5394 XSync (FRAME_X_DISPLAY (f), False);
5395 UNBLOCK_INPUT;
5399 /***********************************************************************
5400 Image types
5401 ***********************************************************************/
5403 /* Value is the number of elements of vector VECTOR. */
5405 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5407 /* List of supported image types. Use define_image_type to add new
5408 types. Use lookup_image_type to find a type for a given symbol. */
5410 static struct image_type *image_types;
5412 /* The symbol `image' which is the car of the lists used to represent
5413 images in Lisp. */
5415 extern Lisp_Object Qimage;
5417 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5419 Lisp_Object Qxbm;
5421 /* Keywords. */
5423 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5424 extern Lisp_Object QCdata, QCtype;
5425 Lisp_Object QCascent, QCmargin, QCrelief;
5426 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
5427 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5429 /* Other symbols. */
5431 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5433 /* Time in seconds after which images should be removed from the cache
5434 if not displayed. */
5436 Lisp_Object Vimage_cache_eviction_delay;
5438 /* Function prototypes. */
5440 static void define_image_type P_ ((struct image_type *type));
5441 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5442 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5443 static void x_laplace P_ ((struct frame *, struct image *));
5444 static void x_emboss P_ ((struct frame *, struct image *));
5445 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5446 Lisp_Object));
5449 /* Define a new image type from TYPE. This adds a copy of TYPE to
5450 image_types and adds the symbol *TYPE->type to Vimage_types. */
5452 static void
5453 define_image_type (type)
5454 struct image_type *type;
5456 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5457 The initialized data segment is read-only. */
5458 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5459 bcopy (type, p, sizeof *p);
5460 p->next = image_types;
5461 image_types = p;
5462 Vimage_types = Fcons (*p->type, Vimage_types);
5466 /* Look up image type SYMBOL, and return a pointer to its image_type
5467 structure. Value is null if SYMBOL is not a known image type. */
5469 static INLINE struct image_type *
5470 lookup_image_type (symbol)
5471 Lisp_Object symbol;
5473 struct image_type *type;
5475 for (type = image_types; type; type = type->next)
5476 if (EQ (symbol, *type->type))
5477 break;
5479 return type;
5483 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5484 valid image specification is a list whose car is the symbol
5485 `image', and whose rest is a property list. The property list must
5486 contain a value for key `:type'. That value must be the name of a
5487 supported image type. The rest of the property list depends on the
5488 image type. */
5491 valid_image_p (object)
5492 Lisp_Object object;
5494 int valid_p = 0;
5496 if (CONSP (object) && EQ (XCAR (object), Qimage))
5498 Lisp_Object tem;
5500 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
5501 if (EQ (XCAR (tem), QCtype))
5503 tem = XCDR (tem);
5504 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
5506 struct image_type *type;
5507 type = lookup_image_type (XCAR (tem));
5508 if (type)
5509 valid_p = type->valid_p (object);
5512 break;
5516 return valid_p;
5520 /* Log error message with format string FORMAT and argument ARG.
5521 Signaling an error, e.g. when an image cannot be loaded, is not a
5522 good idea because this would interrupt redisplay, and the error
5523 message display would lead to another redisplay. This function
5524 therefore simply displays a message. */
5526 static void
5527 image_error (format, arg1, arg2)
5528 char *format;
5529 Lisp_Object arg1, arg2;
5531 add_to_log (format, arg1, arg2);
5536 /***********************************************************************
5537 Image specifications
5538 ***********************************************************************/
5540 enum image_value_type
5542 IMAGE_DONT_CHECK_VALUE_TYPE,
5543 IMAGE_STRING_VALUE,
5544 IMAGE_STRING_OR_NIL_VALUE,
5545 IMAGE_SYMBOL_VALUE,
5546 IMAGE_POSITIVE_INTEGER_VALUE,
5547 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
5548 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5549 IMAGE_ASCENT_VALUE,
5550 IMAGE_INTEGER_VALUE,
5551 IMAGE_FUNCTION_VALUE,
5552 IMAGE_NUMBER_VALUE,
5553 IMAGE_BOOL_VALUE
5556 /* Structure used when parsing image specifications. */
5558 struct image_keyword
5560 /* Name of keyword. */
5561 char *name;
5563 /* The type of value allowed. */
5564 enum image_value_type type;
5566 /* Non-zero means key must be present. */
5567 int mandatory_p;
5569 /* Used to recognize duplicate keywords in a property list. */
5570 int count;
5572 /* The value that was found. */
5573 Lisp_Object value;
5577 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5578 int, Lisp_Object));
5579 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5582 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5583 has the format (image KEYWORD VALUE ...). One of the keyword/
5584 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5585 image_keywords structures of size NKEYWORDS describing other
5586 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5588 static int
5589 parse_image_spec (spec, keywords, nkeywords, type)
5590 Lisp_Object spec;
5591 struct image_keyword *keywords;
5592 int nkeywords;
5593 Lisp_Object type;
5595 int i;
5596 Lisp_Object plist;
5598 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5599 return 0;
5601 plist = XCDR (spec);
5602 while (CONSP (plist))
5604 Lisp_Object key, value;
5606 /* First element of a pair must be a symbol. */
5607 key = XCAR (plist);
5608 plist = XCDR (plist);
5609 if (!SYMBOLP (key))
5610 return 0;
5612 /* There must follow a value. */
5613 if (!CONSP (plist))
5614 return 0;
5615 value = XCAR (plist);
5616 plist = XCDR (plist);
5618 /* Find key in KEYWORDS. Error if not found. */
5619 for (i = 0; i < nkeywords; ++i)
5620 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
5621 break;
5623 if (i == nkeywords)
5624 continue;
5626 /* Record that we recognized the keyword. If a keywords
5627 was found more than once, it's an error. */
5628 keywords[i].value = value;
5629 ++keywords[i].count;
5631 if (keywords[i].count > 1)
5632 return 0;
5634 /* Check type of value against allowed type. */
5635 switch (keywords[i].type)
5637 case IMAGE_STRING_VALUE:
5638 if (!STRINGP (value))
5639 return 0;
5640 break;
5642 case IMAGE_STRING_OR_NIL_VALUE:
5643 if (!STRINGP (value) && !NILP (value))
5644 return 0;
5645 break;
5647 case IMAGE_SYMBOL_VALUE:
5648 if (!SYMBOLP (value))
5649 return 0;
5650 break;
5652 case IMAGE_POSITIVE_INTEGER_VALUE:
5653 if (!INTEGERP (value) || XINT (value) <= 0)
5654 return 0;
5655 break;
5657 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
5658 if (INTEGERP (value) && XINT (value) >= 0)
5659 break;
5660 if (CONSP (value)
5661 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
5662 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
5663 break;
5664 return 0;
5666 case IMAGE_ASCENT_VALUE:
5667 if (SYMBOLP (value) && EQ (value, Qcenter))
5668 break;
5669 else if (INTEGERP (value)
5670 && XINT (value) >= 0
5671 && XINT (value) <= 100)
5672 break;
5673 return 0;
5675 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5676 if (!INTEGERP (value) || XINT (value) < 0)
5677 return 0;
5678 break;
5680 case IMAGE_DONT_CHECK_VALUE_TYPE:
5681 break;
5683 case IMAGE_FUNCTION_VALUE:
5684 value = indirect_function (value);
5685 if (SUBRP (value)
5686 || COMPILEDP (value)
5687 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5688 break;
5689 return 0;
5691 case IMAGE_NUMBER_VALUE:
5692 if (!INTEGERP (value) && !FLOATP (value))
5693 return 0;
5694 break;
5696 case IMAGE_INTEGER_VALUE:
5697 if (!INTEGERP (value))
5698 return 0;
5699 break;
5701 case IMAGE_BOOL_VALUE:
5702 if (!NILP (value) && !EQ (value, Qt))
5703 return 0;
5704 break;
5706 default:
5707 abort ();
5708 break;
5711 if (EQ (key, QCtype) && !EQ (type, value))
5712 return 0;
5715 /* Check that all mandatory fields are present. */
5716 for (i = 0; i < nkeywords; ++i)
5717 if (keywords[i].mandatory_p && keywords[i].count == 0)
5718 return 0;
5720 return NILP (plist);
5724 /* Return the value of KEY in image specification SPEC. Value is nil
5725 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5726 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5728 static Lisp_Object
5729 image_spec_value (spec, key, found)
5730 Lisp_Object spec, key;
5731 int *found;
5733 Lisp_Object tail;
5735 xassert (valid_image_p (spec));
5737 for (tail = XCDR (spec);
5738 CONSP (tail) && CONSP (XCDR (tail));
5739 tail = XCDR (XCDR (tail)))
5741 if (EQ (XCAR (tail), key))
5743 if (found)
5744 *found = 1;
5745 return XCAR (XCDR (tail));
5749 if (found)
5750 *found = 0;
5751 return Qnil;
5755 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5756 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
5757 PIXELS non-nil means return the size in pixels, otherwise return the
5758 size in canonical character units.
5759 FRAME is the frame on which the image will be displayed. FRAME nil
5760 or omitted means use the selected frame. */)
5761 (spec, pixels, frame)
5762 Lisp_Object spec, pixels, frame;
5764 Lisp_Object size;
5766 size = Qnil;
5767 if (valid_image_p (spec))
5769 struct frame *f = check_x_frame (frame);
5770 int id = lookup_image (f, spec);
5771 struct image *img = IMAGE_FROM_ID (f, id);
5772 int width = img->width + 2 * img->hmargin;
5773 int height = img->height + 2 * img->vmargin;
5775 if (NILP (pixels))
5776 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5777 make_float ((double) height / CANON_Y_UNIT (f)));
5778 else
5779 size = Fcons (make_number (width), make_number (height));
5781 else
5782 error ("Invalid image specification");
5784 return size;
5788 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5789 doc: /* Return t if image SPEC has a mask bitmap.
5790 FRAME is the frame on which the image will be displayed. FRAME nil
5791 or omitted means use the selected frame. */)
5792 (spec, frame)
5793 Lisp_Object spec, frame;
5795 Lisp_Object mask;
5797 mask = Qnil;
5798 if (valid_image_p (spec))
5800 struct frame *f = check_x_frame (frame);
5801 int id = lookup_image (f, spec);
5802 struct image *img = IMAGE_FROM_ID (f, id);
5803 if (img->mask)
5804 mask = Qt;
5806 else
5807 error ("Invalid image specification");
5809 return mask;
5814 /***********************************************************************
5815 Image type independent image structures
5816 ***********************************************************************/
5818 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5819 static void free_image P_ ((struct frame *f, struct image *img));
5822 /* Allocate and return a new image structure for image specification
5823 SPEC. SPEC has a hash value of HASH. */
5825 static struct image *
5826 make_image (spec, hash)
5827 Lisp_Object spec;
5828 unsigned hash;
5830 struct image *img = (struct image *) xmalloc (sizeof *img);
5832 xassert (valid_image_p (spec));
5833 bzero (img, sizeof *img);
5834 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5835 xassert (img->type != NULL);
5836 img->spec = spec;
5837 img->data.lisp_val = Qnil;
5838 img->ascent = DEFAULT_IMAGE_ASCENT;
5839 img->hash = hash;
5840 return img;
5844 /* Free image IMG which was used on frame F, including its resources. */
5846 static void
5847 free_image (f, img)
5848 struct frame *f;
5849 struct image *img;
5851 if (img)
5853 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5855 /* Remove IMG from the hash table of its cache. */
5856 if (img->prev)
5857 img->prev->next = img->next;
5858 else
5859 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5861 if (img->next)
5862 img->next->prev = img->prev;
5864 c->images[img->id] = NULL;
5866 /* Free resources, then free IMG. */
5867 img->type->free (f, img);
5868 xfree (img);
5873 /* Prepare image IMG for display on frame F. Must be called before
5874 drawing an image. */
5876 void
5877 prepare_image_for_display (f, img)
5878 struct frame *f;
5879 struct image *img;
5881 EMACS_TIME t;
5883 /* We're about to display IMG, so set its timestamp to `now'. */
5884 EMACS_GET_TIME (t);
5885 img->timestamp = EMACS_SECS (t);
5887 /* If IMG doesn't have a pixmap yet, load it now, using the image
5888 type dependent loader function. */
5889 if (img->pixmap == None && !img->load_failed_p)
5890 img->load_failed_p = img->type->load (f, img) == 0;
5894 /* Value is the number of pixels for the ascent of image IMG when
5895 drawn in face FACE. */
5898 image_ascent (img, face)
5899 struct image *img;
5900 struct face *face;
5902 int height = img->height + img->vmargin;
5903 int ascent;
5905 if (img->ascent == CENTERED_IMAGE_ASCENT)
5907 if (face->font)
5908 /* This expression is arranged so that if the image can't be
5909 exactly centered, it will be moved slightly up. This is
5910 because a typical font is `top-heavy' (due to the presence
5911 uppercase letters), so the image placement should err towards
5912 being top-heavy too. It also just generally looks better. */
5913 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5914 else
5915 ascent = height / 2;
5917 else
5918 ascent = height * img->ascent / 100.0;
5920 return ascent;
5924 /* Image background colors. */
5926 static unsigned long
5927 four_corners_best (ximg, width, height)
5928 XImage *ximg;
5929 unsigned long width, height;
5931 unsigned long corners[4], best;
5932 int i, best_count;
5934 /* Get the colors at the corners of ximg. */
5935 corners[0] = XGetPixel (ximg, 0, 0);
5936 corners[1] = XGetPixel (ximg, width - 1, 0);
5937 corners[2] = XGetPixel (ximg, width - 1, height - 1);
5938 corners[3] = XGetPixel (ximg, 0, height - 1);
5940 /* Choose the most frequently found color as background. */
5941 for (i = best_count = 0; i < 4; ++i)
5943 int j, n;
5945 for (j = n = 0; j < 4; ++j)
5946 if (corners[i] == corners[j])
5947 ++n;
5949 if (n > best_count)
5950 best = corners[i], best_count = n;
5953 return best;
5956 /* Return the `background' field of IMG. If IMG doesn't have one yet,
5957 it is guessed heuristically. If non-zero, XIMG is an existing XImage
5958 object to use for the heuristic. */
5960 unsigned long
5961 image_background (img, f, ximg)
5962 struct image *img;
5963 struct frame *f;
5964 XImage *ximg;
5966 if (! img->background_valid)
5967 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5969 int free_ximg = !ximg;
5971 if (! ximg)
5972 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5973 0, 0, img->width, img->height, ~0, ZPixmap);
5975 img->background = four_corners_best (ximg, img->width, img->height);
5977 if (free_ximg)
5978 XDestroyImage (ximg);
5980 img->background_valid = 1;
5983 return img->background;
5986 /* Return the `background_transparent' field of IMG. If IMG doesn't
5987 have one yet, it is guessed heuristically. If non-zero, MASK is an
5988 existing XImage object to use for the heuristic. */
5991 image_background_transparent (img, f, mask)
5992 struct image *img;
5993 struct frame *f;
5994 XImage *mask;
5996 if (! img->background_transparent_valid)
5997 /* IMG doesn't have a background yet, try to guess a reasonable value. */
5999 if (img->mask)
6001 int free_mask = !mask;
6003 if (! mask)
6004 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
6005 0, 0, img->width, img->height, ~0, ZPixmap);
6007 img->background_transparent
6008 = !four_corners_best (mask, img->width, img->height);
6010 if (free_mask)
6011 XDestroyImage (mask);
6013 else
6014 img->background_transparent = 0;
6016 img->background_transparent_valid = 1;
6019 return img->background_transparent;
6023 /***********************************************************************
6024 Helper functions for X image types
6025 ***********************************************************************/
6027 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
6028 int, int));
6029 static void x_clear_image P_ ((struct frame *f, struct image *img));
6030 static unsigned long x_alloc_image_color P_ ((struct frame *f,
6031 struct image *img,
6032 Lisp_Object color_name,
6033 unsigned long dflt));
6036 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
6037 free the pixmap if any. MASK_P non-zero means clear the mask
6038 pixmap if any. COLORS_P non-zero means free colors allocated for
6039 the image, if any. */
6041 static void
6042 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
6043 struct frame *f;
6044 struct image *img;
6045 int pixmap_p, mask_p, colors_p;
6047 if (pixmap_p && img->pixmap)
6049 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
6050 img->pixmap = None;
6051 img->background_valid = 0;
6054 if (mask_p && img->mask)
6056 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6057 img->mask = None;
6058 img->background_transparent_valid = 0;
6061 if (colors_p && img->ncolors)
6063 x_free_colors (f, img->colors, img->ncolors);
6064 xfree (img->colors);
6065 img->colors = NULL;
6066 img->ncolors = 0;
6070 /* Free X resources of image IMG which is used on frame F. */
6072 static void
6073 x_clear_image (f, img)
6074 struct frame *f;
6075 struct image *img;
6077 BLOCK_INPUT;
6078 x_clear_image_1 (f, img, 1, 1, 1);
6079 UNBLOCK_INPUT;
6083 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6084 cannot be allocated, use DFLT. Add a newly allocated color to
6085 IMG->colors, so that it can be freed again. Value is the pixel
6086 color. */
6088 static unsigned long
6089 x_alloc_image_color (f, img, color_name, dflt)
6090 struct frame *f;
6091 struct image *img;
6092 Lisp_Object color_name;
6093 unsigned long dflt;
6095 XColor color;
6096 unsigned long result;
6098 xassert (STRINGP (color_name));
6100 if (x_defined_color (f, SDATA (color_name), &color, 1))
6102 /* This isn't called frequently so we get away with simply
6103 reallocating the color vector to the needed size, here. */
6104 ++img->ncolors;
6105 img->colors =
6106 (unsigned long *) xrealloc (img->colors,
6107 img->ncolors * sizeof *img->colors);
6108 img->colors[img->ncolors - 1] = color.pixel;
6109 result = color.pixel;
6111 else
6112 result = dflt;
6114 return result;
6119 /***********************************************************************
6120 Image Cache
6121 ***********************************************************************/
6123 static void cache_image P_ ((struct frame *f, struct image *img));
6124 static void postprocess_image P_ ((struct frame *, struct image *));
6127 /* Return a new, initialized image cache that is allocated from the
6128 heap. Call free_image_cache to free an image cache. */
6130 struct image_cache *
6131 make_image_cache ()
6133 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
6134 int size;
6136 bzero (c, sizeof *c);
6137 c->size = 50;
6138 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
6139 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
6140 c->buckets = (struct image **) xmalloc (size);
6141 bzero (c->buckets, size);
6142 return c;
6146 /* Free image cache of frame F. Be aware that X frames share images
6147 caches. */
6149 void
6150 free_image_cache (f)
6151 struct frame *f;
6153 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6154 if (c)
6156 int i;
6158 /* Cache should not be referenced by any frame when freed. */
6159 xassert (c->refcount == 0);
6161 for (i = 0; i < c->used; ++i)
6162 free_image (f, c->images[i]);
6163 xfree (c->images);
6164 xfree (c->buckets);
6165 xfree (c);
6166 FRAME_X_IMAGE_CACHE (f) = NULL;
6171 /* Clear image cache of frame F. FORCE_P non-zero means free all
6172 images. FORCE_P zero means clear only images that haven't been
6173 displayed for some time. Should be called from time to time to
6174 reduce the number of loaded images. If image-eviction-seconds is
6175 non-nil, this frees images in the cache which weren't displayed for
6176 at least that many seconds. */
6178 void
6179 clear_image_cache (f, force_p)
6180 struct frame *f;
6181 int force_p;
6183 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6185 if (c && INTEGERP (Vimage_cache_eviction_delay))
6187 EMACS_TIME t;
6188 unsigned long old;
6189 int i, nfreed;
6191 EMACS_GET_TIME (t);
6192 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
6194 /* Block input so that we won't be interrupted by a SIGIO
6195 while being in an inconsistent state. */
6196 BLOCK_INPUT;
6198 for (i = nfreed = 0; i < c->used; ++i)
6200 struct image *img = c->images[i];
6201 if (img != NULL
6202 && (force_p || img->timestamp < old))
6204 free_image (f, img);
6205 ++nfreed;
6209 /* We may be clearing the image cache because, for example,
6210 Emacs was iconified for a longer period of time. In that
6211 case, current matrices may still contain references to
6212 images freed above. So, clear these matrices. */
6213 if (nfreed)
6215 Lisp_Object tail, frame;
6217 FOR_EACH_FRAME (tail, frame)
6219 struct frame *f = XFRAME (frame);
6220 if (FRAME_X_P (f)
6221 && FRAME_X_IMAGE_CACHE (f) == c)
6222 clear_current_matrices (f);
6225 ++windows_or_buffers_changed;
6228 UNBLOCK_INPUT;
6233 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
6234 0, 1, 0,
6235 doc: /* Clear the image cache of FRAME.
6236 FRAME nil or omitted means use the selected frame.
6237 FRAME t means clear the image caches of all frames. */)
6238 (frame)
6239 Lisp_Object frame;
6241 if (EQ (frame, Qt))
6243 Lisp_Object tail;
6245 FOR_EACH_FRAME (tail, frame)
6246 if (FRAME_X_P (XFRAME (frame)))
6247 clear_image_cache (XFRAME (frame), 1);
6249 else
6250 clear_image_cache (check_x_frame (frame), 1);
6252 return Qnil;
6256 /* Compute masks and transform image IMG on frame F, as specified
6257 by the image's specification, */
6259 static void
6260 postprocess_image (f, img)
6261 struct frame *f;
6262 struct image *img;
6264 /* Manipulation of the image's mask. */
6265 if (img->pixmap)
6267 Lisp_Object conversion, spec;
6268 Lisp_Object mask;
6270 spec = img->spec;
6272 /* `:heuristic-mask t'
6273 `:mask heuristic'
6274 means build a mask heuristically.
6275 `:heuristic-mask (R G B)'
6276 `:mask (heuristic (R G B))'
6277 means build a mask from color (R G B) in the
6278 image.
6279 `:mask nil'
6280 means remove a mask, if any. */
6282 mask = image_spec_value (spec, QCheuristic_mask, NULL);
6283 if (!NILP (mask))
6284 x_build_heuristic_mask (f, img, mask);
6285 else
6287 int found_p;
6289 mask = image_spec_value (spec, QCmask, &found_p);
6291 if (EQ (mask, Qheuristic))
6292 x_build_heuristic_mask (f, img, Qt);
6293 else if (CONSP (mask)
6294 && EQ (XCAR (mask), Qheuristic))
6296 if (CONSP (XCDR (mask)))
6297 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
6298 else
6299 x_build_heuristic_mask (f, img, XCDR (mask));
6301 else if (NILP (mask) && found_p && img->mask)
6303 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6304 img->mask = None;
6309 /* Should we apply an image transformation algorithm? */
6310 conversion = image_spec_value (spec, QCconversion, NULL);
6311 if (EQ (conversion, Qdisabled))
6312 x_disable_image (f, img);
6313 else if (EQ (conversion, Qlaplace))
6314 x_laplace (f, img);
6315 else if (EQ (conversion, Qemboss))
6316 x_emboss (f, img);
6317 else if (CONSP (conversion)
6318 && EQ (XCAR (conversion), Qedge_detection))
6320 Lisp_Object tem;
6321 tem = XCDR (conversion);
6322 if (CONSP (tem))
6323 x_edge_detection (f, img,
6324 Fplist_get (tem, QCmatrix),
6325 Fplist_get (tem, QCcolor_adjustment));
6331 /* Return the id of image with Lisp specification SPEC on frame F.
6332 SPEC must be a valid Lisp image specification (see valid_image_p). */
6335 lookup_image (f, spec)
6336 struct frame *f;
6337 Lisp_Object spec;
6339 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6340 struct image *img;
6341 int i;
6342 unsigned hash;
6343 struct gcpro gcpro1;
6344 EMACS_TIME now;
6346 /* F must be a window-system frame, and SPEC must be a valid image
6347 specification. */
6348 xassert (FRAME_WINDOW_P (f));
6349 xassert (valid_image_p (spec));
6351 GCPRO1 (spec);
6353 /* Look up SPEC in the hash table of the image cache. */
6354 hash = sxhash (spec, 0);
6355 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
6357 for (img = c->buckets[i]; img; img = img->next)
6358 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
6359 break;
6361 /* If not found, create a new image and cache it. */
6362 if (img == NULL)
6364 extern Lisp_Object Qpostscript;
6366 BLOCK_INPUT;
6367 img = make_image (spec, hash);
6368 cache_image (f, img);
6369 img->load_failed_p = img->type->load (f, img) == 0;
6371 /* If we can't load the image, and we don't have a width and
6372 height, use some arbitrary width and height so that we can
6373 draw a rectangle for it. */
6374 if (img->load_failed_p)
6376 Lisp_Object value;
6378 value = image_spec_value (spec, QCwidth, NULL);
6379 img->width = (INTEGERP (value)
6380 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
6381 value = image_spec_value (spec, QCheight, NULL);
6382 img->height = (INTEGERP (value)
6383 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
6385 else
6387 /* Handle image type independent image attributes
6388 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
6389 `:background COLOR'. */
6390 Lisp_Object ascent, margin, relief, bg;
6392 ascent = image_spec_value (spec, QCascent, NULL);
6393 if (INTEGERP (ascent))
6394 img->ascent = XFASTINT (ascent);
6395 else if (EQ (ascent, Qcenter))
6396 img->ascent = CENTERED_IMAGE_ASCENT;
6398 margin = image_spec_value (spec, QCmargin, NULL);
6399 if (INTEGERP (margin) && XINT (margin) >= 0)
6400 img->vmargin = img->hmargin = XFASTINT (margin);
6401 else if (CONSP (margin) && INTEGERP (XCAR (margin))
6402 && INTEGERP (XCDR (margin)))
6404 if (XINT (XCAR (margin)) > 0)
6405 img->hmargin = XFASTINT (XCAR (margin));
6406 if (XINT (XCDR (margin)) > 0)
6407 img->vmargin = XFASTINT (XCDR (margin));
6410 relief = image_spec_value (spec, QCrelief, NULL);
6411 if (INTEGERP (relief))
6413 img->relief = XINT (relief);
6414 img->hmargin += abs (img->relief);
6415 img->vmargin += abs (img->relief);
6418 if (! img->background_valid)
6420 bg = image_spec_value (img->spec, QCbackground, NULL);
6421 if (!NILP (bg))
6423 img->background
6424 = x_alloc_image_color (f, img, bg,
6425 FRAME_BACKGROUND_PIXEL (f));
6426 img->background_valid = 1;
6430 /* Do image transformations and compute masks, unless we
6431 don't have the image yet. */
6432 if (!EQ (*img->type->type, Qpostscript))
6433 postprocess_image (f, img);
6436 UNBLOCK_INPUT;
6437 xassert (!interrupt_input_blocked);
6440 /* We're using IMG, so set its timestamp to `now'. */
6441 EMACS_GET_TIME (now);
6442 img->timestamp = EMACS_SECS (now);
6444 UNGCPRO;
6446 /* Value is the image id. */
6447 return img->id;
6451 /* Cache image IMG in the image cache of frame F. */
6453 static void
6454 cache_image (f, img)
6455 struct frame *f;
6456 struct image *img;
6458 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6459 int i;
6461 /* Find a free slot in c->images. */
6462 for (i = 0; i < c->used; ++i)
6463 if (c->images[i] == NULL)
6464 break;
6466 /* If no free slot found, maybe enlarge c->images. */
6467 if (i == c->used && c->used == c->size)
6469 c->size *= 2;
6470 c->images = (struct image **) xrealloc (c->images,
6471 c->size * sizeof *c->images);
6474 /* Add IMG to c->images, and assign IMG an id. */
6475 c->images[i] = img;
6476 img->id = i;
6477 if (i == c->used)
6478 ++c->used;
6480 /* Add IMG to the cache's hash table. */
6481 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
6482 img->next = c->buckets[i];
6483 if (img->next)
6484 img->next->prev = img;
6485 img->prev = NULL;
6486 c->buckets[i] = img;
6490 /* Call FN on every image in the image cache of frame F. Used to mark
6491 Lisp Objects in the image cache. */
6493 void
6494 forall_images_in_image_cache (f, fn)
6495 struct frame *f;
6496 void (*fn) P_ ((struct image *img));
6498 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
6500 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
6501 if (c)
6503 int i;
6504 for (i = 0; i < c->used; ++i)
6505 if (c->images[i])
6506 fn (c->images[i]);
6513 /***********************************************************************
6514 X support code
6515 ***********************************************************************/
6517 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6518 XImage **, Pixmap *));
6519 static void x_destroy_x_image P_ ((XImage *));
6520 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6523 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6524 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6525 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6526 via xmalloc. Print error messages via image_error if an error
6527 occurs. Value is non-zero if successful. */
6529 static int
6530 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6531 struct frame *f;
6532 int width, height, depth;
6533 XImage **ximg;
6534 Pixmap *pixmap;
6536 Display *display = FRAME_X_DISPLAY (f);
6537 Screen *screen = FRAME_X_SCREEN (f);
6538 Window window = FRAME_X_WINDOW (f);
6540 xassert (interrupt_input_blocked);
6542 if (depth <= 0)
6543 depth = DefaultDepthOfScreen (screen);
6544 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6545 depth, ZPixmap, 0, NULL, width, height,
6546 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6547 if (*ximg == NULL)
6549 image_error ("Unable to allocate X image", Qnil, Qnil);
6550 return 0;
6553 /* Allocate image raster. */
6554 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6556 /* Allocate a pixmap of the same size. */
6557 *pixmap = XCreatePixmap (display, window, width, height, depth);
6558 if (*pixmap == None)
6560 x_destroy_x_image (*ximg);
6561 *ximg = NULL;
6562 image_error ("Unable to create X pixmap", Qnil, Qnil);
6563 return 0;
6566 return 1;
6570 /* Destroy XImage XIMG. Free XIMG->data. */
6572 static void
6573 x_destroy_x_image (ximg)
6574 XImage *ximg;
6576 xassert (interrupt_input_blocked);
6577 if (ximg)
6579 xfree (ximg->data);
6580 ximg->data = NULL;
6581 XDestroyImage (ximg);
6586 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6587 are width and height of both the image and pixmap. */
6589 static void
6590 x_put_x_image (f, ximg, pixmap, width, height)
6591 struct frame *f;
6592 XImage *ximg;
6593 Pixmap pixmap;
6595 GC gc;
6597 xassert (interrupt_input_blocked);
6598 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6599 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6600 XFreeGC (FRAME_X_DISPLAY (f), gc);
6605 /***********************************************************************
6606 File Handling
6607 ***********************************************************************/
6609 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6610 static char *slurp_file P_ ((char *, int *));
6613 /* Find image file FILE. Look in data-directory, then
6614 x-bitmap-file-path. Value is the full name of the file found, or
6615 nil if not found. */
6617 static Lisp_Object
6618 x_find_image_file (file)
6619 Lisp_Object file;
6621 Lisp_Object file_found, search_path;
6622 struct gcpro gcpro1, gcpro2;
6623 int fd;
6625 file_found = Qnil;
6626 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6627 GCPRO2 (file_found, search_path);
6629 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6630 fd = openp (search_path, file, Qnil, &file_found, Qnil);
6632 if (fd == -1)
6633 file_found = Qnil;
6634 else
6635 close (fd);
6637 UNGCPRO;
6638 return file_found;
6642 /* Read FILE into memory. Value is a pointer to a buffer allocated
6643 with xmalloc holding FILE's contents. Value is null if an error
6644 occurred. *SIZE is set to the size of the file. */
6646 static char *
6647 slurp_file (file, size)
6648 char *file;
6649 int *size;
6651 FILE *fp = NULL;
6652 char *buf = NULL;
6653 struct stat st;
6655 if (stat (file, &st) == 0
6656 && (fp = fopen (file, "r")) != NULL
6657 && (buf = (char *) xmalloc (st.st_size),
6658 fread (buf, 1, st.st_size, fp) == st.st_size))
6660 *size = st.st_size;
6661 fclose (fp);
6663 else
6665 if (fp)
6666 fclose (fp);
6667 if (buf)
6669 xfree (buf);
6670 buf = NULL;
6674 return buf;
6679 /***********************************************************************
6680 XBM images
6681 ***********************************************************************/
6683 static int xbm_scan P_ ((char **, char *, char *, int *));
6684 static int xbm_load P_ ((struct frame *f, struct image *img));
6685 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6686 char *, char *));
6687 static int xbm_image_p P_ ((Lisp_Object object));
6688 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6689 unsigned char **));
6690 static int xbm_file_p P_ ((Lisp_Object));
6693 /* Indices of image specification fields in xbm_format, below. */
6695 enum xbm_keyword_index
6697 XBM_TYPE,
6698 XBM_FILE,
6699 XBM_WIDTH,
6700 XBM_HEIGHT,
6701 XBM_DATA,
6702 XBM_FOREGROUND,
6703 XBM_BACKGROUND,
6704 XBM_ASCENT,
6705 XBM_MARGIN,
6706 XBM_RELIEF,
6707 XBM_ALGORITHM,
6708 XBM_HEURISTIC_MASK,
6709 XBM_MASK,
6710 XBM_LAST
6713 /* Vector of image_keyword structures describing the format
6714 of valid XBM image specifications. */
6716 static struct image_keyword xbm_format[XBM_LAST] =
6718 {":type", IMAGE_SYMBOL_VALUE, 1},
6719 {":file", IMAGE_STRING_VALUE, 0},
6720 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6721 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6722 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6723 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6724 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6725 {":ascent", IMAGE_ASCENT_VALUE, 0},
6726 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6727 {":relief", IMAGE_INTEGER_VALUE, 0},
6728 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6729 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6730 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6733 /* Structure describing the image type XBM. */
6735 static struct image_type xbm_type =
6737 &Qxbm,
6738 xbm_image_p,
6739 xbm_load,
6740 x_clear_image,
6741 NULL
6744 /* Tokens returned from xbm_scan. */
6746 enum xbm_token
6748 XBM_TK_IDENT = 256,
6749 XBM_TK_NUMBER
6753 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6754 A valid specification is a list starting with the symbol `image'
6755 The rest of the list is a property list which must contain an
6756 entry `:type xbm..
6758 If the specification specifies a file to load, it must contain
6759 an entry `:file FILENAME' where FILENAME is a string.
6761 If the specification is for a bitmap loaded from memory it must
6762 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6763 WIDTH and HEIGHT are integers > 0. DATA may be:
6765 1. a string large enough to hold the bitmap data, i.e. it must
6766 have a size >= (WIDTH + 7) / 8 * HEIGHT
6768 2. a bool-vector of size >= WIDTH * HEIGHT
6770 3. a vector of strings or bool-vectors, one for each line of the
6771 bitmap.
6773 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6774 may not be specified in this case because they are defined in the
6775 XBM file.
6777 Both the file and data forms may contain the additional entries
6778 `:background COLOR' and `:foreground COLOR'. If not present,
6779 foreground and background of the frame on which the image is
6780 displayed is used. */
6782 static int
6783 xbm_image_p (object)
6784 Lisp_Object object;
6786 struct image_keyword kw[XBM_LAST];
6788 bcopy (xbm_format, kw, sizeof kw);
6789 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6790 return 0;
6792 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6794 if (kw[XBM_FILE].count)
6796 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6797 return 0;
6799 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6801 /* In-memory XBM file. */
6802 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6803 return 0;
6805 else
6807 Lisp_Object data;
6808 int width, height;
6810 /* Entries for `:width', `:height' and `:data' must be present. */
6811 if (!kw[XBM_WIDTH].count
6812 || !kw[XBM_HEIGHT].count
6813 || !kw[XBM_DATA].count)
6814 return 0;
6816 data = kw[XBM_DATA].value;
6817 width = XFASTINT (kw[XBM_WIDTH].value);
6818 height = XFASTINT (kw[XBM_HEIGHT].value);
6820 /* Check type of data, and width and height against contents of
6821 data. */
6822 if (VECTORP (data))
6824 int i;
6826 /* Number of elements of the vector must be >= height. */
6827 if (XVECTOR (data)->size < height)
6828 return 0;
6830 /* Each string or bool-vector in data must be large enough
6831 for one line of the image. */
6832 for (i = 0; i < height; ++i)
6834 Lisp_Object elt = XVECTOR (data)->contents[i];
6836 if (STRINGP (elt))
6838 if (SCHARS (elt)
6839 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6840 return 0;
6842 else if (BOOL_VECTOR_P (elt))
6844 if (XBOOL_VECTOR (elt)->size < width)
6845 return 0;
6847 else
6848 return 0;
6851 else if (STRINGP (data))
6853 if (SCHARS (data)
6854 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6855 return 0;
6857 else if (BOOL_VECTOR_P (data))
6859 if (XBOOL_VECTOR (data)->size < width * height)
6860 return 0;
6862 else
6863 return 0;
6866 return 1;
6870 /* Scan a bitmap file. FP is the stream to read from. Value is
6871 either an enumerator from enum xbm_token, or a character for a
6872 single-character token, or 0 at end of file. If scanning an
6873 identifier, store the lexeme of the identifier in SVAL. If
6874 scanning a number, store its value in *IVAL. */
6876 static int
6877 xbm_scan (s, end, sval, ival)
6878 char **s, *end;
6879 char *sval;
6880 int *ival;
6882 int c;
6884 loop:
6886 /* Skip white space. */
6887 while (*s < end && (c = *(*s)++, isspace (c)))
6890 if (*s >= end)
6891 c = 0;
6892 else if (isdigit (c))
6894 int value = 0, digit;
6896 if (c == '0' && *s < end)
6898 c = *(*s)++;
6899 if (c == 'x' || c == 'X')
6901 while (*s < end)
6903 c = *(*s)++;
6904 if (isdigit (c))
6905 digit = c - '0';
6906 else if (c >= 'a' && c <= 'f')
6907 digit = c - 'a' + 10;
6908 else if (c >= 'A' && c <= 'F')
6909 digit = c - 'A' + 10;
6910 else
6911 break;
6912 value = 16 * value + digit;
6915 else if (isdigit (c))
6917 value = c - '0';
6918 while (*s < end
6919 && (c = *(*s)++, isdigit (c)))
6920 value = 8 * value + c - '0';
6923 else
6925 value = c - '0';
6926 while (*s < end
6927 && (c = *(*s)++, isdigit (c)))
6928 value = 10 * value + c - '0';
6931 if (*s < end)
6932 *s = *s - 1;
6933 *ival = value;
6934 c = XBM_TK_NUMBER;
6936 else if (isalpha (c) || c == '_')
6938 *sval++ = c;
6939 while (*s < end
6940 && (c = *(*s)++, (isalnum (c) || c == '_')))
6941 *sval++ = c;
6942 *sval = 0;
6943 if (*s < end)
6944 *s = *s - 1;
6945 c = XBM_TK_IDENT;
6947 else if (c == '/' && **s == '*')
6949 /* C-style comment. */
6950 ++*s;
6951 while (**s && (**s != '*' || *(*s + 1) != '/'))
6952 ++*s;
6953 if (**s)
6955 *s += 2;
6956 goto loop;
6960 return c;
6964 /* Replacement for XReadBitmapFileData which isn't available under old
6965 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6966 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6967 the image. Return in *DATA the bitmap data allocated with xmalloc.
6968 Value is non-zero if successful. DATA null means just test if
6969 CONTENTS looks like an in-memory XBM file. */
6971 static int
6972 xbm_read_bitmap_data (contents, end, width, height, data)
6973 char *contents, *end;
6974 int *width, *height;
6975 unsigned char **data;
6977 char *s = contents;
6978 char buffer[BUFSIZ];
6979 int padding_p = 0;
6980 int v10 = 0;
6981 int bytes_per_line, i, nbytes;
6982 unsigned char *p;
6983 int value;
6984 int LA1;
6986 #define match() \
6987 LA1 = xbm_scan (&s, end, buffer, &value)
6989 #define expect(TOKEN) \
6990 if (LA1 != (TOKEN)) \
6991 goto failure; \
6992 else \
6993 match ()
6995 #define expect_ident(IDENT) \
6996 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6997 match (); \
6998 else \
6999 goto failure
7001 *width = *height = -1;
7002 if (data)
7003 *data = NULL;
7004 LA1 = xbm_scan (&s, end, buffer, &value);
7006 /* Parse defines for width, height and hot-spots. */
7007 while (LA1 == '#')
7009 match ();
7010 expect_ident ("define");
7011 expect (XBM_TK_IDENT);
7013 if (LA1 == XBM_TK_NUMBER);
7015 char *p = strrchr (buffer, '_');
7016 p = p ? p + 1 : buffer;
7017 if (strcmp (p, "width") == 0)
7018 *width = value;
7019 else if (strcmp (p, "height") == 0)
7020 *height = value;
7022 expect (XBM_TK_NUMBER);
7025 if (*width < 0 || *height < 0)
7026 goto failure;
7027 else if (data == NULL)
7028 goto success;
7030 /* Parse bits. Must start with `static'. */
7031 expect_ident ("static");
7032 if (LA1 == XBM_TK_IDENT)
7034 if (strcmp (buffer, "unsigned") == 0)
7036 match ();
7037 expect_ident ("char");
7039 else if (strcmp (buffer, "short") == 0)
7041 match ();
7042 v10 = 1;
7043 if (*width % 16 && *width % 16 < 9)
7044 padding_p = 1;
7046 else if (strcmp (buffer, "char") == 0)
7047 match ();
7048 else
7049 goto failure;
7051 else
7052 goto failure;
7054 expect (XBM_TK_IDENT);
7055 expect ('[');
7056 expect (']');
7057 expect ('=');
7058 expect ('{');
7060 bytes_per_line = (*width + 7) / 8 + padding_p;
7061 nbytes = bytes_per_line * *height;
7062 p = *data = (char *) xmalloc (nbytes);
7064 if (v10)
7066 for (i = 0; i < nbytes; i += 2)
7068 int val = value;
7069 expect (XBM_TK_NUMBER);
7071 *p++ = val;
7072 if (!padding_p || ((i + 2) % bytes_per_line))
7073 *p++ = value >> 8;
7075 if (LA1 == ',' || LA1 == '}')
7076 match ();
7077 else
7078 goto failure;
7081 else
7083 for (i = 0; i < nbytes; ++i)
7085 int val = value;
7086 expect (XBM_TK_NUMBER);
7088 *p++ = val;
7090 if (LA1 == ',' || LA1 == '}')
7091 match ();
7092 else
7093 goto failure;
7097 success:
7098 return 1;
7100 failure:
7102 if (data && *data)
7104 xfree (*data);
7105 *data = NULL;
7107 return 0;
7109 #undef match
7110 #undef expect
7111 #undef expect_ident
7115 /* Load XBM image IMG which will be displayed on frame F from buffer
7116 CONTENTS. END is the end of the buffer. Value is non-zero if
7117 successful. */
7119 static int
7120 xbm_load_image (f, img, contents, end)
7121 struct frame *f;
7122 struct image *img;
7123 char *contents, *end;
7125 int rc;
7126 unsigned char *data;
7127 int success_p = 0;
7129 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
7130 if (rc)
7132 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7133 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7134 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7135 Lisp_Object value;
7137 xassert (img->width > 0 && img->height > 0);
7139 /* Get foreground and background colors, maybe allocate colors. */
7140 value = image_spec_value (img->spec, QCforeground, NULL);
7141 if (!NILP (value))
7142 foreground = x_alloc_image_color (f, img, value, foreground);
7143 value = image_spec_value (img->spec, QCbackground, NULL);
7144 if (!NILP (value))
7146 background = x_alloc_image_color (f, img, value, background);
7147 img->background = background;
7148 img->background_valid = 1;
7151 img->pixmap
7152 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7153 FRAME_X_WINDOW (f),
7154 data,
7155 img->width, img->height,
7156 foreground, background,
7157 depth);
7158 xfree (data);
7160 if (img->pixmap == None)
7162 x_clear_image (f, img);
7163 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
7165 else
7166 success_p = 1;
7168 else
7169 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7171 return success_p;
7175 /* Value is non-zero if DATA looks like an in-memory XBM file. */
7177 static int
7178 xbm_file_p (data)
7179 Lisp_Object data;
7181 int w, h;
7182 return (STRINGP (data)
7183 && xbm_read_bitmap_data (SDATA (data),
7184 (SDATA (data)
7185 + SBYTES (data)),
7186 &w, &h, NULL));
7190 /* Fill image IMG which is used on frame F with pixmap data. Value is
7191 non-zero if successful. */
7193 static int
7194 xbm_load (f, img)
7195 struct frame *f;
7196 struct image *img;
7198 int success_p = 0;
7199 Lisp_Object file_name;
7201 xassert (xbm_image_p (img->spec));
7203 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7204 file_name = image_spec_value (img->spec, QCfile, NULL);
7205 if (STRINGP (file_name))
7207 Lisp_Object file;
7208 char *contents;
7209 int size;
7210 struct gcpro gcpro1;
7212 file = x_find_image_file (file_name);
7213 GCPRO1 (file);
7214 if (!STRINGP (file))
7216 image_error ("Cannot find image file `%s'", file_name, Qnil);
7217 UNGCPRO;
7218 return 0;
7221 contents = slurp_file (SDATA (file), &size);
7222 if (contents == NULL)
7224 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
7225 UNGCPRO;
7226 return 0;
7229 success_p = xbm_load_image (f, img, contents, contents + size);
7230 UNGCPRO;
7232 else
7234 struct image_keyword fmt[XBM_LAST];
7235 Lisp_Object data;
7236 int depth;
7237 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
7238 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
7239 char *bits;
7240 int parsed_p;
7241 int in_memory_file_p = 0;
7243 /* See if data looks like an in-memory XBM file. */
7244 data = image_spec_value (img->spec, QCdata, NULL);
7245 in_memory_file_p = xbm_file_p (data);
7247 /* Parse the image specification. */
7248 bcopy (xbm_format, fmt, sizeof fmt);
7249 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
7250 xassert (parsed_p);
7252 /* Get specified width, and height. */
7253 if (!in_memory_file_p)
7255 img->width = XFASTINT (fmt[XBM_WIDTH].value);
7256 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
7257 xassert (img->width > 0 && img->height > 0);
7260 /* Get foreground and background colors, maybe allocate colors. */
7261 if (fmt[XBM_FOREGROUND].count
7262 && STRINGP (fmt[XBM_FOREGROUND].value))
7263 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
7264 foreground);
7265 if (fmt[XBM_BACKGROUND].count
7266 && STRINGP (fmt[XBM_BACKGROUND].value))
7267 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
7268 background);
7270 if (in_memory_file_p)
7271 success_p = xbm_load_image (f, img, SDATA (data),
7272 (SDATA (data)
7273 + SBYTES (data)));
7274 else
7276 if (VECTORP (data))
7278 int i;
7279 char *p;
7280 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
7282 p = bits = (char *) alloca (nbytes * img->height);
7283 for (i = 0; i < img->height; ++i, p += nbytes)
7285 Lisp_Object line = XVECTOR (data)->contents[i];
7286 if (STRINGP (line))
7287 bcopy (SDATA (line), p, nbytes);
7288 else
7289 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
7292 else if (STRINGP (data))
7293 bits = SDATA (data);
7294 else
7295 bits = XBOOL_VECTOR (data)->data;
7297 /* Create the pixmap. */
7298 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
7299 img->pixmap
7300 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
7301 FRAME_X_WINDOW (f),
7302 bits,
7303 img->width, img->height,
7304 foreground, background,
7305 depth);
7306 if (img->pixmap)
7307 success_p = 1;
7308 else
7310 image_error ("Unable to create pixmap for XBM image `%s'",
7311 img->spec, Qnil);
7312 x_clear_image (f, img);
7317 return success_p;
7322 /***********************************************************************
7323 XPM images
7324 ***********************************************************************/
7326 #if HAVE_XPM
7328 static int xpm_image_p P_ ((Lisp_Object object));
7329 static int xpm_load P_ ((struct frame *f, struct image *img));
7330 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
7332 #include "X11/xpm.h"
7334 /* The symbol `xpm' identifying XPM-format images. */
7336 Lisp_Object Qxpm;
7338 /* Indices of image specification fields in xpm_format, below. */
7340 enum xpm_keyword_index
7342 XPM_TYPE,
7343 XPM_FILE,
7344 XPM_DATA,
7345 XPM_ASCENT,
7346 XPM_MARGIN,
7347 XPM_RELIEF,
7348 XPM_ALGORITHM,
7349 XPM_HEURISTIC_MASK,
7350 XPM_MASK,
7351 XPM_COLOR_SYMBOLS,
7352 XPM_BACKGROUND,
7353 XPM_LAST
7356 /* Vector of image_keyword structures describing the format
7357 of valid XPM image specifications. */
7359 static struct image_keyword xpm_format[XPM_LAST] =
7361 {":type", IMAGE_SYMBOL_VALUE, 1},
7362 {":file", IMAGE_STRING_VALUE, 0},
7363 {":data", IMAGE_STRING_VALUE, 0},
7364 {":ascent", IMAGE_ASCENT_VALUE, 0},
7365 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7366 {":relief", IMAGE_INTEGER_VALUE, 0},
7367 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7368 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7369 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7370 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7371 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7374 /* Structure describing the image type XBM. */
7376 static struct image_type xpm_type =
7378 &Qxpm,
7379 xpm_image_p,
7380 xpm_load,
7381 x_clear_image,
7382 NULL
7386 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
7387 functions for allocating image colors. Our own functions handle
7388 color allocation failures more gracefully than the ones on the XPM
7389 lib. */
7391 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
7392 #define ALLOC_XPM_COLORS
7393 #endif
7395 #ifdef ALLOC_XPM_COLORS
7397 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
7398 static void xpm_free_color_cache P_ ((void));
7399 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
7400 static int xpm_color_bucket P_ ((char *));
7401 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
7402 XColor *, int));
7404 /* An entry in a hash table used to cache color definitions of named
7405 colors. This cache is necessary to speed up XPM image loading in
7406 case we do color allocations ourselves. Without it, we would need
7407 a call to XParseColor per pixel in the image. */
7409 struct xpm_cached_color
7411 /* Next in collision chain. */
7412 struct xpm_cached_color *next;
7414 /* Color definition (RGB and pixel color). */
7415 XColor color;
7417 /* Color name. */
7418 char name[1];
7421 /* The hash table used for the color cache, and its bucket vector
7422 size. */
7424 #define XPM_COLOR_CACHE_BUCKETS 1001
7425 struct xpm_cached_color **xpm_color_cache;
7427 /* Initialize the color cache. */
7429 static void
7430 xpm_init_color_cache (f, attrs)
7431 struct frame *f;
7432 XpmAttributes *attrs;
7434 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
7435 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
7436 memset (xpm_color_cache, 0, nbytes);
7437 init_color_table ();
7439 if (attrs->valuemask & XpmColorSymbols)
7441 int i;
7442 XColor color;
7444 for (i = 0; i < attrs->numsymbols; ++i)
7445 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7446 attrs->colorsymbols[i].value, &color))
7448 color.pixel = lookup_rgb_color (f, color.red, color.green,
7449 color.blue);
7450 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
7456 /* Free the color cache. */
7458 static void
7459 xpm_free_color_cache ()
7461 struct xpm_cached_color *p, *next;
7462 int i;
7464 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
7465 for (p = xpm_color_cache[i]; p; p = next)
7467 next = p->next;
7468 xfree (p);
7471 xfree (xpm_color_cache);
7472 xpm_color_cache = NULL;
7473 free_color_table ();
7477 /* Return the bucket index for color named COLOR_NAME in the color
7478 cache. */
7480 static int
7481 xpm_color_bucket (color_name)
7482 char *color_name;
7484 unsigned h = 0;
7485 char *s;
7487 for (s = color_name; *s; ++s)
7488 h = (h << 2) ^ *s;
7489 return h %= XPM_COLOR_CACHE_BUCKETS;
7493 /* On frame F, cache values COLOR for color with name COLOR_NAME.
7494 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
7495 entry added. */
7497 static struct xpm_cached_color *
7498 xpm_cache_color (f, color_name, color, bucket)
7499 struct frame *f;
7500 char *color_name;
7501 XColor *color;
7502 int bucket;
7504 size_t nbytes;
7505 struct xpm_cached_color *p;
7507 if (bucket < 0)
7508 bucket = xpm_color_bucket (color_name);
7510 nbytes = sizeof *p + strlen (color_name);
7511 p = (struct xpm_cached_color *) xmalloc (nbytes);
7512 strcpy (p->name, color_name);
7513 p->color = *color;
7514 p->next = xpm_color_cache[bucket];
7515 xpm_color_cache[bucket] = p;
7516 return p;
7520 /* Look up color COLOR_NAME for frame F in the color cache. If found,
7521 return the cached definition in *COLOR. Otherwise, make a new
7522 entry in the cache and allocate the color. Value is zero if color
7523 allocation failed. */
7525 static int
7526 xpm_lookup_color (f, color_name, color)
7527 struct frame *f;
7528 char *color_name;
7529 XColor *color;
7531 struct xpm_cached_color *p;
7532 int h = xpm_color_bucket (color_name);
7534 for (p = xpm_color_cache[h]; p; p = p->next)
7535 if (strcmp (p->name, color_name) == 0)
7536 break;
7538 if (p != NULL)
7539 *color = p->color;
7540 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7541 color_name, color))
7543 color->pixel = lookup_rgb_color (f, color->red, color->green,
7544 color->blue);
7545 p = xpm_cache_color (f, color_name, color, h);
7548 return p != NULL;
7552 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7553 CLOSURE is a pointer to the frame on which we allocate the
7554 color. Return in *COLOR the allocated color. Value is non-zero
7555 if successful. */
7557 static int
7558 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7559 Display *dpy;
7560 Colormap cmap;
7561 char *color_name;
7562 XColor *color;
7563 void *closure;
7565 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7569 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7570 is a pointer to the frame on which we allocate the color. Value is
7571 non-zero if successful. */
7573 static int
7574 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7575 Display *dpy;
7576 Colormap cmap;
7577 Pixel *pixels;
7578 int npixels;
7579 void *closure;
7581 return 1;
7584 #endif /* ALLOC_XPM_COLORS */
7587 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7588 for XPM images. Such a list must consist of conses whose car and
7589 cdr are strings. */
7591 static int
7592 xpm_valid_color_symbols_p (color_symbols)
7593 Lisp_Object color_symbols;
7595 while (CONSP (color_symbols))
7597 Lisp_Object sym = XCAR (color_symbols);
7598 if (!CONSP (sym)
7599 || !STRINGP (XCAR (sym))
7600 || !STRINGP (XCDR (sym)))
7601 break;
7602 color_symbols = XCDR (color_symbols);
7605 return NILP (color_symbols);
7609 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7611 static int
7612 xpm_image_p (object)
7613 Lisp_Object object;
7615 struct image_keyword fmt[XPM_LAST];
7616 bcopy (xpm_format, fmt, sizeof fmt);
7617 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7618 /* Either `:file' or `:data' must be present. */
7619 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7620 /* Either no `:color-symbols' or it's a list of conses
7621 whose car and cdr are strings. */
7622 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7623 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7627 /* Load image IMG which will be displayed on frame F. Value is
7628 non-zero if successful. */
7630 static int
7631 xpm_load (f, img)
7632 struct frame *f;
7633 struct image *img;
7635 int rc;
7636 XpmAttributes attrs;
7637 Lisp_Object specified_file, color_symbols;
7639 /* Configure the XPM lib. Use the visual of frame F. Allocate
7640 close colors. Return colors allocated. */
7641 bzero (&attrs, sizeof attrs);
7642 attrs.visual = FRAME_X_VISUAL (f);
7643 attrs.colormap = FRAME_X_COLORMAP (f);
7644 attrs.valuemask |= XpmVisual;
7645 attrs.valuemask |= XpmColormap;
7647 #ifdef ALLOC_XPM_COLORS
7648 /* Allocate colors with our own functions which handle
7649 failing color allocation more gracefully. */
7650 attrs.color_closure = f;
7651 attrs.alloc_color = xpm_alloc_color;
7652 attrs.free_colors = xpm_free_colors;
7653 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7654 #else /* not ALLOC_XPM_COLORS */
7655 /* Let the XPM lib allocate colors. */
7656 attrs.valuemask |= XpmReturnAllocPixels;
7657 #ifdef XpmAllocCloseColors
7658 attrs.alloc_close_colors = 1;
7659 attrs.valuemask |= XpmAllocCloseColors;
7660 #else /* not XpmAllocCloseColors */
7661 attrs.closeness = 600;
7662 attrs.valuemask |= XpmCloseness;
7663 #endif /* not XpmAllocCloseColors */
7664 #endif /* ALLOC_XPM_COLORS */
7666 /* If image specification contains symbolic color definitions, add
7667 these to `attrs'. */
7668 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7669 if (CONSP (color_symbols))
7671 Lisp_Object tail;
7672 XpmColorSymbol *xpm_syms;
7673 int i, size;
7675 attrs.valuemask |= XpmColorSymbols;
7677 /* Count number of symbols. */
7678 attrs.numsymbols = 0;
7679 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7680 ++attrs.numsymbols;
7682 /* Allocate an XpmColorSymbol array. */
7683 size = attrs.numsymbols * sizeof *xpm_syms;
7684 xpm_syms = (XpmColorSymbol *) alloca (size);
7685 bzero (xpm_syms, size);
7686 attrs.colorsymbols = xpm_syms;
7688 /* Fill the color symbol array. */
7689 for (tail = color_symbols, i = 0;
7690 CONSP (tail);
7691 ++i, tail = XCDR (tail))
7693 Lisp_Object name = XCAR (XCAR (tail));
7694 Lisp_Object color = XCDR (XCAR (tail));
7695 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
7696 strcpy (xpm_syms[i].name, SDATA (name));
7697 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
7698 strcpy (xpm_syms[i].value, SDATA (color));
7702 /* Create a pixmap for the image, either from a file, or from a
7703 string buffer containing data in the same format as an XPM file. */
7704 #ifdef ALLOC_XPM_COLORS
7705 xpm_init_color_cache (f, &attrs);
7706 #endif
7708 specified_file = image_spec_value (img->spec, QCfile, NULL);
7709 if (STRINGP (specified_file))
7711 Lisp_Object file = x_find_image_file (specified_file);
7712 if (!STRINGP (file))
7714 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7715 return 0;
7718 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7719 SDATA (file), &img->pixmap, &img->mask,
7720 &attrs);
7722 else
7724 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7725 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7726 SDATA (buffer),
7727 &img->pixmap, &img->mask,
7728 &attrs);
7731 if (rc == XpmSuccess)
7733 #ifdef ALLOC_XPM_COLORS
7734 img->colors = colors_in_color_table (&img->ncolors);
7735 #else /* not ALLOC_XPM_COLORS */
7736 int i;
7738 img->ncolors = attrs.nalloc_pixels;
7739 img->colors = (unsigned long *) xmalloc (img->ncolors
7740 * sizeof *img->colors);
7741 for (i = 0; i < attrs.nalloc_pixels; ++i)
7743 img->colors[i] = attrs.alloc_pixels[i];
7744 #ifdef DEBUG_X_COLORS
7745 register_color (img->colors[i]);
7746 #endif
7748 #endif /* not ALLOC_XPM_COLORS */
7750 img->width = attrs.width;
7751 img->height = attrs.height;
7752 xassert (img->width > 0 && img->height > 0);
7754 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7755 XpmFreeAttributes (&attrs);
7757 else
7759 switch (rc)
7761 case XpmOpenFailed:
7762 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7763 break;
7765 case XpmFileInvalid:
7766 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7767 break;
7769 case XpmNoMemory:
7770 image_error ("Out of memory (%s)", img->spec, Qnil);
7771 break;
7773 case XpmColorFailed:
7774 image_error ("Color allocation error (%s)", img->spec, Qnil);
7775 break;
7777 default:
7778 image_error ("Unknown error (%s)", img->spec, Qnil);
7779 break;
7783 #ifdef ALLOC_XPM_COLORS
7784 xpm_free_color_cache ();
7785 #endif
7786 return rc == XpmSuccess;
7789 #endif /* HAVE_XPM != 0 */
7792 /***********************************************************************
7793 Color table
7794 ***********************************************************************/
7796 /* An entry in the color table mapping an RGB color to a pixel color. */
7798 struct ct_color
7800 int r, g, b;
7801 unsigned long pixel;
7803 /* Next in color table collision list. */
7804 struct ct_color *next;
7807 /* The bucket vector size to use. Must be prime. */
7809 #define CT_SIZE 101
7811 /* Value is a hash of the RGB color given by R, G, and B. */
7813 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7815 /* The color hash table. */
7817 struct ct_color **ct_table;
7819 /* Number of entries in the color table. */
7821 int ct_colors_allocated;
7823 /* Initialize the color table. */
7825 static void
7826 init_color_table ()
7828 int size = CT_SIZE * sizeof (*ct_table);
7829 ct_table = (struct ct_color **) xmalloc (size);
7830 bzero (ct_table, size);
7831 ct_colors_allocated = 0;
7835 /* Free memory associated with the color table. */
7837 static void
7838 free_color_table ()
7840 int i;
7841 struct ct_color *p, *next;
7843 for (i = 0; i < CT_SIZE; ++i)
7844 for (p = ct_table[i]; p; p = next)
7846 next = p->next;
7847 xfree (p);
7850 xfree (ct_table);
7851 ct_table = NULL;
7855 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7856 entry for that color already is in the color table, return the
7857 pixel color of that entry. Otherwise, allocate a new color for R,
7858 G, B, and make an entry in the color table. */
7860 static unsigned long
7861 lookup_rgb_color (f, r, g, b)
7862 struct frame *f;
7863 int r, g, b;
7865 unsigned hash = CT_HASH_RGB (r, g, b);
7866 int i = hash % CT_SIZE;
7867 struct ct_color *p;
7869 for (p = ct_table[i]; p; p = p->next)
7870 if (p->r == r && p->g == g && p->b == b)
7871 break;
7873 if (p == NULL)
7875 XColor color;
7876 Colormap cmap;
7877 int rc;
7879 color.red = r;
7880 color.green = g;
7881 color.blue = b;
7883 cmap = FRAME_X_COLORMAP (f);
7884 rc = x_alloc_nearest_color (f, cmap, &color);
7886 if (rc)
7888 ++ct_colors_allocated;
7890 p = (struct ct_color *) xmalloc (sizeof *p);
7891 p->r = r;
7892 p->g = g;
7893 p->b = b;
7894 p->pixel = color.pixel;
7895 p->next = ct_table[i];
7896 ct_table[i] = p;
7898 else
7899 return FRAME_FOREGROUND_PIXEL (f);
7902 return p->pixel;
7906 /* Look up pixel color PIXEL which is used on frame F in the color
7907 table. If not already present, allocate it. Value is PIXEL. */
7909 static unsigned long
7910 lookup_pixel_color (f, pixel)
7911 struct frame *f;
7912 unsigned long pixel;
7914 int i = pixel % CT_SIZE;
7915 struct ct_color *p;
7917 for (p = ct_table[i]; p; p = p->next)
7918 if (p->pixel == pixel)
7919 break;
7921 if (p == NULL)
7923 XColor color;
7924 Colormap cmap;
7925 int rc;
7927 cmap = FRAME_X_COLORMAP (f);
7928 color.pixel = pixel;
7929 x_query_color (f, &color);
7930 rc = x_alloc_nearest_color (f, cmap, &color);
7932 if (rc)
7934 ++ct_colors_allocated;
7936 p = (struct ct_color *) xmalloc (sizeof *p);
7937 p->r = color.red;
7938 p->g = color.green;
7939 p->b = color.blue;
7940 p->pixel = pixel;
7941 p->next = ct_table[i];
7942 ct_table[i] = p;
7944 else
7945 return FRAME_FOREGROUND_PIXEL (f);
7948 return p->pixel;
7952 /* Value is a vector of all pixel colors contained in the color table,
7953 allocated via xmalloc. Set *N to the number of colors. */
7955 static unsigned long *
7956 colors_in_color_table (n)
7957 int *n;
7959 int i, j;
7960 struct ct_color *p;
7961 unsigned long *colors;
7963 if (ct_colors_allocated == 0)
7965 *n = 0;
7966 colors = NULL;
7968 else
7970 colors = (unsigned long *) xmalloc (ct_colors_allocated
7971 * sizeof *colors);
7972 *n = ct_colors_allocated;
7974 for (i = j = 0; i < CT_SIZE; ++i)
7975 for (p = ct_table[i]; p; p = p->next)
7976 colors[j++] = p->pixel;
7979 return colors;
7984 /***********************************************************************
7985 Algorithms
7986 ***********************************************************************/
7988 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7989 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7990 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7992 /* Non-zero means draw a cross on images having `:conversion
7993 disabled'. */
7995 int cross_disabled_images;
7997 /* Edge detection matrices for different edge-detection
7998 strategies. */
8000 static int emboss_matrix[9] = {
8001 /* x - 1 x x + 1 */
8002 2, -1, 0, /* y - 1 */
8003 -1, 0, 1, /* y */
8004 0, 1, -2 /* y + 1 */
8007 static int laplace_matrix[9] = {
8008 /* x - 1 x x + 1 */
8009 1, 0, 0, /* y - 1 */
8010 0, 0, 0, /* y */
8011 0, 0, -1 /* y + 1 */
8014 /* Value is the intensity of the color whose red/green/blue values
8015 are R, G, and B. */
8017 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
8020 /* On frame F, return an array of XColor structures describing image
8021 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
8022 non-zero means also fill the red/green/blue members of the XColor
8023 structures. Value is a pointer to the array of XColors structures,
8024 allocated with xmalloc; it must be freed by the caller. */
8026 static XColor *
8027 x_to_xcolors (f, img, rgb_p)
8028 struct frame *f;
8029 struct image *img;
8030 int rgb_p;
8032 int x, y;
8033 XColor *colors, *p;
8034 XImage *ximg;
8036 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
8038 /* Get the X image IMG->pixmap. */
8039 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8040 0, 0, img->width, img->height, ~0, ZPixmap);
8042 /* Fill the `pixel' members of the XColor array. I wished there
8043 were an easy and portable way to circumvent XGetPixel. */
8044 p = colors;
8045 for (y = 0; y < img->height; ++y)
8047 XColor *row = p;
8049 for (x = 0; x < img->width; ++x, ++p)
8050 p->pixel = XGetPixel (ximg, x, y);
8052 if (rgb_p)
8053 x_query_colors (f, row, img->width);
8056 XDestroyImage (ximg);
8057 return colors;
8061 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
8062 RGB members are set. F is the frame on which this all happens.
8063 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
8065 static void
8066 x_from_xcolors (f, img, colors)
8067 struct frame *f;
8068 struct image *img;
8069 XColor *colors;
8071 int x, y;
8072 XImage *oimg;
8073 Pixmap pixmap;
8074 XColor *p;
8076 init_color_table ();
8078 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
8079 &oimg, &pixmap);
8080 p = colors;
8081 for (y = 0; y < img->height; ++y)
8082 for (x = 0; x < img->width; ++x, ++p)
8084 unsigned long pixel;
8085 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
8086 XPutPixel (oimg, x, y, pixel);
8089 xfree (colors);
8090 x_clear_image_1 (f, img, 1, 0, 1);
8092 x_put_x_image (f, oimg, pixmap, img->width, img->height);
8093 x_destroy_x_image (oimg);
8094 img->pixmap = pixmap;
8095 img->colors = colors_in_color_table (&img->ncolors);
8096 free_color_table ();
8100 /* On frame F, perform edge-detection on image IMG.
8102 MATRIX is a nine-element array specifying the transformation
8103 matrix. See emboss_matrix for an example.
8105 COLOR_ADJUST is a color adjustment added to each pixel of the
8106 outgoing image. */
8108 static void
8109 x_detect_edges (f, img, matrix, color_adjust)
8110 struct frame *f;
8111 struct image *img;
8112 int matrix[9], color_adjust;
8114 XColor *colors = x_to_xcolors (f, img, 1);
8115 XColor *new, *p;
8116 int x, y, i, sum;
8118 for (i = sum = 0; i < 9; ++i)
8119 sum += abs (matrix[i]);
8121 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
8123 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
8125 for (y = 0; y < img->height; ++y)
8127 p = COLOR (new, 0, y);
8128 p->red = p->green = p->blue = 0xffff/2;
8129 p = COLOR (new, img->width - 1, y);
8130 p->red = p->green = p->blue = 0xffff/2;
8133 for (x = 1; x < img->width - 1; ++x)
8135 p = COLOR (new, x, 0);
8136 p->red = p->green = p->blue = 0xffff/2;
8137 p = COLOR (new, x, img->height - 1);
8138 p->red = p->green = p->blue = 0xffff/2;
8141 for (y = 1; y < img->height - 1; ++y)
8143 p = COLOR (new, 1, y);
8145 for (x = 1; x < img->width - 1; ++x, ++p)
8147 int r, g, b, y1, x1;
8149 r = g = b = i = 0;
8150 for (y1 = y - 1; y1 < y + 2; ++y1)
8151 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
8152 if (matrix[i])
8154 XColor *t = COLOR (colors, x1, y1);
8155 r += matrix[i] * t->red;
8156 g += matrix[i] * t->green;
8157 b += matrix[i] * t->blue;
8160 r = (r / sum + color_adjust) & 0xffff;
8161 g = (g / sum + color_adjust) & 0xffff;
8162 b = (b / sum + color_adjust) & 0xffff;
8163 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
8167 xfree (colors);
8168 x_from_xcolors (f, img, new);
8170 #undef COLOR
8174 /* Perform the pre-defined `emboss' edge-detection on image IMG
8175 on frame F. */
8177 static void
8178 x_emboss (f, img)
8179 struct frame *f;
8180 struct image *img;
8182 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
8186 /* Perform the pre-defined `laplace' edge-detection on image IMG
8187 on frame F. */
8189 static void
8190 x_laplace (f, img)
8191 struct frame *f;
8192 struct image *img;
8194 x_detect_edges (f, img, laplace_matrix, 45000);
8198 /* Perform edge-detection on image IMG on frame F, with specified
8199 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
8201 MATRIX must be either
8203 - a list of at least 9 numbers in row-major form
8204 - a vector of at least 9 numbers
8206 COLOR_ADJUST nil means use a default; otherwise it must be a
8207 number. */
8209 static void
8210 x_edge_detection (f, img, matrix, color_adjust)
8211 struct frame *f;
8212 struct image *img;
8213 Lisp_Object matrix, color_adjust;
8215 int i = 0;
8216 int trans[9];
8218 if (CONSP (matrix))
8220 for (i = 0;
8221 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
8222 ++i, matrix = XCDR (matrix))
8223 trans[i] = XFLOATINT (XCAR (matrix));
8225 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
8227 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
8228 trans[i] = XFLOATINT (AREF (matrix, i));
8231 if (NILP (color_adjust))
8232 color_adjust = make_number (0xffff / 2);
8234 if (i == 9 && NUMBERP (color_adjust))
8235 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
8239 /* Transform image IMG on frame F so that it looks disabled. */
8241 static void
8242 x_disable_image (f, img)
8243 struct frame *f;
8244 struct image *img;
8246 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8248 if (dpyinfo->n_planes >= 2)
8250 /* Color (or grayscale). Convert to gray, and equalize. Just
8251 drawing such images with a stipple can look very odd, so
8252 we're using this method instead. */
8253 XColor *colors = x_to_xcolors (f, img, 1);
8254 XColor *p, *end;
8255 const int h = 15000;
8256 const int l = 30000;
8258 for (p = colors, end = colors + img->width * img->height;
8259 p < end;
8260 ++p)
8262 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
8263 int i2 = (0xffff - h - l) * i / 0xffff + l;
8264 p->red = p->green = p->blue = i2;
8267 x_from_xcolors (f, img, colors);
8270 /* Draw a cross over the disabled image, if we must or if we
8271 should. */
8272 if (dpyinfo->n_planes < 2 || cross_disabled_images)
8274 Display *dpy = FRAME_X_DISPLAY (f);
8275 GC gc;
8277 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
8278 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
8279 XDrawLine (dpy, img->pixmap, gc, 0, 0,
8280 img->width - 1, img->height - 1);
8281 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
8282 img->width - 1, 0);
8283 XFreeGC (dpy, gc);
8285 if (img->mask)
8287 gc = XCreateGC (dpy, img->mask, 0, NULL);
8288 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
8289 XDrawLine (dpy, img->mask, gc, 0, 0,
8290 img->width - 1, img->height - 1);
8291 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
8292 img->width - 1, 0);
8293 XFreeGC (dpy, gc);
8299 /* Build a mask for image IMG which is used on frame F. FILE is the
8300 name of an image file, for error messages. HOW determines how to
8301 determine the background color of IMG. If it is a list '(R G B)',
8302 with R, G, and B being integers >= 0, take that as the color of the
8303 background. Otherwise, determine the background color of IMG
8304 heuristically. Value is non-zero if successful. */
8306 static int
8307 x_build_heuristic_mask (f, img, how)
8308 struct frame *f;
8309 struct image *img;
8310 Lisp_Object how;
8312 Display *dpy = FRAME_X_DISPLAY (f);
8313 XImage *ximg, *mask_img;
8314 int x, y, rc, use_img_background;
8315 unsigned long bg = 0;
8317 if (img->mask)
8319 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
8320 img->mask = None;
8321 img->background_transparent_valid = 0;
8324 /* Create an image and pixmap serving as mask. */
8325 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
8326 &mask_img, &img->mask);
8327 if (!rc)
8328 return 0;
8330 /* Get the X image of IMG->pixmap. */
8331 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
8332 ~0, ZPixmap);
8334 /* Determine the background color of ximg. If HOW is `(R G B)'
8335 take that as color. Otherwise, use the image's background color. */
8336 use_img_background = 1;
8338 if (CONSP (how))
8340 int rgb[3], i;
8342 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
8344 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
8345 how = XCDR (how);
8348 if (i == 3 && NILP (how))
8350 char color_name[30];
8351 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
8352 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
8353 use_img_background = 0;
8357 if (use_img_background)
8358 bg = four_corners_best (ximg, img->width, img->height);
8360 /* Set all bits in mask_img to 1 whose color in ximg is different
8361 from the background color bg. */
8362 for (y = 0; y < img->height; ++y)
8363 for (x = 0; x < img->width; ++x)
8364 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
8366 /* Fill in the background_transparent field while we have the mask handy. */
8367 image_background_transparent (img, f, mask_img);
8369 /* Put mask_img into img->mask. */
8370 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8371 x_destroy_x_image (mask_img);
8372 XDestroyImage (ximg);
8374 return 1;
8379 /***********************************************************************
8380 PBM (mono, gray, color)
8381 ***********************************************************************/
8383 static int pbm_image_p P_ ((Lisp_Object object));
8384 static int pbm_load P_ ((struct frame *f, struct image *img));
8385 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
8387 /* The symbol `pbm' identifying images of this type. */
8389 Lisp_Object Qpbm;
8391 /* Indices of image specification fields in gs_format, below. */
8393 enum pbm_keyword_index
8395 PBM_TYPE,
8396 PBM_FILE,
8397 PBM_DATA,
8398 PBM_ASCENT,
8399 PBM_MARGIN,
8400 PBM_RELIEF,
8401 PBM_ALGORITHM,
8402 PBM_HEURISTIC_MASK,
8403 PBM_MASK,
8404 PBM_FOREGROUND,
8405 PBM_BACKGROUND,
8406 PBM_LAST
8409 /* Vector of image_keyword structures describing the format
8410 of valid user-defined image specifications. */
8412 static struct image_keyword pbm_format[PBM_LAST] =
8414 {":type", IMAGE_SYMBOL_VALUE, 1},
8415 {":file", IMAGE_STRING_VALUE, 0},
8416 {":data", IMAGE_STRING_VALUE, 0},
8417 {":ascent", IMAGE_ASCENT_VALUE, 0},
8418 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8419 {":relief", IMAGE_INTEGER_VALUE, 0},
8420 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8421 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8422 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8423 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8424 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8427 /* Structure describing the image type `pbm'. */
8429 static struct image_type pbm_type =
8431 &Qpbm,
8432 pbm_image_p,
8433 pbm_load,
8434 x_clear_image,
8435 NULL
8439 /* Return non-zero if OBJECT is a valid PBM image specification. */
8441 static int
8442 pbm_image_p (object)
8443 Lisp_Object object;
8445 struct image_keyword fmt[PBM_LAST];
8447 bcopy (pbm_format, fmt, sizeof fmt);
8449 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
8450 return 0;
8452 /* Must specify either :data or :file. */
8453 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
8457 /* Scan a decimal number from *S and return it. Advance *S while
8458 reading the number. END is the end of the string. Value is -1 at
8459 end of input. */
8461 static int
8462 pbm_scan_number (s, end)
8463 unsigned char **s, *end;
8465 int c = 0, val = -1;
8467 while (*s < end)
8469 /* Skip white-space. */
8470 while (*s < end && (c = *(*s)++, isspace (c)))
8473 if (c == '#')
8475 /* Skip comment to end of line. */
8476 while (*s < end && (c = *(*s)++, c != '\n'))
8479 else if (isdigit (c))
8481 /* Read decimal number. */
8482 val = c - '0';
8483 while (*s < end && (c = *(*s)++, isdigit (c)))
8484 val = 10 * val + c - '0';
8485 break;
8487 else
8488 break;
8491 return val;
8495 /* Load PBM image IMG for use on frame F. */
8497 static int
8498 pbm_load (f, img)
8499 struct frame *f;
8500 struct image *img;
8502 int raw_p, x, y;
8503 int width, height, max_color_idx = 0;
8504 XImage *ximg;
8505 Lisp_Object file, specified_file;
8506 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8507 struct gcpro gcpro1;
8508 unsigned char *contents = NULL;
8509 unsigned char *end, *p;
8510 int size;
8512 specified_file = image_spec_value (img->spec, QCfile, NULL);
8513 file = Qnil;
8514 GCPRO1 (file);
8516 if (STRINGP (specified_file))
8518 file = x_find_image_file (specified_file);
8519 if (!STRINGP (file))
8521 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8522 UNGCPRO;
8523 return 0;
8526 contents = slurp_file (SDATA (file), &size);
8527 if (contents == NULL)
8529 image_error ("Error reading `%s'", file, Qnil);
8530 UNGCPRO;
8531 return 0;
8534 p = contents;
8535 end = contents + size;
8537 else
8539 Lisp_Object data;
8540 data = image_spec_value (img->spec, QCdata, NULL);
8541 p = SDATA (data);
8542 end = p + SBYTES (data);
8545 /* Check magic number. */
8546 if (end - p < 2 || *p++ != 'P')
8548 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8549 error:
8550 xfree (contents);
8551 UNGCPRO;
8552 return 0;
8555 switch (*p++)
8557 case '1':
8558 raw_p = 0, type = PBM_MONO;
8559 break;
8561 case '2':
8562 raw_p = 0, type = PBM_GRAY;
8563 break;
8565 case '3':
8566 raw_p = 0, type = PBM_COLOR;
8567 break;
8569 case '4':
8570 raw_p = 1, type = PBM_MONO;
8571 break;
8573 case '5':
8574 raw_p = 1, type = PBM_GRAY;
8575 break;
8577 case '6':
8578 raw_p = 1, type = PBM_COLOR;
8579 break;
8581 default:
8582 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8583 goto error;
8586 /* Read width, height, maximum color-component. Characters
8587 starting with `#' up to the end of a line are ignored. */
8588 width = pbm_scan_number (&p, end);
8589 height = pbm_scan_number (&p, end);
8591 if (type != PBM_MONO)
8593 max_color_idx = pbm_scan_number (&p, end);
8594 if (raw_p && max_color_idx > 255)
8595 max_color_idx = 255;
8598 if (width < 0
8599 || height < 0
8600 || (type != PBM_MONO && max_color_idx < 0))
8601 goto error;
8603 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8604 &ximg, &img->pixmap))
8605 goto error;
8607 /* Initialize the color hash table. */
8608 init_color_table ();
8610 if (type == PBM_MONO)
8612 int c = 0, g;
8613 struct image_keyword fmt[PBM_LAST];
8614 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8615 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8617 /* Parse the image specification. */
8618 bcopy (pbm_format, fmt, sizeof fmt);
8619 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8621 /* Get foreground and background colors, maybe allocate colors. */
8622 if (fmt[PBM_FOREGROUND].count
8623 && STRINGP (fmt[PBM_FOREGROUND].value))
8624 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8625 if (fmt[PBM_BACKGROUND].count
8626 && STRINGP (fmt[PBM_BACKGROUND].value))
8628 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8629 img->background = bg;
8630 img->background_valid = 1;
8633 for (y = 0; y < height; ++y)
8634 for (x = 0; x < width; ++x)
8636 if (raw_p)
8638 if ((x & 7) == 0)
8639 c = *p++;
8640 g = c & 0x80;
8641 c <<= 1;
8643 else
8644 g = pbm_scan_number (&p, end);
8646 XPutPixel (ximg, x, y, g ? fg : bg);
8649 else
8651 for (y = 0; y < height; ++y)
8652 for (x = 0; x < width; ++x)
8654 int r, g, b;
8656 if (type == PBM_GRAY)
8657 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8658 else if (raw_p)
8660 r = *p++;
8661 g = *p++;
8662 b = *p++;
8664 else
8666 r = pbm_scan_number (&p, end);
8667 g = pbm_scan_number (&p, end);
8668 b = pbm_scan_number (&p, end);
8671 if (r < 0 || g < 0 || b < 0)
8673 xfree (ximg->data);
8674 ximg->data = NULL;
8675 XDestroyImage (ximg);
8676 image_error ("Invalid pixel value in image `%s'",
8677 img->spec, Qnil);
8678 goto error;
8681 /* RGB values are now in the range 0..max_color_idx.
8682 Scale this to the range 0..0xffff supported by X. */
8683 r = (double) r * 65535 / max_color_idx;
8684 g = (double) g * 65535 / max_color_idx;
8685 b = (double) b * 65535 / max_color_idx;
8686 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8690 /* Store in IMG->colors the colors allocated for the image, and
8691 free the color table. */
8692 img->colors = colors_in_color_table (&img->ncolors);
8693 free_color_table ();
8695 /* Maybe fill in the background field while we have ximg handy. */
8696 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8697 IMAGE_BACKGROUND (img, f, ximg);
8699 /* Put the image into a pixmap. */
8700 x_put_x_image (f, ximg, img->pixmap, width, height);
8701 x_destroy_x_image (ximg);
8703 img->width = width;
8704 img->height = height;
8706 UNGCPRO;
8707 xfree (contents);
8708 return 1;
8713 /***********************************************************************
8715 ***********************************************************************/
8717 #if HAVE_PNG
8719 #include <png.h>
8721 /* Function prototypes. */
8723 static int png_image_p P_ ((Lisp_Object object));
8724 static int png_load P_ ((struct frame *f, struct image *img));
8726 /* The symbol `png' identifying images of this type. */
8728 Lisp_Object Qpng;
8730 /* Indices of image specification fields in png_format, below. */
8732 enum png_keyword_index
8734 PNG_TYPE,
8735 PNG_DATA,
8736 PNG_FILE,
8737 PNG_ASCENT,
8738 PNG_MARGIN,
8739 PNG_RELIEF,
8740 PNG_ALGORITHM,
8741 PNG_HEURISTIC_MASK,
8742 PNG_MASK,
8743 PNG_BACKGROUND,
8744 PNG_LAST
8747 /* Vector of image_keyword structures describing the format
8748 of valid user-defined image specifications. */
8750 static struct image_keyword png_format[PNG_LAST] =
8752 {":type", IMAGE_SYMBOL_VALUE, 1},
8753 {":data", IMAGE_STRING_VALUE, 0},
8754 {":file", IMAGE_STRING_VALUE, 0},
8755 {":ascent", IMAGE_ASCENT_VALUE, 0},
8756 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8757 {":relief", IMAGE_INTEGER_VALUE, 0},
8758 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8759 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8760 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8761 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8764 /* Structure describing the image type `png'. */
8766 static struct image_type png_type =
8768 &Qpng,
8769 png_image_p,
8770 png_load,
8771 x_clear_image,
8772 NULL
8776 /* Return non-zero if OBJECT is a valid PNG image specification. */
8778 static int
8779 png_image_p (object)
8780 Lisp_Object object;
8782 struct image_keyword fmt[PNG_LAST];
8783 bcopy (png_format, fmt, sizeof fmt);
8785 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8786 return 0;
8788 /* Must specify either the :data or :file keyword. */
8789 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8793 /* Error and warning handlers installed when the PNG library
8794 is initialized. */
8796 static void
8797 my_png_error (png_ptr, msg)
8798 png_struct *png_ptr;
8799 char *msg;
8801 xassert (png_ptr != NULL);
8802 image_error ("PNG error: %s", build_string (msg), Qnil);
8803 longjmp (png_ptr->jmpbuf, 1);
8807 static void
8808 my_png_warning (png_ptr, msg)
8809 png_struct *png_ptr;
8810 char *msg;
8812 xassert (png_ptr != NULL);
8813 image_error ("PNG warning: %s", build_string (msg), Qnil);
8816 /* Memory source for PNG decoding. */
8818 struct png_memory_storage
8820 unsigned char *bytes; /* The data */
8821 size_t len; /* How big is it? */
8822 int index; /* Where are we? */
8826 /* Function set as reader function when reading PNG image from memory.
8827 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8828 bytes from the input to DATA. */
8830 static void
8831 png_read_from_memory (png_ptr, data, length)
8832 png_structp png_ptr;
8833 png_bytep data;
8834 png_size_t length;
8836 struct png_memory_storage *tbr
8837 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8839 if (length > tbr->len - tbr->index)
8840 png_error (png_ptr, "Read error");
8842 bcopy (tbr->bytes + tbr->index, data, length);
8843 tbr->index = tbr->index + length;
8846 /* Load PNG image IMG for use on frame F. Value is non-zero if
8847 successful. */
8849 static int
8850 png_load (f, img)
8851 struct frame *f;
8852 struct image *img;
8854 Lisp_Object file, specified_file;
8855 Lisp_Object specified_data;
8856 int x, y, i;
8857 XImage *ximg, *mask_img = NULL;
8858 struct gcpro gcpro1;
8859 png_struct *png_ptr = NULL;
8860 png_info *info_ptr = NULL, *end_info = NULL;
8861 FILE *volatile fp = NULL;
8862 png_byte sig[8];
8863 png_byte * volatile pixels = NULL;
8864 png_byte ** volatile rows = NULL;
8865 png_uint_32 width, height;
8866 int bit_depth, color_type, interlace_type;
8867 png_byte channels;
8868 png_uint_32 row_bytes;
8869 int transparent_p;
8870 double screen_gamma, image_gamma;
8871 int intent;
8872 struct png_memory_storage tbr; /* Data to be read */
8874 /* Find out what file to load. */
8875 specified_file = image_spec_value (img->spec, QCfile, NULL);
8876 specified_data = image_spec_value (img->spec, QCdata, NULL);
8877 file = Qnil;
8878 GCPRO1 (file);
8880 if (NILP (specified_data))
8882 file = x_find_image_file (specified_file);
8883 if (!STRINGP (file))
8885 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8886 UNGCPRO;
8887 return 0;
8890 /* Open the image file. */
8891 fp = fopen (SDATA (file), "rb");
8892 if (!fp)
8894 image_error ("Cannot open image file `%s'", file, Qnil);
8895 UNGCPRO;
8896 fclose (fp);
8897 return 0;
8900 /* Check PNG signature. */
8901 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8902 || !png_check_sig (sig, sizeof sig))
8904 image_error ("Not a PNG file: `%s'", file, Qnil);
8905 UNGCPRO;
8906 fclose (fp);
8907 return 0;
8910 else
8912 /* Read from memory. */
8913 tbr.bytes = SDATA (specified_data);
8914 tbr.len = SBYTES (specified_data);
8915 tbr.index = 0;
8917 /* Check PNG signature. */
8918 if (tbr.len < sizeof sig
8919 || !png_check_sig (tbr.bytes, sizeof sig))
8921 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8922 UNGCPRO;
8923 return 0;
8926 /* Need to skip past the signature. */
8927 tbr.bytes += sizeof (sig);
8930 /* Initialize read and info structs for PNG lib. */
8931 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8932 my_png_error, my_png_warning);
8933 if (!png_ptr)
8935 if (fp) fclose (fp);
8936 UNGCPRO;
8937 return 0;
8940 info_ptr = png_create_info_struct (png_ptr);
8941 if (!info_ptr)
8943 png_destroy_read_struct (&png_ptr, NULL, NULL);
8944 if (fp) fclose (fp);
8945 UNGCPRO;
8946 return 0;
8949 end_info = png_create_info_struct (png_ptr);
8950 if (!end_info)
8952 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8953 if (fp) fclose (fp);
8954 UNGCPRO;
8955 return 0;
8958 /* Set error jump-back. We come back here when the PNG library
8959 detects an error. */
8960 if (setjmp (png_ptr->jmpbuf))
8962 error:
8963 if (png_ptr)
8964 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8965 xfree (pixels);
8966 xfree (rows);
8967 if (fp) fclose (fp);
8968 UNGCPRO;
8969 return 0;
8972 /* Read image info. */
8973 if (!NILP (specified_data))
8974 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8975 else
8976 png_init_io (png_ptr, fp);
8978 png_set_sig_bytes (png_ptr, sizeof sig);
8979 png_read_info (png_ptr, info_ptr);
8980 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8981 &interlace_type, NULL, NULL);
8983 /* If image contains simply transparency data, we prefer to
8984 construct a clipping mask. */
8985 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8986 transparent_p = 1;
8987 else
8988 transparent_p = 0;
8990 /* This function is easier to write if we only have to handle
8991 one data format: RGB or RGBA with 8 bits per channel. Let's
8992 transform other formats into that format. */
8994 /* Strip more than 8 bits per channel. */
8995 if (bit_depth == 16)
8996 png_set_strip_16 (png_ptr);
8998 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8999 if available. */
9000 png_set_expand (png_ptr);
9002 /* Convert grayscale images to RGB. */
9003 if (color_type == PNG_COLOR_TYPE_GRAY
9004 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
9005 png_set_gray_to_rgb (png_ptr);
9007 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
9009 /* Tell the PNG lib to handle gamma correction for us. */
9011 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
9012 if (png_get_sRGB (png_ptr, info_ptr, &intent))
9013 /* The libpng documentation says this is right in this case. */
9014 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9015 else
9016 #endif
9017 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
9018 /* Image contains gamma information. */
9019 png_set_gamma (png_ptr, screen_gamma, image_gamma);
9020 else
9021 /* Use the standard default for the image gamma. */
9022 png_set_gamma (png_ptr, screen_gamma, 0.45455);
9024 /* Handle alpha channel by combining the image with a background
9025 color. Do this only if a real alpha channel is supplied. For
9026 simple transparency, we prefer a clipping mask. */
9027 if (!transparent_p)
9029 png_color_16 *image_bg;
9030 Lisp_Object specified_bg
9031 = image_spec_value (img->spec, QCbackground, NULL);
9033 if (STRINGP (specified_bg))
9034 /* The user specified `:background', use that. */
9036 XColor color;
9037 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
9039 png_color_16 user_bg;
9041 bzero (&user_bg, sizeof user_bg);
9042 user_bg.red = color.red;
9043 user_bg.green = color.green;
9044 user_bg.blue = color.blue;
9046 png_set_background (png_ptr, &user_bg,
9047 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9050 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
9051 /* Image contains a background color with which to
9052 combine the image. */
9053 png_set_background (png_ptr, image_bg,
9054 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
9055 else
9057 /* Image does not contain a background color with which
9058 to combine the image data via an alpha channel. Use
9059 the frame's background instead. */
9060 XColor color;
9061 Colormap cmap;
9062 png_color_16 frame_background;
9064 cmap = FRAME_X_COLORMAP (f);
9065 color.pixel = FRAME_BACKGROUND_PIXEL (f);
9066 x_query_color (f, &color);
9068 bzero (&frame_background, sizeof frame_background);
9069 frame_background.red = color.red;
9070 frame_background.green = color.green;
9071 frame_background.blue = color.blue;
9073 png_set_background (png_ptr, &frame_background,
9074 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
9078 /* Update info structure. */
9079 png_read_update_info (png_ptr, info_ptr);
9081 /* Get number of channels. Valid values are 1 for grayscale images
9082 and images with a palette, 2 for grayscale images with transparency
9083 information (alpha channel), 3 for RGB images, and 4 for RGB
9084 images with alpha channel, i.e. RGBA. If conversions above were
9085 sufficient we should only have 3 or 4 channels here. */
9086 channels = png_get_channels (png_ptr, info_ptr);
9087 xassert (channels == 3 || channels == 4);
9089 /* Number of bytes needed for one row of the image. */
9090 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
9092 /* Allocate memory for the image. */
9093 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
9094 rows = (png_byte **) xmalloc (height * sizeof *rows);
9095 for (i = 0; i < height; ++i)
9096 rows[i] = pixels + i * row_bytes;
9098 /* Read the entire image. */
9099 png_read_image (png_ptr, rows);
9100 png_read_end (png_ptr, info_ptr);
9101 if (fp)
9103 fclose (fp);
9104 fp = NULL;
9107 /* Create the X image and pixmap. */
9108 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
9109 &img->pixmap))
9110 goto error;
9112 /* Create an image and pixmap serving as mask if the PNG image
9113 contains an alpha channel. */
9114 if (channels == 4
9115 && !transparent_p
9116 && !x_create_x_image_and_pixmap (f, width, height, 1,
9117 &mask_img, &img->mask))
9119 x_destroy_x_image (ximg);
9120 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
9121 img->pixmap = None;
9122 goto error;
9125 /* Fill the X image and mask from PNG data. */
9126 init_color_table ();
9128 for (y = 0; y < height; ++y)
9130 png_byte *p = rows[y];
9132 for (x = 0; x < width; ++x)
9134 unsigned r, g, b;
9136 r = *p++ << 8;
9137 g = *p++ << 8;
9138 b = *p++ << 8;
9139 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
9141 /* An alpha channel, aka mask channel, associates variable
9142 transparency with an image. Where other image formats
9143 support binary transparency---fully transparent or fully
9144 opaque---PNG allows up to 254 levels of partial transparency.
9145 The PNG library implements partial transparency by combining
9146 the image with a specified background color.
9148 I'm not sure how to handle this here nicely: because the
9149 background on which the image is displayed may change, for
9150 real alpha channel support, it would be necessary to create
9151 a new image for each possible background.
9153 What I'm doing now is that a mask is created if we have
9154 boolean transparency information. Otherwise I'm using
9155 the frame's background color to combine the image with. */
9157 if (channels == 4)
9159 if (mask_img)
9160 XPutPixel (mask_img, x, y, *p > 0);
9161 ++p;
9166 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9167 /* Set IMG's background color from the PNG image, unless the user
9168 overrode it. */
9170 png_color_16 *bg;
9171 if (png_get_bKGD (png_ptr, info_ptr, &bg))
9173 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
9174 img->background_valid = 1;
9178 /* Remember colors allocated for this image. */
9179 img->colors = colors_in_color_table (&img->ncolors);
9180 free_color_table ();
9182 /* Clean up. */
9183 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
9184 xfree (rows);
9185 xfree (pixels);
9187 img->width = width;
9188 img->height = height;
9190 /* Maybe fill in the background field while we have ximg handy. */
9191 IMAGE_BACKGROUND (img, f, ximg);
9193 /* Put the image into the pixmap, then free the X image and its buffer. */
9194 x_put_x_image (f, ximg, img->pixmap, width, height);
9195 x_destroy_x_image (ximg);
9197 /* Same for the mask. */
9198 if (mask_img)
9200 /* Fill in the background_transparent field while we have the mask
9201 handy. */
9202 image_background_transparent (img, f, mask_img);
9204 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
9205 x_destroy_x_image (mask_img);
9208 UNGCPRO;
9209 return 1;
9212 #endif /* HAVE_PNG != 0 */
9216 /***********************************************************************
9217 JPEG
9218 ***********************************************************************/
9220 #if HAVE_JPEG
9222 /* Work around a warning about HAVE_STDLIB_H being redefined in
9223 jconfig.h. */
9224 #ifdef HAVE_STDLIB_H
9225 #define HAVE_STDLIB_H_1
9226 #undef HAVE_STDLIB_H
9227 #endif /* HAVE_STLIB_H */
9229 #include <jpeglib.h>
9230 #include <jerror.h>
9231 #include <setjmp.h>
9233 #ifdef HAVE_STLIB_H_1
9234 #define HAVE_STDLIB_H 1
9235 #endif
9237 static int jpeg_image_p P_ ((Lisp_Object object));
9238 static int jpeg_load P_ ((struct frame *f, struct image *img));
9240 /* The symbol `jpeg' identifying images of this type. */
9242 Lisp_Object Qjpeg;
9244 /* Indices of image specification fields in gs_format, below. */
9246 enum jpeg_keyword_index
9248 JPEG_TYPE,
9249 JPEG_DATA,
9250 JPEG_FILE,
9251 JPEG_ASCENT,
9252 JPEG_MARGIN,
9253 JPEG_RELIEF,
9254 JPEG_ALGORITHM,
9255 JPEG_HEURISTIC_MASK,
9256 JPEG_MASK,
9257 JPEG_BACKGROUND,
9258 JPEG_LAST
9261 /* Vector of image_keyword structures describing the format
9262 of valid user-defined image specifications. */
9264 static struct image_keyword jpeg_format[JPEG_LAST] =
9266 {":type", IMAGE_SYMBOL_VALUE, 1},
9267 {":data", IMAGE_STRING_VALUE, 0},
9268 {":file", IMAGE_STRING_VALUE, 0},
9269 {":ascent", IMAGE_ASCENT_VALUE, 0},
9270 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9271 {":relief", IMAGE_INTEGER_VALUE, 0},
9272 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9273 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9274 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9275 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9278 /* Structure describing the image type `jpeg'. */
9280 static struct image_type jpeg_type =
9282 &Qjpeg,
9283 jpeg_image_p,
9284 jpeg_load,
9285 x_clear_image,
9286 NULL
9290 /* Return non-zero if OBJECT is a valid JPEG image specification. */
9292 static int
9293 jpeg_image_p (object)
9294 Lisp_Object object;
9296 struct image_keyword fmt[JPEG_LAST];
9298 bcopy (jpeg_format, fmt, sizeof fmt);
9300 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
9301 return 0;
9303 /* Must specify either the :data or :file keyword. */
9304 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
9308 struct my_jpeg_error_mgr
9310 struct jpeg_error_mgr pub;
9311 jmp_buf setjmp_buffer;
9315 static void
9316 my_error_exit (cinfo)
9317 j_common_ptr cinfo;
9319 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
9320 longjmp (mgr->setjmp_buffer, 1);
9324 /* Init source method for JPEG data source manager. Called by
9325 jpeg_read_header() before any data is actually read. See
9326 libjpeg.doc from the JPEG lib distribution. */
9328 static void
9329 our_init_source (cinfo)
9330 j_decompress_ptr cinfo;
9335 /* Fill input buffer method for JPEG data source manager. Called
9336 whenever more data is needed. We read the whole image in one step,
9337 so this only adds a fake end of input marker at the end. */
9339 static boolean
9340 our_fill_input_buffer (cinfo)
9341 j_decompress_ptr cinfo;
9343 /* Insert a fake EOI marker. */
9344 struct jpeg_source_mgr *src = cinfo->src;
9345 static JOCTET buffer[2];
9347 buffer[0] = (JOCTET) 0xFF;
9348 buffer[1] = (JOCTET) JPEG_EOI;
9350 src->next_input_byte = buffer;
9351 src->bytes_in_buffer = 2;
9352 return TRUE;
9356 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
9357 is the JPEG data source manager. */
9359 static void
9360 our_skip_input_data (cinfo, num_bytes)
9361 j_decompress_ptr cinfo;
9362 long num_bytes;
9364 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
9366 if (src)
9368 if (num_bytes > src->bytes_in_buffer)
9369 ERREXIT (cinfo, JERR_INPUT_EOF);
9371 src->bytes_in_buffer -= num_bytes;
9372 src->next_input_byte += num_bytes;
9377 /* Method to terminate data source. Called by
9378 jpeg_finish_decompress() after all data has been processed. */
9380 static void
9381 our_term_source (cinfo)
9382 j_decompress_ptr cinfo;
9387 /* Set up the JPEG lib for reading an image from DATA which contains
9388 LEN bytes. CINFO is the decompression info structure created for
9389 reading the image. */
9391 static void
9392 jpeg_memory_src (cinfo, data, len)
9393 j_decompress_ptr cinfo;
9394 JOCTET *data;
9395 unsigned int len;
9397 struct jpeg_source_mgr *src;
9399 if (cinfo->src == NULL)
9401 /* First time for this JPEG object? */
9402 cinfo->src = (struct jpeg_source_mgr *)
9403 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
9404 sizeof (struct jpeg_source_mgr));
9405 src = (struct jpeg_source_mgr *) cinfo->src;
9406 src->next_input_byte = data;
9409 src = (struct jpeg_source_mgr *) cinfo->src;
9410 src->init_source = our_init_source;
9411 src->fill_input_buffer = our_fill_input_buffer;
9412 src->skip_input_data = our_skip_input_data;
9413 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
9414 src->term_source = our_term_source;
9415 src->bytes_in_buffer = len;
9416 src->next_input_byte = data;
9420 /* Load image IMG for use on frame F. Patterned after example.c
9421 from the JPEG lib. */
9423 static int
9424 jpeg_load (f, img)
9425 struct frame *f;
9426 struct image *img;
9428 struct jpeg_decompress_struct cinfo;
9429 struct my_jpeg_error_mgr mgr;
9430 Lisp_Object file, specified_file;
9431 Lisp_Object specified_data;
9432 FILE * volatile fp = NULL;
9433 JSAMPARRAY buffer;
9434 int row_stride, x, y;
9435 XImage *ximg = NULL;
9436 int rc;
9437 unsigned long *colors;
9438 int width, height;
9439 struct gcpro gcpro1;
9441 /* Open the JPEG file. */
9442 specified_file = image_spec_value (img->spec, QCfile, NULL);
9443 specified_data = image_spec_value (img->spec, QCdata, NULL);
9444 file = Qnil;
9445 GCPRO1 (file);
9447 if (NILP (specified_data))
9449 file = x_find_image_file (specified_file);
9450 if (!STRINGP (file))
9452 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9453 UNGCPRO;
9454 return 0;
9457 fp = fopen (SDATA (file), "r");
9458 if (fp == NULL)
9460 image_error ("Cannot open `%s'", file, Qnil);
9461 UNGCPRO;
9462 return 0;
9466 /* Customize libjpeg's error handling to call my_error_exit when an
9467 error is detected. This function will perform a longjmp. */
9468 cinfo.err = jpeg_std_error (&mgr.pub);
9469 mgr.pub.error_exit = my_error_exit;
9471 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
9473 if (rc == 1)
9475 /* Called from my_error_exit. Display a JPEG error. */
9476 char buffer[JMSG_LENGTH_MAX];
9477 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
9478 image_error ("Error reading JPEG image `%s': %s", img->spec,
9479 build_string (buffer));
9482 /* Close the input file and destroy the JPEG object. */
9483 if (fp)
9484 fclose ((FILE *) fp);
9485 jpeg_destroy_decompress (&cinfo);
9487 /* If we already have an XImage, free that. */
9488 x_destroy_x_image (ximg);
9490 /* Free pixmap and colors. */
9491 x_clear_image (f, img);
9493 UNGCPRO;
9494 return 0;
9497 /* Create the JPEG decompression object. Let it read from fp.
9498 Read the JPEG image header. */
9499 jpeg_create_decompress (&cinfo);
9501 if (NILP (specified_data))
9502 jpeg_stdio_src (&cinfo, (FILE *) fp);
9503 else
9504 jpeg_memory_src (&cinfo, SDATA (specified_data),
9505 SBYTES (specified_data));
9507 jpeg_read_header (&cinfo, TRUE);
9509 /* Customize decompression so that color quantization will be used.
9510 Start decompression. */
9511 cinfo.quantize_colors = TRUE;
9512 jpeg_start_decompress (&cinfo);
9513 width = img->width = cinfo.output_width;
9514 height = img->height = cinfo.output_height;
9516 /* Create X image and pixmap. */
9517 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9518 longjmp (mgr.setjmp_buffer, 2);
9520 /* Allocate colors. When color quantization is used,
9521 cinfo.actual_number_of_colors has been set with the number of
9522 colors generated, and cinfo.colormap is a two-dimensional array
9523 of color indices in the range 0..cinfo.actual_number_of_colors.
9524 No more than 255 colors will be generated. */
9526 int i, ir, ig, ib;
9528 if (cinfo.out_color_components > 2)
9529 ir = 0, ig = 1, ib = 2;
9530 else if (cinfo.out_color_components > 1)
9531 ir = 0, ig = 1, ib = 0;
9532 else
9533 ir = 0, ig = 0, ib = 0;
9535 /* Use the color table mechanism because it handles colors that
9536 cannot be allocated nicely. Such colors will be replaced with
9537 a default color, and we don't have to care about which colors
9538 can be freed safely, and which can't. */
9539 init_color_table ();
9540 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
9541 * sizeof *colors);
9543 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9545 /* Multiply RGB values with 255 because X expects RGB values
9546 in the range 0..0xffff. */
9547 int r = cinfo.colormap[ir][i] << 8;
9548 int g = cinfo.colormap[ig][i] << 8;
9549 int b = cinfo.colormap[ib][i] << 8;
9550 colors[i] = lookup_rgb_color (f, r, g, b);
9553 /* Remember those colors actually allocated. */
9554 img->colors = colors_in_color_table (&img->ncolors);
9555 free_color_table ();
9558 /* Read pixels. */
9559 row_stride = width * cinfo.output_components;
9560 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9561 row_stride, 1);
9562 for (y = 0; y < height; ++y)
9564 jpeg_read_scanlines (&cinfo, buffer, 1);
9565 for (x = 0; x < cinfo.output_width; ++x)
9566 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9569 /* Clean up. */
9570 jpeg_finish_decompress (&cinfo);
9571 jpeg_destroy_decompress (&cinfo);
9572 if (fp)
9573 fclose ((FILE *) fp);
9575 /* Maybe fill in the background field while we have ximg handy. */
9576 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9577 IMAGE_BACKGROUND (img, f, ximg);
9579 /* Put the image into the pixmap. */
9580 x_put_x_image (f, ximg, img->pixmap, width, height);
9581 x_destroy_x_image (ximg);
9582 UNGCPRO;
9583 return 1;
9586 #endif /* HAVE_JPEG */
9590 /***********************************************************************
9591 TIFF
9592 ***********************************************************************/
9594 #if HAVE_TIFF
9596 #include <tiffio.h>
9598 static int tiff_image_p P_ ((Lisp_Object object));
9599 static int tiff_load P_ ((struct frame *f, struct image *img));
9601 /* The symbol `tiff' identifying images of this type. */
9603 Lisp_Object Qtiff;
9605 /* Indices of image specification fields in tiff_format, below. */
9607 enum tiff_keyword_index
9609 TIFF_TYPE,
9610 TIFF_DATA,
9611 TIFF_FILE,
9612 TIFF_ASCENT,
9613 TIFF_MARGIN,
9614 TIFF_RELIEF,
9615 TIFF_ALGORITHM,
9616 TIFF_HEURISTIC_MASK,
9617 TIFF_MASK,
9618 TIFF_BACKGROUND,
9619 TIFF_LAST
9622 /* Vector of image_keyword structures describing the format
9623 of valid user-defined image specifications. */
9625 static struct image_keyword tiff_format[TIFF_LAST] =
9627 {":type", IMAGE_SYMBOL_VALUE, 1},
9628 {":data", IMAGE_STRING_VALUE, 0},
9629 {":file", IMAGE_STRING_VALUE, 0},
9630 {":ascent", IMAGE_ASCENT_VALUE, 0},
9631 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9632 {":relief", IMAGE_INTEGER_VALUE, 0},
9633 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9634 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9635 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9636 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9639 /* Structure describing the image type `tiff'. */
9641 static struct image_type tiff_type =
9643 &Qtiff,
9644 tiff_image_p,
9645 tiff_load,
9646 x_clear_image,
9647 NULL
9651 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9653 static int
9654 tiff_image_p (object)
9655 Lisp_Object object;
9657 struct image_keyword fmt[TIFF_LAST];
9658 bcopy (tiff_format, fmt, sizeof fmt);
9660 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9661 return 0;
9663 /* Must specify either the :data or :file keyword. */
9664 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9668 /* Reading from a memory buffer for TIFF images Based on the PNG
9669 memory source, but we have to provide a lot of extra functions.
9670 Blah.
9672 We really only need to implement read and seek, but I am not
9673 convinced that the TIFF library is smart enough not to destroy
9674 itself if we only hand it the function pointers we need to
9675 override. */
9677 typedef struct
9679 unsigned char *bytes;
9680 size_t len;
9681 int index;
9683 tiff_memory_source;
9686 static size_t
9687 tiff_read_from_memory (data, buf, size)
9688 thandle_t data;
9689 tdata_t buf;
9690 tsize_t size;
9692 tiff_memory_source *src = (tiff_memory_source *) data;
9694 if (size > src->len - src->index)
9695 return (size_t) -1;
9696 bcopy (src->bytes + src->index, buf, size);
9697 src->index += size;
9698 return size;
9702 static size_t
9703 tiff_write_from_memory (data, buf, size)
9704 thandle_t data;
9705 tdata_t buf;
9706 tsize_t size;
9708 return (size_t) -1;
9712 static toff_t
9713 tiff_seek_in_memory (data, off, whence)
9714 thandle_t data;
9715 toff_t off;
9716 int whence;
9718 tiff_memory_source *src = (tiff_memory_source *) data;
9719 int idx;
9721 switch (whence)
9723 case SEEK_SET: /* Go from beginning of source. */
9724 idx = off;
9725 break;
9727 case SEEK_END: /* Go from end of source. */
9728 idx = src->len + off;
9729 break;
9731 case SEEK_CUR: /* Go from current position. */
9732 idx = src->index + off;
9733 break;
9735 default: /* Invalid `whence'. */
9736 return -1;
9739 if (idx > src->len || idx < 0)
9740 return -1;
9742 src->index = idx;
9743 return src->index;
9747 static int
9748 tiff_close_memory (data)
9749 thandle_t data;
9751 /* NOOP */
9752 return 0;
9756 static int
9757 tiff_mmap_memory (data, pbase, psize)
9758 thandle_t data;
9759 tdata_t *pbase;
9760 toff_t *psize;
9762 /* It is already _IN_ memory. */
9763 return 0;
9767 static void
9768 tiff_unmap_memory (data, base, size)
9769 thandle_t data;
9770 tdata_t base;
9771 toff_t size;
9773 /* We don't need to do this. */
9777 static toff_t
9778 tiff_size_of_memory (data)
9779 thandle_t data;
9781 return ((tiff_memory_source *) data)->len;
9785 static void
9786 tiff_error_handler (title, format, ap)
9787 const char *title, *format;
9788 va_list ap;
9790 char buf[512];
9791 int len;
9793 len = sprintf (buf, "TIFF error: %s ", title);
9794 vsprintf (buf + len, format, ap);
9795 add_to_log (buf, Qnil, Qnil);
9799 static void
9800 tiff_warning_handler (title, format, ap)
9801 const char *title, *format;
9802 va_list ap;
9804 char buf[512];
9805 int len;
9807 len = sprintf (buf, "TIFF warning: %s ", title);
9808 vsprintf (buf + len, format, ap);
9809 add_to_log (buf, Qnil, Qnil);
9813 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9814 successful. */
9816 static int
9817 tiff_load (f, img)
9818 struct frame *f;
9819 struct image *img;
9821 Lisp_Object file, specified_file;
9822 Lisp_Object specified_data;
9823 TIFF *tiff;
9824 int width, height, x, y;
9825 uint32 *buf;
9826 int rc;
9827 XImage *ximg;
9828 struct gcpro gcpro1;
9829 tiff_memory_source memsrc;
9831 specified_file = image_spec_value (img->spec, QCfile, NULL);
9832 specified_data = image_spec_value (img->spec, QCdata, NULL);
9833 file = Qnil;
9834 GCPRO1 (file);
9836 TIFFSetErrorHandler (tiff_error_handler);
9837 TIFFSetWarningHandler (tiff_warning_handler);
9839 if (NILP (specified_data))
9841 /* Read from a file */
9842 file = x_find_image_file (specified_file);
9843 if (!STRINGP (file))
9845 image_error ("Cannot find image file `%s'", file, Qnil);
9846 UNGCPRO;
9847 return 0;
9850 /* Try to open the image file. */
9851 tiff = TIFFOpen (SDATA (file), "r");
9852 if (tiff == NULL)
9854 image_error ("Cannot open `%s'", file, Qnil);
9855 UNGCPRO;
9856 return 0;
9859 else
9861 /* Memory source! */
9862 memsrc.bytes = SDATA (specified_data);
9863 memsrc.len = SBYTES (specified_data);
9864 memsrc.index = 0;
9866 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9867 (TIFFReadWriteProc) tiff_read_from_memory,
9868 (TIFFReadWriteProc) tiff_write_from_memory,
9869 tiff_seek_in_memory,
9870 tiff_close_memory,
9871 tiff_size_of_memory,
9872 tiff_mmap_memory,
9873 tiff_unmap_memory);
9875 if (!tiff)
9877 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9878 UNGCPRO;
9879 return 0;
9883 /* Get width and height of the image, and allocate a raster buffer
9884 of width x height 32-bit values. */
9885 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9886 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9887 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9889 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9890 TIFFClose (tiff);
9891 if (!rc)
9893 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9894 xfree (buf);
9895 UNGCPRO;
9896 return 0;
9899 /* Create the X image and pixmap. */
9900 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9902 xfree (buf);
9903 UNGCPRO;
9904 return 0;
9907 /* Initialize the color table. */
9908 init_color_table ();
9910 /* Process the pixel raster. Origin is in the lower-left corner. */
9911 for (y = 0; y < height; ++y)
9913 uint32 *row = buf + y * width;
9915 for (x = 0; x < width; ++x)
9917 uint32 abgr = row[x];
9918 int r = TIFFGetR (abgr) << 8;
9919 int g = TIFFGetG (abgr) << 8;
9920 int b = TIFFGetB (abgr) << 8;
9921 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9925 /* Remember the colors allocated for the image. Free the color table. */
9926 img->colors = colors_in_color_table (&img->ncolors);
9927 free_color_table ();
9929 img->width = width;
9930 img->height = height;
9932 /* Maybe fill in the background field while we have ximg handy. */
9933 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
9934 IMAGE_BACKGROUND (img, f, ximg);
9936 /* Put the image into the pixmap, then free the X image and its buffer. */
9937 x_put_x_image (f, ximg, img->pixmap, width, height);
9938 x_destroy_x_image (ximg);
9939 xfree (buf);
9941 UNGCPRO;
9942 return 1;
9945 #endif /* HAVE_TIFF != 0 */
9949 /***********************************************************************
9951 ***********************************************************************/
9953 #if HAVE_GIF
9955 #include <gif_lib.h>
9957 static int gif_image_p P_ ((Lisp_Object object));
9958 static int gif_load P_ ((struct frame *f, struct image *img));
9960 /* The symbol `gif' identifying images of this type. */
9962 Lisp_Object Qgif;
9964 /* Indices of image specification fields in gif_format, below. */
9966 enum gif_keyword_index
9968 GIF_TYPE,
9969 GIF_DATA,
9970 GIF_FILE,
9971 GIF_ASCENT,
9972 GIF_MARGIN,
9973 GIF_RELIEF,
9974 GIF_ALGORITHM,
9975 GIF_HEURISTIC_MASK,
9976 GIF_MASK,
9977 GIF_IMAGE,
9978 GIF_BACKGROUND,
9979 GIF_LAST
9982 /* Vector of image_keyword structures describing the format
9983 of valid user-defined image specifications. */
9985 static struct image_keyword gif_format[GIF_LAST] =
9987 {":type", IMAGE_SYMBOL_VALUE, 1},
9988 {":data", IMAGE_STRING_VALUE, 0},
9989 {":file", IMAGE_STRING_VALUE, 0},
9990 {":ascent", IMAGE_ASCENT_VALUE, 0},
9991 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9992 {":relief", IMAGE_INTEGER_VALUE, 0},
9993 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9994 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9995 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9996 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9997 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10000 /* Structure describing the image type `gif'. */
10002 static struct image_type gif_type =
10004 &Qgif,
10005 gif_image_p,
10006 gif_load,
10007 x_clear_image,
10008 NULL
10012 /* Return non-zero if OBJECT is a valid GIF image specification. */
10014 static int
10015 gif_image_p (object)
10016 Lisp_Object object;
10018 struct image_keyword fmt[GIF_LAST];
10019 bcopy (gif_format, fmt, sizeof fmt);
10021 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
10022 return 0;
10024 /* Must specify either the :data or :file keyword. */
10025 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
10029 /* Reading a GIF image from memory
10030 Based on the PNG memory stuff to a certain extent. */
10032 typedef struct
10034 unsigned char *bytes;
10035 size_t len;
10036 int index;
10038 gif_memory_source;
10041 /* Make the current memory source available to gif_read_from_memory.
10042 It's done this way because not all versions of libungif support
10043 a UserData field in the GifFileType structure. */
10044 static gif_memory_source *current_gif_memory_src;
10046 static int
10047 gif_read_from_memory (file, buf, len)
10048 GifFileType *file;
10049 GifByteType *buf;
10050 int len;
10052 gif_memory_source *src = current_gif_memory_src;
10054 if (len > src->len - src->index)
10055 return -1;
10057 bcopy (src->bytes + src->index, buf, len);
10058 src->index += len;
10059 return len;
10063 /* Load GIF image IMG for use on frame F. Value is non-zero if
10064 successful. */
10066 static int
10067 gif_load (f, img)
10068 struct frame *f;
10069 struct image *img;
10071 Lisp_Object file, specified_file;
10072 Lisp_Object specified_data;
10073 int rc, width, height, x, y, i;
10074 XImage *ximg;
10075 ColorMapObject *gif_color_map;
10076 unsigned long pixel_colors[256];
10077 GifFileType *gif;
10078 struct gcpro gcpro1;
10079 Lisp_Object image;
10080 int ino, image_left, image_top, image_width, image_height;
10081 gif_memory_source memsrc;
10082 unsigned char *raster;
10084 specified_file = image_spec_value (img->spec, QCfile, NULL);
10085 specified_data = image_spec_value (img->spec, QCdata, NULL);
10086 file = Qnil;
10087 GCPRO1 (file);
10089 if (NILP (specified_data))
10091 file = x_find_image_file (specified_file);
10092 if (!STRINGP (file))
10094 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10095 UNGCPRO;
10096 return 0;
10099 /* Open the GIF file. */
10100 gif = DGifOpenFileName (SDATA (file));
10101 if (gif == NULL)
10103 image_error ("Cannot open `%s'", file, Qnil);
10104 UNGCPRO;
10105 return 0;
10108 else
10110 /* Read from memory! */
10111 current_gif_memory_src = &memsrc;
10112 memsrc.bytes = SDATA (specified_data);
10113 memsrc.len = SBYTES (specified_data);
10114 memsrc.index = 0;
10116 gif = DGifOpen(&memsrc, gif_read_from_memory);
10117 if (!gif)
10119 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
10120 UNGCPRO;
10121 return 0;
10125 /* Read entire contents. */
10126 rc = DGifSlurp (gif);
10127 if (rc == GIF_ERROR)
10129 image_error ("Error reading `%s'", img->spec, Qnil);
10130 DGifCloseFile (gif);
10131 UNGCPRO;
10132 return 0;
10135 image = image_spec_value (img->spec, QCindex, NULL);
10136 ino = INTEGERP (image) ? XFASTINT (image) : 0;
10137 if (ino >= gif->ImageCount)
10139 image_error ("Invalid image number `%s' in image `%s'",
10140 image, img->spec);
10141 DGifCloseFile (gif);
10142 UNGCPRO;
10143 return 0;
10146 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
10147 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
10149 /* Create the X image and pixmap. */
10150 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10152 DGifCloseFile (gif);
10153 UNGCPRO;
10154 return 0;
10157 /* Allocate colors. */
10158 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
10159 if (!gif_color_map)
10160 gif_color_map = gif->SColorMap;
10161 init_color_table ();
10162 bzero (pixel_colors, sizeof pixel_colors);
10164 for (i = 0; i < gif_color_map->ColorCount; ++i)
10166 int r = gif_color_map->Colors[i].Red << 8;
10167 int g = gif_color_map->Colors[i].Green << 8;
10168 int b = gif_color_map->Colors[i].Blue << 8;
10169 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
10172 img->colors = colors_in_color_table (&img->ncolors);
10173 free_color_table ();
10175 /* Clear the part of the screen image that are not covered by
10176 the image from the GIF file. Full animated GIF support
10177 requires more than can be done here (see the gif89 spec,
10178 disposal methods). Let's simply assume that the part
10179 not covered by a sub-image is in the frame's background color. */
10180 image_top = gif->SavedImages[ino].ImageDesc.Top;
10181 image_left = gif->SavedImages[ino].ImageDesc.Left;
10182 image_width = gif->SavedImages[ino].ImageDesc.Width;
10183 image_height = gif->SavedImages[ino].ImageDesc.Height;
10185 for (y = 0; y < image_top; ++y)
10186 for (x = 0; x < width; ++x)
10187 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10189 for (y = image_top + image_height; y < height; ++y)
10190 for (x = 0; x < width; ++x)
10191 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10193 for (y = image_top; y < image_top + image_height; ++y)
10195 for (x = 0; x < image_left; ++x)
10196 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10197 for (x = image_left + image_width; x < width; ++x)
10198 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
10201 /* Read the GIF image into the X image. We use a local variable
10202 `raster' here because RasterBits below is a char *, and invites
10203 problems with bytes >= 0x80. */
10204 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
10206 if (gif->SavedImages[ino].ImageDesc.Interlace)
10208 static int interlace_start[] = {0, 4, 2, 1};
10209 static int interlace_increment[] = {8, 8, 4, 2};
10210 int pass;
10211 int row = interlace_start[0];
10213 pass = 0;
10215 for (y = 0; y < image_height; y++)
10217 if (row >= image_height)
10219 row = interlace_start[++pass];
10220 while (row >= image_height)
10221 row = interlace_start[++pass];
10224 for (x = 0; x < image_width; x++)
10226 int i = raster[(y * image_width) + x];
10227 XPutPixel (ximg, x + image_left, row + image_top,
10228 pixel_colors[i]);
10231 row += interlace_increment[pass];
10234 else
10236 for (y = 0; y < image_height; ++y)
10237 for (x = 0; x < image_width; ++x)
10239 int i = raster[y * image_width + x];
10240 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
10244 DGifCloseFile (gif);
10246 /* Maybe fill in the background field while we have ximg handy. */
10247 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10248 IMAGE_BACKGROUND (img, f, ximg);
10250 /* Put the image into the pixmap, then free the X image and its buffer. */
10251 x_put_x_image (f, ximg, img->pixmap, width, height);
10252 x_destroy_x_image (ximg);
10254 UNGCPRO;
10255 return 1;
10258 #endif /* HAVE_GIF != 0 */
10262 /***********************************************************************
10263 Ghostscript
10264 ***********************************************************************/
10266 static int gs_image_p P_ ((Lisp_Object object));
10267 static int gs_load P_ ((struct frame *f, struct image *img));
10268 static void gs_clear_image P_ ((struct frame *f, struct image *img));
10270 /* The symbol `postscript' identifying images of this type. */
10272 Lisp_Object Qpostscript;
10274 /* Keyword symbols. */
10276 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
10278 /* Indices of image specification fields in gs_format, below. */
10280 enum gs_keyword_index
10282 GS_TYPE,
10283 GS_PT_WIDTH,
10284 GS_PT_HEIGHT,
10285 GS_FILE,
10286 GS_LOADER,
10287 GS_BOUNDING_BOX,
10288 GS_ASCENT,
10289 GS_MARGIN,
10290 GS_RELIEF,
10291 GS_ALGORITHM,
10292 GS_HEURISTIC_MASK,
10293 GS_MASK,
10294 GS_BACKGROUND,
10295 GS_LAST
10298 /* Vector of image_keyword structures describing the format
10299 of valid user-defined image specifications. */
10301 static struct image_keyword gs_format[GS_LAST] =
10303 {":type", IMAGE_SYMBOL_VALUE, 1},
10304 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10305 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
10306 {":file", IMAGE_STRING_VALUE, 1},
10307 {":loader", IMAGE_FUNCTION_VALUE, 0},
10308 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
10309 {":ascent", IMAGE_ASCENT_VALUE, 0},
10310 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10311 {":relief", IMAGE_INTEGER_VALUE, 0},
10312 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10313 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10314 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10315 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10318 /* Structure describing the image type `ghostscript'. */
10320 static struct image_type gs_type =
10322 &Qpostscript,
10323 gs_image_p,
10324 gs_load,
10325 gs_clear_image,
10326 NULL
10330 /* Free X resources of Ghostscript image IMG which is used on frame F. */
10332 static void
10333 gs_clear_image (f, img)
10334 struct frame *f;
10335 struct image *img;
10337 /* IMG->data.ptr_val may contain a recorded colormap. */
10338 xfree (img->data.ptr_val);
10339 x_clear_image (f, img);
10343 /* Return non-zero if OBJECT is a valid Ghostscript image
10344 specification. */
10346 static int
10347 gs_image_p (object)
10348 Lisp_Object object;
10350 struct image_keyword fmt[GS_LAST];
10351 Lisp_Object tem;
10352 int i;
10354 bcopy (gs_format, fmt, sizeof fmt);
10356 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
10357 return 0;
10359 /* Bounding box must be a list or vector containing 4 integers. */
10360 tem = fmt[GS_BOUNDING_BOX].value;
10361 if (CONSP (tem))
10363 for (i = 0; i < 4; ++i, tem = XCDR (tem))
10364 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
10365 return 0;
10366 if (!NILP (tem))
10367 return 0;
10369 else if (VECTORP (tem))
10371 if (XVECTOR (tem)->size != 4)
10372 return 0;
10373 for (i = 0; i < 4; ++i)
10374 if (!INTEGERP (XVECTOR (tem)->contents[i]))
10375 return 0;
10377 else
10378 return 0;
10380 return 1;
10384 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
10385 if successful. */
10387 static int
10388 gs_load (f, img)
10389 struct frame *f;
10390 struct image *img;
10392 char buffer[100];
10393 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
10394 struct gcpro gcpro1, gcpro2;
10395 Lisp_Object frame;
10396 double in_width, in_height;
10397 Lisp_Object pixel_colors = Qnil;
10399 /* Compute pixel size of pixmap needed from the given size in the
10400 image specification. Sizes in the specification are in pt. 1 pt
10401 = 1/72 in, xdpi and ydpi are stored in the frame's X display
10402 info. */
10403 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
10404 in_width = XFASTINT (pt_width) / 72.0;
10405 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
10406 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
10407 in_height = XFASTINT (pt_height) / 72.0;
10408 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
10410 /* Create the pixmap. */
10411 xassert (img->pixmap == None);
10412 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10413 img->width, img->height,
10414 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
10416 if (!img->pixmap)
10418 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
10419 return 0;
10422 /* Call the loader to fill the pixmap. It returns a process object
10423 if successful. We do not record_unwind_protect here because
10424 other places in redisplay like calling window scroll functions
10425 don't either. Let the Lisp loader use `unwind-protect' instead. */
10426 GCPRO2 (window_and_pixmap_id, pixel_colors);
10428 sprintf (buffer, "%lu %lu",
10429 (unsigned long) FRAME_X_WINDOW (f),
10430 (unsigned long) img->pixmap);
10431 window_and_pixmap_id = build_string (buffer);
10433 sprintf (buffer, "%lu %lu",
10434 FRAME_FOREGROUND_PIXEL (f),
10435 FRAME_BACKGROUND_PIXEL (f));
10436 pixel_colors = build_string (buffer);
10438 XSETFRAME (frame, f);
10439 loader = image_spec_value (img->spec, QCloader, NULL);
10440 if (NILP (loader))
10441 loader = intern ("gs-load-image");
10443 img->data.lisp_val = call6 (loader, frame, img->spec,
10444 make_number (img->width),
10445 make_number (img->height),
10446 window_and_pixmap_id,
10447 pixel_colors);
10448 UNGCPRO;
10449 return PROCESSP (img->data.lisp_val);
10453 /* Kill the Ghostscript process that was started to fill PIXMAP on
10454 frame F. Called from XTread_socket when receiving an event
10455 telling Emacs that Ghostscript has finished drawing. */
10457 void
10458 x_kill_gs_process (pixmap, f)
10459 Pixmap pixmap;
10460 struct frame *f;
10462 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
10463 int class, i;
10464 struct image *img;
10466 /* Find the image containing PIXMAP. */
10467 for (i = 0; i < c->used; ++i)
10468 if (c->images[i]->pixmap == pixmap)
10469 break;
10471 /* Should someone in between have cleared the image cache, for
10472 instance, give up. */
10473 if (i == c->used)
10474 return;
10476 /* Kill the GS process. We should have found PIXMAP in the image
10477 cache and its image should contain a process object. */
10478 img = c->images[i];
10479 xassert (PROCESSP (img->data.lisp_val));
10480 Fkill_process (img->data.lisp_val, Qnil);
10481 img->data.lisp_val = Qnil;
10483 /* On displays with a mutable colormap, figure out the colors
10484 allocated for the image by looking at the pixels of an XImage for
10485 img->pixmap. */
10486 class = FRAME_X_VISUAL (f)->class;
10487 if (class != StaticColor && class != StaticGray && class != TrueColor)
10489 XImage *ximg;
10491 BLOCK_INPUT;
10493 /* Try to get an XImage for img->pixmep. */
10494 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
10495 0, 0, img->width, img->height, ~0, ZPixmap);
10496 if (ximg)
10498 int x, y;
10500 /* Initialize the color table. */
10501 init_color_table ();
10503 /* For each pixel of the image, look its color up in the
10504 color table. After having done so, the color table will
10505 contain an entry for each color used by the image. */
10506 for (y = 0; y < img->height; ++y)
10507 for (x = 0; x < img->width; ++x)
10509 unsigned long pixel = XGetPixel (ximg, x, y);
10510 lookup_pixel_color (f, pixel);
10513 /* Record colors in the image. Free color table and XImage. */
10514 img->colors = colors_in_color_table (&img->ncolors);
10515 free_color_table ();
10516 XDestroyImage (ximg);
10518 #if 0 /* This doesn't seem to be the case. If we free the colors
10519 here, we get a BadAccess later in x_clear_image when
10520 freeing the colors. */
10521 /* We have allocated colors once, but Ghostscript has also
10522 allocated colors on behalf of us. So, to get the
10523 reference counts right, free them once. */
10524 if (img->ncolors)
10525 x_free_colors (f, img->colors, img->ncolors);
10526 #endif
10528 else
10529 image_error ("Cannot get X image of `%s'; colors will not be freed",
10530 img->spec, Qnil);
10532 UNBLOCK_INPUT;
10535 /* Now that we have the pixmap, compute mask and transform the
10536 image if requested. */
10537 BLOCK_INPUT;
10538 postprocess_image (f, img);
10539 UNBLOCK_INPUT;
10544 /***********************************************************************
10545 Window properties
10546 ***********************************************************************/
10548 DEFUN ("x-change-window-property", Fx_change_window_property,
10549 Sx_change_window_property, 2, 3, 0,
10550 doc: /* Change window property PROP to VALUE on the X window of FRAME.
10551 PROP and VALUE must be strings. FRAME nil or omitted means use the
10552 selected frame. Value is VALUE. */)
10553 (prop, value, frame)
10554 Lisp_Object frame, prop, value;
10556 struct frame *f = check_x_frame (frame);
10557 Atom prop_atom;
10559 CHECK_STRING (prop);
10560 CHECK_STRING (value);
10562 BLOCK_INPUT;
10563 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
10564 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10565 prop_atom, XA_STRING, 8, PropModeReplace,
10566 SDATA (value), SCHARS (value));
10568 /* Make sure the property is set when we return. */
10569 XFlush (FRAME_X_DISPLAY (f));
10570 UNBLOCK_INPUT;
10572 return value;
10576 DEFUN ("x-delete-window-property", Fx_delete_window_property,
10577 Sx_delete_window_property, 1, 2, 0,
10578 doc: /* Remove window property PROP from X window of FRAME.
10579 FRAME nil or omitted means use the selected frame. Value is PROP. */)
10580 (prop, frame)
10581 Lisp_Object prop, frame;
10583 struct frame *f = check_x_frame (frame);
10584 Atom prop_atom;
10586 CHECK_STRING (prop);
10587 BLOCK_INPUT;
10588 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
10589 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
10591 /* Make sure the property is removed when we return. */
10592 XFlush (FRAME_X_DISPLAY (f));
10593 UNBLOCK_INPUT;
10595 return prop;
10599 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
10600 1, 2, 0,
10601 doc: /* Value is the value of window property PROP on FRAME.
10602 If FRAME is nil or omitted, use the selected frame. Value is nil
10603 if FRAME hasn't a property with name PROP or if PROP has no string
10604 value. */)
10605 (prop, frame)
10606 Lisp_Object prop, frame;
10608 struct frame *f = check_x_frame (frame);
10609 Atom prop_atom;
10610 int rc;
10611 Lisp_Object prop_value = Qnil;
10612 char *tmp_data = NULL;
10613 Atom actual_type;
10614 int actual_format;
10615 unsigned long actual_size, bytes_remaining;
10617 CHECK_STRING (prop);
10618 BLOCK_INPUT;
10619 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
10620 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10621 prop_atom, 0, 0, False, XA_STRING,
10622 &actual_type, &actual_format, &actual_size,
10623 &bytes_remaining, (unsigned char **) &tmp_data);
10624 if (rc == Success)
10626 int size = bytes_remaining;
10628 XFree (tmp_data);
10629 tmp_data = NULL;
10631 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10632 prop_atom, 0, bytes_remaining,
10633 False, XA_STRING,
10634 &actual_type, &actual_format,
10635 &actual_size, &bytes_remaining,
10636 (unsigned char **) &tmp_data);
10637 if (rc == Success && tmp_data)
10638 prop_value = make_string (tmp_data, size);
10640 XFree (tmp_data);
10643 UNBLOCK_INPUT;
10644 return prop_value;
10649 /***********************************************************************
10650 Busy cursor
10651 ***********************************************************************/
10653 /* If non-null, an asynchronous timer that, when it expires, displays
10654 an hourglass cursor on all frames. */
10656 static struct atimer *hourglass_atimer;
10658 /* Non-zero means an hourglass cursor is currently shown. */
10660 static int hourglass_shown_p;
10662 /* Number of seconds to wait before displaying an hourglass cursor. */
10664 static Lisp_Object Vhourglass_delay;
10666 /* Default number of seconds to wait before displaying an hourglass
10667 cursor. */
10669 #define DEFAULT_HOURGLASS_DELAY 1
10671 /* Function prototypes. */
10673 static void show_hourglass P_ ((struct atimer *));
10674 static void hide_hourglass P_ ((void));
10677 /* Cancel a currently active hourglass timer, and start a new one. */
10679 void
10680 start_hourglass ()
10682 EMACS_TIME delay;
10683 int secs, usecs = 0;
10685 cancel_hourglass ();
10687 if (INTEGERP (Vhourglass_delay)
10688 && XINT (Vhourglass_delay) > 0)
10689 secs = XFASTINT (Vhourglass_delay);
10690 else if (FLOATP (Vhourglass_delay)
10691 && XFLOAT_DATA (Vhourglass_delay) > 0)
10693 Lisp_Object tem;
10694 tem = Ftruncate (Vhourglass_delay, Qnil);
10695 secs = XFASTINT (tem);
10696 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
10698 else
10699 secs = DEFAULT_HOURGLASS_DELAY;
10701 EMACS_SET_SECS_USECS (delay, secs, usecs);
10702 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
10703 show_hourglass, NULL);
10707 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
10708 shown. */
10710 void
10711 cancel_hourglass ()
10713 if (hourglass_atimer)
10715 cancel_atimer (hourglass_atimer);
10716 hourglass_atimer = NULL;
10719 if (hourglass_shown_p)
10720 hide_hourglass ();
10724 /* Timer function of hourglass_atimer. TIMER is equal to
10725 hourglass_atimer.
10727 Display an hourglass pointer on all frames by mapping the frames'
10728 hourglass_window. Set the hourglass_p flag in the frames'
10729 output_data.x structure to indicate that an hourglass cursor is
10730 shown on the frames. */
10732 static void
10733 show_hourglass (timer)
10734 struct atimer *timer;
10736 /* The timer implementation will cancel this timer automatically
10737 after this function has run. Set hourglass_atimer to null
10738 so that we know the timer doesn't have to be canceled. */
10739 hourglass_atimer = NULL;
10741 if (!hourglass_shown_p)
10743 Lisp_Object rest, frame;
10745 BLOCK_INPUT;
10747 FOR_EACH_FRAME (rest, frame)
10749 struct frame *f = XFRAME (frame);
10751 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
10753 Display *dpy = FRAME_X_DISPLAY (f);
10755 #ifdef USE_X_TOOLKIT
10756 if (f->output_data.x->widget)
10757 #else
10758 if (FRAME_OUTER_WINDOW (f))
10759 #endif
10761 f->output_data.x->hourglass_p = 1;
10763 if (!f->output_data.x->hourglass_window)
10765 unsigned long mask = CWCursor;
10766 XSetWindowAttributes attrs;
10768 attrs.cursor = f->output_data.x->hourglass_cursor;
10770 f->output_data.x->hourglass_window
10771 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
10772 0, 0, 32000, 32000, 0, 0,
10773 InputOnly,
10774 CopyFromParent,
10775 mask, &attrs);
10778 XMapRaised (dpy, f->output_data.x->hourglass_window);
10779 XFlush (dpy);
10784 hourglass_shown_p = 1;
10785 UNBLOCK_INPUT;
10790 /* Hide the hourglass pointer on all frames, if it is currently
10791 shown. */
10793 static void
10794 hide_hourglass ()
10796 if (hourglass_shown_p)
10798 Lisp_Object rest, frame;
10800 BLOCK_INPUT;
10801 FOR_EACH_FRAME (rest, frame)
10803 struct frame *f = XFRAME (frame);
10805 if (FRAME_X_P (f)
10806 /* Watch out for newly created frames. */
10807 && f->output_data.x->hourglass_window)
10809 XUnmapWindow (FRAME_X_DISPLAY (f),
10810 f->output_data.x->hourglass_window);
10811 /* Sync here because XTread_socket looks at the
10812 hourglass_p flag that is reset to zero below. */
10813 XSync (FRAME_X_DISPLAY (f), False);
10814 f->output_data.x->hourglass_p = 0;
10818 hourglass_shown_p = 0;
10819 UNBLOCK_INPUT;
10825 /***********************************************************************
10826 Tool tips
10827 ***********************************************************************/
10829 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10830 Lisp_Object, Lisp_Object));
10831 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
10832 Lisp_Object, int, int, int *, int *));
10834 /* The frame of a currently visible tooltip. */
10836 Lisp_Object tip_frame;
10838 /* If non-nil, a timer started that hides the last tooltip when it
10839 fires. */
10841 Lisp_Object tip_timer;
10842 Window tip_window;
10844 /* If non-nil, a vector of 3 elements containing the last args
10845 with which x-show-tip was called. See there. */
10847 Lisp_Object last_show_tip_args;
10849 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
10851 Lisp_Object Vx_max_tooltip_size;
10854 static Lisp_Object
10855 unwind_create_tip_frame (frame)
10856 Lisp_Object frame;
10858 Lisp_Object deleted;
10860 deleted = unwind_create_frame (frame);
10861 if (EQ (deleted, Qt))
10863 tip_window = None;
10864 tip_frame = Qnil;
10867 return deleted;
10871 /* Create a frame for a tooltip on the display described by DPYINFO.
10872 PARMS is a list of frame parameters. TEXT is the string to
10873 display in the tip frame. Value is the frame.
10875 Note that functions called here, esp. x_default_parameter can
10876 signal errors, for instance when a specified color name is
10877 undefined. We have to make sure that we're in a consistent state
10878 when this happens. */
10880 static Lisp_Object
10881 x_create_tip_frame (dpyinfo, parms, text)
10882 struct x_display_info *dpyinfo;
10883 Lisp_Object parms, text;
10885 struct frame *f;
10886 Lisp_Object frame, tem;
10887 Lisp_Object name;
10888 long window_prompting = 0;
10889 int width, height;
10890 int count = SPECPDL_INDEX ();
10891 struct gcpro gcpro1, gcpro2, gcpro3;
10892 struct kboard *kb;
10893 int face_change_count_before = face_change_count;
10894 Lisp_Object buffer;
10895 struct buffer *old_buffer;
10897 check_x ();
10899 /* Use this general default value to start with until we know if
10900 this frame has a specified name. */
10901 Vx_resource_name = Vinvocation_name;
10903 #ifdef MULTI_KBOARD
10904 kb = dpyinfo->kboard;
10905 #else
10906 kb = &the_only_kboard;
10907 #endif
10909 /* Get the name of the frame to use for resource lookup. */
10910 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10911 if (!STRINGP (name)
10912 && !EQ (name, Qunbound)
10913 && !NILP (name))
10914 error ("Invalid frame name--not a string or nil");
10915 Vx_resource_name = name;
10917 frame = Qnil;
10918 GCPRO3 (parms, name, frame);
10919 f = make_frame (1);
10920 XSETFRAME (frame, f);
10922 buffer = Fget_buffer_create (build_string (" *tip*"));
10923 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10924 old_buffer = current_buffer;
10925 set_buffer_internal_1 (XBUFFER (buffer));
10926 current_buffer->truncate_lines = Qnil;
10927 Ferase_buffer ();
10928 Finsert (1, &text);
10929 set_buffer_internal_1 (old_buffer);
10931 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10932 record_unwind_protect (unwind_create_tip_frame, frame);
10934 /* By setting the output method, we're essentially saying that
10935 the frame is live, as per FRAME_LIVE_P. If we get a signal
10936 from this point on, x_destroy_window might screw up reference
10937 counts etc. */
10938 f->output_method = output_x_window;
10939 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10940 bzero (f->output_data.x, sizeof (struct x_output));
10941 f->output_data.x->icon_bitmap = -1;
10942 f->output_data.x->fontset = -1;
10943 f->output_data.x->scroll_bar_foreground_pixel = -1;
10944 f->output_data.x->scroll_bar_background_pixel = -1;
10945 #ifdef USE_TOOLKIT_SCROLL_BARS
10946 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
10947 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
10948 #endif /* USE_TOOLKIT_SCROLL_BARS */
10949 f->icon_name = Qnil;
10950 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10951 #if GLYPH_DEBUG
10952 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
10953 dpyinfo_refcount = dpyinfo->reference_count;
10954 #endif /* GLYPH_DEBUG */
10955 #ifdef MULTI_KBOARD
10956 FRAME_KBOARD (f) = kb;
10957 #endif
10958 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10959 f->output_data.x->explicit_parent = 0;
10961 /* These colors will be set anyway later, but it's important
10962 to get the color reference counts right, so initialize them! */
10964 Lisp_Object black;
10965 struct gcpro gcpro1;
10967 black = build_string ("black");
10968 GCPRO1 (black);
10969 f->output_data.x->foreground_pixel
10970 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10971 f->output_data.x->background_pixel
10972 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10973 f->output_data.x->cursor_pixel
10974 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10975 f->output_data.x->cursor_foreground_pixel
10976 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10977 f->output_data.x->border_pixel
10978 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10979 f->output_data.x->mouse_pixel
10980 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10981 UNGCPRO;
10984 /* Set the name; the functions to which we pass f expect the name to
10985 be set. */
10986 if (EQ (name, Qunbound) || NILP (name))
10988 f->name = build_string (dpyinfo->x_id_name);
10989 f->explicit_name = 0;
10991 else
10993 f->name = name;
10994 f->explicit_name = 1;
10995 /* use the frame's title when getting resources for this frame. */
10996 specbind (Qx_resource_name, name);
10999 /* Extract the window parameters from the supplied values that are
11000 needed to determine window geometry. */
11002 Lisp_Object font;
11004 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
11006 BLOCK_INPUT;
11007 /* First, try whatever font the caller has specified. */
11008 if (STRINGP (font))
11010 tem = Fquery_fontset (font, Qnil);
11011 if (STRINGP (tem))
11012 font = x_new_fontset (f, SDATA (tem));
11013 else
11014 font = x_new_font (f, SDATA (font));
11017 /* Try out a font which we hope has bold and italic variations. */
11018 if (!STRINGP (font))
11019 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
11020 if (!STRINGP (font))
11021 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11022 if (! STRINGP (font))
11023 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
11024 if (! STRINGP (font))
11025 /* This was formerly the first thing tried, but it finds too many fonts
11026 and takes too long. */
11027 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
11028 /* If those didn't work, look for something which will at least work. */
11029 if (! STRINGP (font))
11030 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
11031 UNBLOCK_INPUT;
11032 if (! STRINGP (font))
11033 font = build_string ("fixed");
11035 x_default_parameter (f, parms, Qfont, font,
11036 "font", "Font", RES_TYPE_STRING);
11039 x_default_parameter (f, parms, Qborder_width, make_number (2),
11040 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
11042 /* This defaults to 2 in order to match xterm. We recognize either
11043 internalBorderWidth or internalBorder (which is what xterm calls
11044 it). */
11045 if (NILP (Fassq (Qinternal_border_width, parms)))
11047 Lisp_Object value;
11049 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
11050 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
11051 if (! EQ (value, Qunbound))
11052 parms = Fcons (Fcons (Qinternal_border_width, value),
11053 parms);
11056 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
11057 "internalBorderWidth", "internalBorderWidth",
11058 RES_TYPE_NUMBER);
11060 /* Also do the stuff which must be set before the window exists. */
11061 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
11062 "foreground", "Foreground", RES_TYPE_STRING);
11063 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
11064 "background", "Background", RES_TYPE_STRING);
11065 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
11066 "pointerColor", "Foreground", RES_TYPE_STRING);
11067 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
11068 "cursorColor", "Foreground", RES_TYPE_STRING);
11069 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
11070 "borderColor", "BorderColor", RES_TYPE_STRING);
11072 /* Init faces before x_default_parameter is called for scroll-bar
11073 parameters because that function calls x_set_scroll_bar_width,
11074 which calls change_frame_size, which calls Fset_window_buffer,
11075 which runs hooks, which call Fvertical_motion. At the end, we
11076 end up in init_iterator with a null face cache, which should not
11077 happen. */
11078 init_frame_faces (f);
11080 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
11081 window_prompting = x_figure_window_size (f, parms);
11083 if (window_prompting & XNegative)
11085 if (window_prompting & YNegative)
11086 f->output_data.x->win_gravity = SouthEastGravity;
11087 else
11088 f->output_data.x->win_gravity = NorthEastGravity;
11090 else
11092 if (window_prompting & YNegative)
11093 f->output_data.x->win_gravity = SouthWestGravity;
11094 else
11095 f->output_data.x->win_gravity = NorthWestGravity;
11098 f->output_data.x->size_hint_flags = window_prompting;
11100 XSetWindowAttributes attrs;
11101 unsigned long mask;
11103 BLOCK_INPUT;
11104 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
11105 if (DoesSaveUnders (dpyinfo->screen))
11106 mask |= CWSaveUnder;
11108 /* Window managers look at the override-redirect flag to determine
11109 whether or net to give windows a decoration (Xlib spec, chapter
11110 3.2.8). */
11111 attrs.override_redirect = True;
11112 attrs.save_under = True;
11113 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
11114 /* Arrange for getting MapNotify and UnmapNotify events. */
11115 attrs.event_mask = StructureNotifyMask;
11116 tip_window
11117 = FRAME_X_WINDOW (f)
11118 = XCreateWindow (FRAME_X_DISPLAY (f),
11119 FRAME_X_DISPLAY_INFO (f)->root_window,
11120 /* x, y, width, height */
11121 0, 0, 1, 1,
11122 /* Border. */
11124 CopyFromParent, InputOutput, CopyFromParent,
11125 mask, &attrs);
11126 UNBLOCK_INPUT;
11129 x_make_gc (f);
11131 x_default_parameter (f, parms, Qauto_raise, Qnil,
11132 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11133 x_default_parameter (f, parms, Qauto_lower, Qnil,
11134 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
11135 x_default_parameter (f, parms, Qcursor_type, Qbox,
11136 "cursorType", "CursorType", RES_TYPE_SYMBOL);
11138 /* Dimensions, especially f->height, must be done via change_frame_size.
11139 Change will not be effected unless different from the current
11140 f->height. */
11141 width = f->width;
11142 height = f->height;
11143 f->height = 0;
11144 SET_FRAME_WIDTH (f, 0);
11145 change_frame_size (f, height, width, 1, 0, 0);
11147 /* Add `tooltip' frame parameter's default value. */
11148 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
11149 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
11150 Qnil));
11152 /* Set up faces after all frame parameters are known. This call
11153 also merges in face attributes specified for new frames.
11155 Frame parameters may be changed if .Xdefaults contains
11156 specifications for the default font. For example, if there is an
11157 `Emacs.default.attributeBackground: pink', the `background-color'
11158 attribute of the frame get's set, which let's the internal border
11159 of the tooltip frame appear in pink. Prevent this. */
11161 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
11163 /* Set tip_frame here, so that */
11164 tip_frame = frame;
11165 call1 (Qface_set_after_frame_default, frame);
11167 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
11168 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
11169 Qnil));
11172 f->no_split = 1;
11174 UNGCPRO;
11176 /* It is now ok to make the frame official even if we get an error
11177 below. And the frame needs to be on Vframe_list or making it
11178 visible won't work. */
11179 Vframe_list = Fcons (frame, Vframe_list);
11181 /* Now that the frame is official, it counts as a reference to
11182 its display. */
11183 FRAME_X_DISPLAY_INFO (f)->reference_count++;
11185 /* Setting attributes of faces of the tooltip frame from resources
11186 and similar will increment face_change_count, which leads to the
11187 clearing of all current matrices. Since this isn't necessary
11188 here, avoid it by resetting face_change_count to the value it
11189 had before we created the tip frame. */
11190 face_change_count = face_change_count_before;
11192 /* Discard the unwind_protect. */
11193 return unbind_to (count, frame);
11197 /* Compute where to display tip frame F. PARMS is the list of frame
11198 parameters for F. DX and DY are specified offsets from the current
11199 location of the mouse. WIDTH and HEIGHT are the width and height
11200 of the tooltip. Return coordinates relative to the root window of
11201 the display in *ROOT_X, and *ROOT_Y. */
11203 static void
11204 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
11205 struct frame *f;
11206 Lisp_Object parms, dx, dy;
11207 int width, height;
11208 int *root_x, *root_y;
11210 Lisp_Object left, top;
11211 int win_x, win_y;
11212 Window root, child;
11213 unsigned pmask;
11215 /* User-specified position? */
11216 left = Fcdr (Fassq (Qleft, parms));
11217 top = Fcdr (Fassq (Qtop, parms));
11219 /* Move the tooltip window where the mouse pointer is. Resize and
11220 show it. */
11221 if (!INTEGERP (left) || !INTEGERP (top))
11223 BLOCK_INPUT;
11224 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
11225 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
11226 UNBLOCK_INPUT;
11229 if (INTEGERP (top))
11230 *root_y = XINT (top);
11231 else if (*root_y + XINT (dy) - height < 0)
11232 *root_y -= XINT (dy);
11233 else
11235 *root_y -= height;
11236 *root_y += XINT (dy);
11239 if (INTEGERP (left))
11240 *root_x = XINT (left);
11241 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
11242 /* It fits to the right of the pointer. */
11243 *root_x += XINT (dx);
11244 else if (width + XINT (dx) <= *root_x)
11245 /* It fits to the left of the pointer. */
11246 *root_x -= width + XINT (dx);
11247 else
11248 /* Put it left-justified on the screen--it ought to fit that way. */
11249 *root_x = 0;
11253 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
11254 doc: /* Show STRING in a "tooltip" window on frame FRAME.
11255 A tooltip window is a small X window displaying a string.
11257 FRAME nil or omitted means use the selected frame.
11259 PARMS is an optional list of frame parameters which can be used to
11260 change the tooltip's appearance.
11262 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
11263 means use the default timeout of 5 seconds.
11265 If the list of frame parameters PARAMS contains a `left' parameters,
11266 the tooltip is displayed at that x-position. Otherwise it is
11267 displayed at the mouse position, with offset DX added (default is 5 if
11268 DX isn't specified). Likewise for the y-position; if a `top' frame
11269 parameter is specified, it determines the y-position of the tooltip
11270 window, otherwise it is displayed at the mouse position, with offset
11271 DY added (default is -10).
11273 A tooltip's maximum size is specified by `x-max-tooltip-size'.
11274 Text larger than the specified size is clipped. */)
11275 (string, frame, parms, timeout, dx, dy)
11276 Lisp_Object string, frame, parms, timeout, dx, dy;
11278 struct frame *f;
11279 struct window *w;
11280 int root_x, root_y;
11281 struct buffer *old_buffer;
11282 struct text_pos pos;
11283 int i, width, height;
11284 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
11285 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11286 int count = SPECPDL_INDEX ();
11288 specbind (Qinhibit_redisplay, Qt);
11290 GCPRO4 (string, parms, frame, timeout);
11292 CHECK_STRING (string);
11293 f = check_x_frame (frame);
11294 if (NILP (timeout))
11295 timeout = make_number (5);
11296 else
11297 CHECK_NATNUM (timeout);
11299 if (NILP (dx))
11300 dx = make_number (5);
11301 else
11302 CHECK_NUMBER (dx);
11304 if (NILP (dy))
11305 dy = make_number (-10);
11306 else
11307 CHECK_NUMBER (dy);
11309 if (NILP (last_show_tip_args))
11310 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
11312 if (!NILP (tip_frame))
11314 Lisp_Object last_string = AREF (last_show_tip_args, 0);
11315 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
11316 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
11318 if (EQ (frame, last_frame)
11319 && !NILP (Fequal (last_string, string))
11320 && !NILP (Fequal (last_parms, parms)))
11322 struct frame *f = XFRAME (tip_frame);
11324 /* Only DX and DY have changed. */
11325 if (!NILP (tip_timer))
11327 Lisp_Object timer = tip_timer;
11328 tip_timer = Qnil;
11329 call1 (Qcancel_timer, timer);
11332 BLOCK_INPUT;
11333 compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
11334 PIXEL_HEIGHT (f), &root_x, &root_y);
11335 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11336 root_x, root_y);
11337 UNBLOCK_INPUT;
11338 goto start_timer;
11342 /* Hide a previous tip, if any. */
11343 Fx_hide_tip ();
11345 ASET (last_show_tip_args, 0, string);
11346 ASET (last_show_tip_args, 1, frame);
11347 ASET (last_show_tip_args, 2, parms);
11349 /* Add default values to frame parameters. */
11350 if (NILP (Fassq (Qname, parms)))
11351 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
11352 if (NILP (Fassq (Qinternal_border_width, parms)))
11353 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
11354 if (NILP (Fassq (Qborder_width, parms)))
11355 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
11356 if (NILP (Fassq (Qborder_color, parms)))
11357 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
11358 if (NILP (Fassq (Qbackground_color, parms)))
11359 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
11360 parms);
11362 /* Create a frame for the tooltip, and record it in the global
11363 variable tip_frame. */
11364 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
11365 f = XFRAME (frame);
11367 /* Set up the frame's root window. */
11368 w = XWINDOW (FRAME_ROOT_WINDOW (f));
11369 w->left = w->top = make_number (0);
11371 if (CONSP (Vx_max_tooltip_size)
11372 && INTEGERP (XCAR (Vx_max_tooltip_size))
11373 && XINT (XCAR (Vx_max_tooltip_size)) > 0
11374 && INTEGERP (XCDR (Vx_max_tooltip_size))
11375 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
11377 w->width = XCAR (Vx_max_tooltip_size);
11378 w->height = XCDR (Vx_max_tooltip_size);
11380 else
11382 w->width = make_number (80);
11383 w->height = make_number (40);
11386 f->window_width = XINT (w->width);
11387 adjust_glyphs (f);
11388 w->pseudo_window_p = 1;
11390 /* Display the tooltip text in a temporary buffer. */
11391 old_buffer = current_buffer;
11392 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
11393 current_buffer->truncate_lines = Qnil;
11394 clear_glyph_matrix (w->desired_matrix);
11395 clear_glyph_matrix (w->current_matrix);
11396 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
11397 try_window (FRAME_ROOT_WINDOW (f), pos);
11399 /* Compute width and height of the tooltip. */
11400 width = height = 0;
11401 for (i = 0; i < w->desired_matrix->nrows; ++i)
11403 struct glyph_row *row = &w->desired_matrix->rows[i];
11404 struct glyph *last;
11405 int row_width;
11407 /* Stop at the first empty row at the end. */
11408 if (!row->enabled_p || !row->displays_text_p)
11409 break;
11411 /* Let the row go over the full width of the frame. */
11412 row->full_width_p = 1;
11414 /* There's a glyph at the end of rows that is used to place
11415 the cursor there. Don't include the width of this glyph. */
11416 if (row->used[TEXT_AREA])
11418 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
11419 row_width = row->pixel_width - last->pixel_width;
11421 else
11422 row_width = row->pixel_width;
11424 height += row->height;
11425 width = max (width, row_width);
11428 /* Add the frame's internal border to the width and height the X
11429 window should have. */
11430 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11431 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
11433 /* Move the tooltip window where the mouse pointer is. Resize and
11434 show it. */
11435 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
11437 BLOCK_INPUT;
11438 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11439 root_x, root_y, width, height);
11440 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11441 UNBLOCK_INPUT;
11443 /* Draw into the window. */
11444 w->must_be_updated_p = 1;
11445 update_single_window (w, 1);
11447 /* Restore original current buffer. */
11448 set_buffer_internal_1 (old_buffer);
11449 windows_or_buffers_changed = old_windows_or_buffers_changed;
11451 start_timer:
11452 /* Let the tip disappear after timeout seconds. */
11453 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
11454 intern ("x-hide-tip"));
11456 UNGCPRO;
11457 return unbind_to (count, Qnil);
11461 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
11462 doc: /* Hide the current tooltip window, if there is any.
11463 Value is t if tooltip was open, nil otherwise. */)
11466 int count;
11467 Lisp_Object deleted, frame, timer;
11468 struct gcpro gcpro1, gcpro2;
11470 /* Return quickly if nothing to do. */
11471 if (NILP (tip_timer) && NILP (tip_frame))
11472 return Qnil;
11474 frame = tip_frame;
11475 timer = tip_timer;
11476 GCPRO2 (frame, timer);
11477 tip_frame = tip_timer = deleted = Qnil;
11479 count = SPECPDL_INDEX ();
11480 specbind (Qinhibit_redisplay, Qt);
11481 specbind (Qinhibit_quit, Qt);
11483 if (!NILP (timer))
11484 call1 (Qcancel_timer, timer);
11486 if (FRAMEP (frame))
11488 Fdelete_frame (frame, Qnil);
11489 deleted = Qt;
11491 #ifdef USE_LUCID
11492 /* Bloodcurdling hack alert: The Lucid menu bar widget's
11493 redisplay procedure is not called when a tip frame over menu
11494 items is unmapped. Redisplay the menu manually... */
11496 struct frame *f = SELECTED_FRAME ();
11497 Widget w = f->output_data.x->menubar_widget;
11498 extern void xlwmenu_redisplay P_ ((Widget));
11500 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
11501 && w != NULL)
11503 BLOCK_INPUT;
11504 xlwmenu_redisplay (w);
11505 UNBLOCK_INPUT;
11508 #endif /* USE_LUCID */
11511 UNGCPRO;
11512 return unbind_to (count, deleted);
11517 /***********************************************************************
11518 File selection dialog
11519 ***********************************************************************/
11521 #ifdef USE_MOTIF
11523 /* Callback for "OK" and "Cancel" on file selection dialog. */
11525 static void
11526 file_dialog_cb (widget, client_data, call_data)
11527 Widget widget;
11528 XtPointer call_data, client_data;
11530 int *result = (int *) client_data;
11531 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
11532 *result = cb->reason;
11536 /* Callback for unmapping a file selection dialog. This is used to
11537 capture the case where a dialog is closed via a window manager's
11538 closer button, for example. Using a XmNdestroyCallback didn't work
11539 in this case. */
11541 static void
11542 file_dialog_unmap_cb (widget, client_data, call_data)
11543 Widget widget;
11544 XtPointer call_data, client_data;
11546 int *result = (int *) client_data;
11547 *result = XmCR_CANCEL;
11551 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
11552 doc: /* Read file name, prompting with PROMPT in directory DIR.
11553 Use a file selection dialog.
11554 Select DEFAULT-FILENAME in the dialog's file selection box, if
11555 specified. Don't let the user enter a file name in the file
11556 selection dialog's entry field, if MUSTMATCH is non-nil. */)
11557 (prompt, dir, default_filename, mustmatch)
11558 Lisp_Object prompt, dir, default_filename, mustmatch;
11560 int result;
11561 struct frame *f = SELECTED_FRAME ();
11562 Lisp_Object file = Qnil;
11563 Widget dialog, text, list, help;
11564 Arg al[10];
11565 int ac = 0;
11566 extern XtAppContext Xt_app_con;
11567 XmString dir_xmstring, pattern_xmstring;
11568 int count = SPECPDL_INDEX ();
11569 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
11571 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
11572 CHECK_STRING (prompt);
11573 CHECK_STRING (dir);
11575 /* Prevent redisplay. */
11576 specbind (Qinhibit_redisplay, Qt);
11578 BLOCK_INPUT;
11580 /* Create the dialog with PROMPT as title, using DIR as initial
11581 directory and using "*" as pattern. */
11582 dir = Fexpand_file_name (dir, Qnil);
11583 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
11584 pattern_xmstring = XmStringCreateLocalized ("*");
11586 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
11587 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
11588 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
11589 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
11590 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
11591 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
11592 "fsb", al, ac);
11593 XmStringFree (dir_xmstring);
11594 XmStringFree (pattern_xmstring);
11596 /* Add callbacks for OK and Cancel. */
11597 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
11598 (XtPointer) &result);
11599 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
11600 (XtPointer) &result);
11601 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
11602 (XtPointer) &result);
11604 /* Disable the help button since we can't display help. */
11605 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
11606 XtSetSensitive (help, False);
11608 /* Mark OK button as default. */
11609 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
11610 XmNshowAsDefault, True, NULL);
11612 /* If MUSTMATCH is non-nil, disable the file entry field of the
11613 dialog, so that the user must select a file from the files list
11614 box. We can't remove it because we wouldn't have a way to get at
11615 the result file name, then. */
11616 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
11617 if (!NILP (mustmatch))
11619 Widget label;
11620 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
11621 XtSetSensitive (text, False);
11622 XtSetSensitive (label, False);
11625 /* Manage the dialog, so that list boxes get filled. */
11626 XtManageChild (dialog);
11628 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
11629 must include the path for this to work. */
11630 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
11631 if (STRINGP (default_filename))
11633 XmString default_xmstring;
11634 int item_pos;
11636 default_xmstring
11637 = XmStringCreateLocalized (SDATA (default_filename));
11639 if (!XmListItemExists (list, default_xmstring))
11641 /* Add a new item if DEFAULT_FILENAME is not in the list. */
11642 XmListAddItem (list, default_xmstring, 0);
11643 item_pos = 0;
11645 else
11646 item_pos = XmListItemPos (list, default_xmstring);
11647 XmStringFree (default_xmstring);
11649 /* Select the item and scroll it into view. */
11650 XmListSelectPos (list, item_pos, True);
11651 XmListSetPos (list, item_pos);
11654 /* Process events until the user presses Cancel or OK. Block
11655 and unblock input here so that we get a chance of processing
11656 expose events. */
11657 UNBLOCK_INPUT;
11658 result = 0;
11659 while (result == 0)
11661 BLOCK_INPUT;
11662 XtAppProcessEvent (Xt_app_con, XtIMAll);
11663 UNBLOCK_INPUT;
11665 BLOCK_INPUT;
11667 /* Get the result. */
11668 if (result == XmCR_OK)
11670 XmString text;
11671 String data;
11673 XtVaGetValues (dialog, XmNtextString, &text, NULL);
11674 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
11675 XmStringFree (text);
11676 file = build_string (data);
11677 XtFree (data);
11679 else
11680 file = Qnil;
11682 /* Clean up. */
11683 XtUnmanageChild (dialog);
11684 XtDestroyWidget (dialog);
11685 UNBLOCK_INPUT;
11686 UNGCPRO;
11688 /* Make "Cancel" equivalent to C-g. */
11689 if (NILP (file))
11690 Fsignal (Qquit, Qnil);
11692 return unbind_to (count, file);
11695 #endif /* USE_MOTIF */
11699 /***********************************************************************
11700 Keyboard
11701 ***********************************************************************/
11703 #ifdef HAVE_XKBGETKEYBOARD
11704 #include <X11/XKBlib.h>
11705 #include <X11/keysym.h>
11706 #endif
11708 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
11709 Sx_backspace_delete_keys_p, 0, 1, 0,
11710 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
11711 FRAME nil means use the selected frame.
11712 Value is t if we know that both keys are present, and are mapped to the
11713 usual X keysyms. */)
11714 (frame)
11715 Lisp_Object frame;
11717 #ifdef HAVE_XKBGETKEYBOARD
11718 XkbDescPtr kb;
11719 struct frame *f = check_x_frame (frame);
11720 Display *dpy = FRAME_X_DISPLAY (f);
11721 Lisp_Object have_keys;
11722 int major, minor, op, event, error;
11724 BLOCK_INPUT;
11726 /* Check library version in case we're dynamically linked. */
11727 major = XkbMajorVersion;
11728 minor = XkbMinorVersion;
11729 if (!XkbLibraryVersion (&major, &minor))
11731 UNBLOCK_INPUT;
11732 return Qnil;
11735 /* Check that the server supports XKB. */
11736 major = XkbMajorVersion;
11737 minor = XkbMinorVersion;
11738 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
11740 UNBLOCK_INPUT;
11741 return Qnil;
11744 have_keys = Qnil;
11745 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
11746 if (kb)
11748 int delete_keycode = 0, backspace_keycode = 0, i;
11750 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
11752 for (i = kb->min_key_code;
11753 (i < kb->max_key_code
11754 && (delete_keycode == 0 || backspace_keycode == 0));
11755 ++i)
11757 /* The XKB symbolic key names can be seen most easily in
11758 the PS file generated by `xkbprint -label name
11759 $DISPLAY'. */
11760 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
11761 delete_keycode = i;
11762 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
11763 backspace_keycode = i;
11766 XkbFreeNames (kb, 0, True);
11769 XkbFreeClientMap (kb, 0, True);
11771 if (delete_keycode
11772 && backspace_keycode
11773 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
11774 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
11775 have_keys = Qt;
11777 UNBLOCK_INPUT;
11778 return have_keys;
11779 #else /* not HAVE_XKBGETKEYBOARD */
11780 return Qnil;
11781 #endif /* not HAVE_XKBGETKEYBOARD */
11786 /***********************************************************************
11787 Initialization
11788 ***********************************************************************/
11790 void
11791 syms_of_xfns ()
11793 /* This is zero if not using X windows. */
11794 x_in_use = 0;
11796 /* The section below is built by the lisp expression at the top of the file,
11797 just above where these variables are declared. */
11798 /*&&& init symbols here &&&*/
11799 Qauto_raise = intern ("auto-raise");
11800 staticpro (&Qauto_raise);
11801 Qauto_lower = intern ("auto-lower");
11802 staticpro (&Qauto_lower);
11803 Qborder_color = intern ("border-color");
11804 staticpro (&Qborder_color);
11805 Qborder_width = intern ("border-width");
11806 staticpro (&Qborder_width);
11807 Qcursor_color = intern ("cursor-color");
11808 staticpro (&Qcursor_color);
11809 Qcursor_type = intern ("cursor-type");
11810 staticpro (&Qcursor_type);
11811 Qgeometry = intern ("geometry");
11812 staticpro (&Qgeometry);
11813 Qicon_left = intern ("icon-left");
11814 staticpro (&Qicon_left);
11815 Qicon_top = intern ("icon-top");
11816 staticpro (&Qicon_top);
11817 Qicon_type = intern ("icon-type");
11818 staticpro (&Qicon_type);
11819 Qicon_name = intern ("icon-name");
11820 staticpro (&Qicon_name);
11821 Qinternal_border_width = intern ("internal-border-width");
11822 staticpro (&Qinternal_border_width);
11823 Qleft = intern ("left");
11824 staticpro (&Qleft);
11825 Qright = intern ("right");
11826 staticpro (&Qright);
11827 Qmouse_color = intern ("mouse-color");
11828 staticpro (&Qmouse_color);
11829 Qnone = intern ("none");
11830 staticpro (&Qnone);
11831 Qparent_id = intern ("parent-id");
11832 staticpro (&Qparent_id);
11833 Qscroll_bar_width = intern ("scroll-bar-width");
11834 staticpro (&Qscroll_bar_width);
11835 Qsuppress_icon = intern ("suppress-icon");
11836 staticpro (&Qsuppress_icon);
11837 Qundefined_color = intern ("undefined-color");
11838 staticpro (&Qundefined_color);
11839 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
11840 staticpro (&Qvertical_scroll_bars);
11841 Qvisibility = intern ("visibility");
11842 staticpro (&Qvisibility);
11843 Qwindow_id = intern ("window-id");
11844 staticpro (&Qwindow_id);
11845 Qouter_window_id = intern ("outer-window-id");
11846 staticpro (&Qouter_window_id);
11847 Qx_frame_parameter = intern ("x-frame-parameter");
11848 staticpro (&Qx_frame_parameter);
11849 Qx_resource_name = intern ("x-resource-name");
11850 staticpro (&Qx_resource_name);
11851 Quser_position = intern ("user-position");
11852 staticpro (&Quser_position);
11853 Quser_size = intern ("user-size");
11854 staticpro (&Quser_size);
11855 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
11856 staticpro (&Qscroll_bar_foreground);
11857 Qscroll_bar_background = intern ("scroll-bar-background");
11858 staticpro (&Qscroll_bar_background);
11859 Qscreen_gamma = intern ("screen-gamma");
11860 staticpro (&Qscreen_gamma);
11861 Qline_spacing = intern ("line-spacing");
11862 staticpro (&Qline_spacing);
11863 Qcenter = intern ("center");
11864 staticpro (&Qcenter);
11865 Qcompound_text = intern ("compound-text");
11866 staticpro (&Qcompound_text);
11867 Qcancel_timer = intern ("cancel-timer");
11868 staticpro (&Qcancel_timer);
11869 Qwait_for_wm = intern ("wait-for-wm");
11870 staticpro (&Qwait_for_wm);
11871 Qfullscreen = intern ("fullscreen");
11872 staticpro (&Qfullscreen);
11873 Qfullwidth = intern ("fullwidth");
11874 staticpro (&Qfullwidth);
11875 Qfullheight = intern ("fullheight");
11876 staticpro (&Qfullheight);
11877 Qfullboth = intern ("fullboth");
11878 staticpro (&Qfullboth);
11879 /* This is the end of symbol initialization. */
11881 /* Text property `display' should be nonsticky by default. */
11882 Vtext_property_default_nonsticky
11883 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
11886 Qlaplace = intern ("laplace");
11887 staticpro (&Qlaplace);
11888 Qemboss = intern ("emboss");
11889 staticpro (&Qemboss);
11890 Qedge_detection = intern ("edge-detection");
11891 staticpro (&Qedge_detection);
11892 Qheuristic = intern ("heuristic");
11893 staticpro (&Qheuristic);
11894 QCmatrix = intern (":matrix");
11895 staticpro (&QCmatrix);
11896 QCcolor_adjustment = intern (":color-adjustment");
11897 staticpro (&QCcolor_adjustment);
11898 QCmask = intern (":mask");
11899 staticpro (&QCmask);
11901 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
11902 staticpro (&Qface_set_after_frame_default);
11904 Fput (Qundefined_color, Qerror_conditions,
11905 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
11906 Fput (Qundefined_color, Qerror_message,
11907 build_string ("Undefined color"));
11909 init_x_parm_symbols ();
11911 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
11912 doc: /* Non-nil means always draw a cross over disabled images.
11913 Disabled images are those having an `:conversion disabled' property.
11914 A cross is always drawn on black & white displays. */);
11915 cross_disabled_images = 0;
11917 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11918 doc: /* List of directories to search for bitmap files for X. */);
11919 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11921 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11922 doc: /* The shape of the pointer when over text.
11923 Changing the value does not affect existing frames
11924 unless you set the mouse color. */);
11925 Vx_pointer_shape = Qnil;
11927 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11928 doc: /* The name Emacs uses to look up X resources.
11929 `x-get-resource' uses this as the first component of the instance name
11930 when requesting resource values.
11931 Emacs initially sets `x-resource-name' to the name under which Emacs
11932 was invoked, or to the value specified with the `-name' or `-rn'
11933 switches, if present.
11935 It may be useful to bind this variable locally around a call
11936 to `x-get-resource'. See also the variable `x-resource-class'. */);
11937 Vx_resource_name = Qnil;
11939 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11940 doc: /* The class Emacs uses to look up X resources.
11941 `x-get-resource' uses this as the first component of the instance class
11942 when requesting resource values.
11944 Emacs initially sets `x-resource-class' to "Emacs".
11946 Setting this variable permanently is not a reasonable thing to do,
11947 but binding this variable locally around a call to `x-get-resource'
11948 is a reasonable practice. See also the variable `x-resource-name'. */);
11949 Vx_resource_class = build_string (EMACS_CLASS);
11951 #if 0 /* This doesn't really do anything. */
11952 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11953 doc: /* The shape of the pointer when not over text.
11954 This variable takes effect when you create a new frame
11955 or when you set the mouse color. */);
11956 #endif
11957 Vx_nontext_pointer_shape = Qnil;
11959 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
11960 doc: /* The shape of the pointer when Emacs is busy.
11961 This variable takes effect when you create a new frame
11962 or when you set the mouse color. */);
11963 Vx_hourglass_pointer_shape = Qnil;
11965 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
11966 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
11967 display_hourglass_p = 1;
11969 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
11970 doc: /* *Seconds to wait before displaying an hourglass pointer.
11971 Value must be an integer or float. */);
11972 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
11974 #if 0 /* This doesn't really do anything. */
11975 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11976 doc: /* The shape of the pointer when over the mode line.
11977 This variable takes effect when you create a new frame
11978 or when you set the mouse color. */);
11979 #endif
11980 Vx_mode_pointer_shape = Qnil;
11982 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11983 &Vx_sensitive_text_pointer_shape,
11984 doc: /* The shape of the pointer when over mouse-sensitive text.
11985 This variable takes effect when you create a new frame
11986 or when you set the mouse color. */);
11987 Vx_sensitive_text_pointer_shape = Qnil;
11989 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
11990 &Vx_window_horizontal_drag_shape,
11991 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
11992 This variable takes effect when you create a new frame
11993 or when you set the mouse color. */);
11994 Vx_window_horizontal_drag_shape = Qnil;
11996 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11997 doc: /* A string indicating the foreground color of the cursor box. */);
11998 Vx_cursor_fore_pixel = Qnil;
12000 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
12001 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
12002 Text larger than this is clipped. */);
12003 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
12005 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
12006 doc: /* Non-nil if no X window manager is in use.
12007 Emacs doesn't try to figure this out; this is always nil
12008 unless you set it to something else. */);
12009 /* We don't have any way to find this out, so set it to nil
12010 and maybe the user would like to set it to t. */
12011 Vx_no_window_manager = Qnil;
12013 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
12014 &Vx_pixel_size_width_font_regexp,
12015 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
12017 Since Emacs gets width of a font matching with this regexp from
12018 PIXEL_SIZE field of the name, font finding mechanism gets faster for
12019 such a font. This is especially effective for such large fonts as
12020 Chinese, Japanese, and Korean. */);
12021 Vx_pixel_size_width_font_regexp = Qnil;
12023 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
12024 doc: /* Time after which cached images are removed from the cache.
12025 When an image has not been displayed this many seconds, remove it
12026 from the image cache. Value must be an integer or nil with nil
12027 meaning don't clear the cache. */);
12028 Vimage_cache_eviction_delay = make_number (30 * 60);
12030 #ifdef USE_X_TOOLKIT
12031 Fprovide (intern ("x-toolkit"), Qnil);
12032 #ifdef USE_MOTIF
12033 Fprovide (intern ("motif"), Qnil);
12035 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
12036 doc: /* Version info for LessTif/Motif. */);
12037 Vmotif_version_string = build_string (XmVERSION_STRING);
12038 #endif /* USE_MOTIF */
12039 #endif /* USE_X_TOOLKIT */
12041 defsubr (&Sx_get_resource);
12043 /* X window properties. */
12044 defsubr (&Sx_change_window_property);
12045 defsubr (&Sx_delete_window_property);
12046 defsubr (&Sx_window_property);
12048 defsubr (&Sxw_display_color_p);
12049 defsubr (&Sx_display_grayscale_p);
12050 defsubr (&Sxw_color_defined_p);
12051 defsubr (&Sxw_color_values);
12052 defsubr (&Sx_server_max_request_size);
12053 defsubr (&Sx_server_vendor);
12054 defsubr (&Sx_server_version);
12055 defsubr (&Sx_display_pixel_width);
12056 defsubr (&Sx_display_pixel_height);
12057 defsubr (&Sx_display_mm_width);
12058 defsubr (&Sx_display_mm_height);
12059 defsubr (&Sx_display_screens);
12060 defsubr (&Sx_display_planes);
12061 defsubr (&Sx_display_color_cells);
12062 defsubr (&Sx_display_visual_class);
12063 defsubr (&Sx_display_backing_store);
12064 defsubr (&Sx_display_save_under);
12065 defsubr (&Sx_parse_geometry);
12066 defsubr (&Sx_create_frame);
12067 defsubr (&Sx_open_connection);
12068 defsubr (&Sx_close_connection);
12069 defsubr (&Sx_display_list);
12070 defsubr (&Sx_synchronize);
12071 defsubr (&Sx_focus_frame);
12072 defsubr (&Sx_backspace_delete_keys_p);
12074 /* Setting callback functions for fontset handler. */
12075 get_font_info_func = x_get_font_info;
12077 #if 0 /* This function pointer doesn't seem to be used anywhere.
12078 And the pointer assigned has the wrong type, anyway. */
12079 list_fonts_func = x_list_fonts;
12080 #endif
12082 load_font_func = x_load_font;
12083 find_ccl_program_func = x_find_ccl_program;
12084 query_font_func = x_query_font;
12085 set_frame_fontset_func = x_set_font;
12086 check_window_system_func = check_x;
12088 /* Images. */
12089 Qxbm = intern ("xbm");
12090 staticpro (&Qxbm);
12091 QCconversion = intern (":conversion");
12092 staticpro (&QCconversion);
12093 QCheuristic_mask = intern (":heuristic-mask");
12094 staticpro (&QCheuristic_mask);
12095 QCcolor_symbols = intern (":color-symbols");
12096 staticpro (&QCcolor_symbols);
12097 QCascent = intern (":ascent");
12098 staticpro (&QCascent);
12099 QCmargin = intern (":margin");
12100 staticpro (&QCmargin);
12101 QCrelief = intern (":relief");
12102 staticpro (&QCrelief);
12103 Qpostscript = intern ("postscript");
12104 staticpro (&Qpostscript);
12105 QCloader = intern (":loader");
12106 staticpro (&QCloader);
12107 QCbounding_box = intern (":bounding-box");
12108 staticpro (&QCbounding_box);
12109 QCpt_width = intern (":pt-width");
12110 staticpro (&QCpt_width);
12111 QCpt_height = intern (":pt-height");
12112 staticpro (&QCpt_height);
12113 QCindex = intern (":index");
12114 staticpro (&QCindex);
12115 Qpbm = intern ("pbm");
12116 staticpro (&Qpbm);
12118 #if HAVE_XPM
12119 Qxpm = intern ("xpm");
12120 staticpro (&Qxpm);
12121 #endif
12123 #if HAVE_JPEG
12124 Qjpeg = intern ("jpeg");
12125 staticpro (&Qjpeg);
12126 #endif
12128 #if HAVE_TIFF
12129 Qtiff = intern ("tiff");
12130 staticpro (&Qtiff);
12131 #endif
12133 #if HAVE_GIF
12134 Qgif = intern ("gif");
12135 staticpro (&Qgif);
12136 #endif
12138 #if HAVE_PNG
12139 Qpng = intern ("png");
12140 staticpro (&Qpng);
12141 #endif
12143 defsubr (&Sclear_image_cache);
12144 defsubr (&Simage_size);
12145 defsubr (&Simage_mask_p);
12147 hourglass_atimer = NULL;
12148 hourglass_shown_p = 0;
12150 defsubr (&Sx_show_tip);
12151 defsubr (&Sx_hide_tip);
12152 tip_timer = Qnil;
12153 staticpro (&tip_timer);
12154 tip_frame = Qnil;
12155 staticpro (&tip_frame);
12157 last_show_tip_args = Qnil;
12158 staticpro (&last_show_tip_args);
12160 #ifdef USE_MOTIF
12161 defsubr (&Sx_file_dialog);
12162 #endif
12166 void
12167 init_xfns ()
12169 image_types = NULL;
12170 Vimage_types = Qnil;
12172 define_image_type (&xbm_type);
12173 define_image_type (&gs_type);
12174 define_image_type (&pbm_type);
12176 #if HAVE_XPM
12177 define_image_type (&xpm_type);
12178 #endif
12180 #if HAVE_JPEG
12181 define_image_type (&jpeg_type);
12182 #endif
12184 #if HAVE_TIFF
12185 define_image_type (&tiff_type);
12186 #endif
12188 #if HAVE_GIF
12189 define_image_type (&gif_type);
12190 #endif
12192 #if HAVE_PNG
12193 define_image_type (&png_type);
12194 #endif
12197 #endif /* HAVE_X_WINDOWS */