Describe bibtex.el changes. From Roland Winkler.
[emacs.git] / src / xfns.c
blobac36b8c0ef28626aa347a206d6b4a68dd89154b4
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02, 03
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_GTK
69 #include "gtkutil.h"
70 #endif
72 #ifdef USE_X_TOOLKIT
73 #include <X11/Shell.h>
75 #ifndef USE_MOTIF
76 #include <X11/Xaw/Paned.h>
77 #include <X11/Xaw/Label.h>
78 #endif /* USE_MOTIF */
80 #ifdef USG
81 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
82 #include <X11/Xos.h>
83 #define USG
84 #else
85 #include <X11/Xos.h>
86 #endif
88 #include "widget.h"
90 #include "../lwlib/lwlib.h"
92 #ifdef USE_MOTIF
93 #include <Xm/Xm.h>
94 #include <Xm/DialogS.h>
95 #include <Xm/FileSB.h>
96 #endif
98 /* Do the EDITRES protocol if running X11R5
99 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
101 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
102 #define HACK_EDITRES
103 extern void _XEditResCheckMessages ();
104 #endif /* R5 + Athena */
106 /* Unique id counter for widgets created by the Lucid Widget Library. */
108 extern LWLIB_ID widget_id_tick;
110 #ifdef USE_LUCID
111 /* This is part of a kludge--see lwlib/xlwmenu.c. */
112 extern XFontStruct *xlwmenu_default_font;
113 #endif
115 extern void free_frame_menubar ();
116 extern double atof ();
118 #ifdef USE_MOTIF
120 /* LessTif/Motif version info. */
122 static Lisp_Object Vmotif_version_string;
124 #endif /* USE_MOTIF */
126 #endif /* USE_X_TOOLKIT */
128 #ifdef HAVE_X11R4
129 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
130 #else
131 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
132 #endif
134 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
135 it, and including `bitmaps/gray' more than once is a problem when
136 config.h defines `static' as an empty replacement string. */
138 int gray_bitmap_width = gray_width;
139 int gray_bitmap_height = gray_height;
140 char *gray_bitmap_bits = gray_bits;
142 /* Non-zero means we're allowed to display an hourglass cursor. */
144 int display_hourglass_p;
146 /* The background and shape of the mouse pointer, and shape when not
147 over text or in the modeline. */
149 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
150 Lisp_Object Vx_hourglass_pointer_shape;
152 /* The shape when over mouse-sensitive text. */
154 Lisp_Object Vx_sensitive_text_pointer_shape;
156 /* If non-nil, the pointer shape to indicate that windows can be
157 dragged horizontally. */
159 Lisp_Object Vx_window_horizontal_drag_shape;
161 /* Color of chars displayed in cursor box. */
163 Lisp_Object Vx_cursor_fore_pixel;
165 /* Nonzero if using X. */
167 static int x_in_use;
169 /* Non nil if no window manager is in use. */
171 Lisp_Object Vx_no_window_manager;
173 /* Search path for bitmap files. */
175 Lisp_Object Vx_bitmap_file_path;
177 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
179 Lisp_Object Vx_pixel_size_width_font_regexp;
181 Lisp_Object Qnone;
182 Lisp_Object Qsuppress_icon;
183 Lisp_Object Qundefined_color;
184 Lisp_Object Qcenter;
185 Lisp_Object Qcompound_text, Qcancel_timer;
187 /* In dispnew.c */
189 extern Lisp_Object Vwindow_system_version;
191 /* The below are defined in frame.c. */
193 #if GLYPH_DEBUG
194 int image_cache_refcount, dpyinfo_refcount;
195 #endif
199 /* Error if we are not connected to X. */
201 void
202 check_x ()
204 if (! x_in_use)
205 error ("X windows are not in use or not initialized");
208 /* Nonzero if we can use mouse menus.
209 You should not call this unless HAVE_MENUS is defined. */
212 have_menus_p ()
214 return x_in_use;
217 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
218 and checking validity for X. */
220 FRAME_PTR
221 check_x_frame (frame)
222 Lisp_Object frame;
224 FRAME_PTR f;
226 if (NILP (frame))
227 frame = selected_frame;
228 CHECK_LIVE_FRAME (frame);
229 f = XFRAME (frame);
230 if (! FRAME_X_P (f))
231 error ("Non-X frame used");
232 return f;
235 /* Let the user specify an X display with a frame.
236 nil stands for the selected frame--or, if that is not an X frame,
237 the first X display on the list. */
239 struct x_display_info *
240 check_x_display_info (frame)
241 Lisp_Object frame;
243 struct x_display_info *dpyinfo = NULL;
245 if (NILP (frame))
247 struct frame *sf = XFRAME (selected_frame);
249 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
250 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
251 else if (x_display_list != 0)
252 dpyinfo = x_display_list;
253 else
254 error ("X windows are not in use or not initialized");
256 else if (STRINGP (frame))
257 dpyinfo = x_display_info_for_name (frame);
258 else
260 FRAME_PTR f = check_x_frame (frame);
261 dpyinfo = FRAME_X_DISPLAY_INFO (f);
264 return dpyinfo;
268 /* Return the Emacs frame-object corresponding to an X window.
269 It could be the frame's main window or an icon window. */
271 /* This function can be called during GC, so use GC_xxx type test macros. */
273 struct frame *
274 x_window_to_frame (dpyinfo, wdesc)
275 struct x_display_info *dpyinfo;
276 int wdesc;
278 Lisp_Object tail, frame;
279 struct frame *f;
281 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
283 frame = XCAR (tail);
284 if (!GC_FRAMEP (frame))
285 continue;
286 f = XFRAME (frame);
287 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
288 continue;
289 if (f->output_data.x->hourglass_window == wdesc)
290 return f;
291 #ifdef USE_X_TOOLKIT
292 if ((f->output_data.x->edit_widget
293 && XtWindow (f->output_data.x->edit_widget) == wdesc)
294 /* A tooltip frame? */
295 || (!f->output_data.x->edit_widget
296 && FRAME_X_WINDOW (f) == wdesc)
297 || f->output_data.x->icon_desc == wdesc)
298 return f;
299 #else /* not USE_X_TOOLKIT */
300 #ifdef USE_GTK
301 if (f->output_data.x->edit_widget)
303 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
304 struct x_output *x = f->output_data.x;
305 if (gwdesc != 0 && gwdesc == x->edit_widget)
306 return f;
308 #endif /* USE_GTK */
309 if (FRAME_X_WINDOW (f) == wdesc
310 || f->output_data.x->icon_desc == wdesc)
311 return f;
312 #endif /* not USE_X_TOOLKIT */
314 return 0;
317 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
318 /* Like x_window_to_frame but also compares the window with the widget's
319 windows. */
321 struct frame *
322 x_any_window_to_frame (dpyinfo, wdesc)
323 struct x_display_info *dpyinfo;
324 int wdesc;
326 Lisp_Object tail, frame;
327 struct frame *f, *found;
328 struct x_output *x;
330 found = NULL;
331 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
333 frame = XCAR (tail);
334 if (!GC_FRAMEP (frame))
335 continue;
337 f = XFRAME (frame);
338 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
340 /* This frame matches if the window is any of its widgets. */
341 x = f->output_data.x;
342 if (x->hourglass_window == wdesc)
343 found = f;
344 else if (x->widget)
346 #ifdef USE_GTK
347 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
348 if (gwdesc != 0
349 && (gwdesc == x->widget
350 || gwdesc == x->edit_widget
351 || gwdesc == x->vbox_widget
352 || gwdesc == x->menubar_widget))
353 found = f;
354 #else
355 if (wdesc == XtWindow (x->widget)
356 || wdesc == XtWindow (x->column_widget)
357 || wdesc == XtWindow (x->edit_widget))
358 found = f;
359 /* Match if the window is this frame's menubar. */
360 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
361 found = f;
362 #endif
364 else if (FRAME_X_WINDOW (f) == wdesc)
365 /* A tooltip frame. */
366 found = f;
370 return found;
373 /* Likewise, but exclude the menu bar widget. */
375 struct frame *
376 x_non_menubar_window_to_frame (dpyinfo, wdesc)
377 struct x_display_info *dpyinfo;
378 int wdesc;
380 Lisp_Object tail, frame;
381 struct frame *f;
382 struct x_output *x;
384 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
386 frame = XCAR (tail);
387 if (!GC_FRAMEP (frame))
388 continue;
389 f = XFRAME (frame);
390 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
391 continue;
392 x = f->output_data.x;
393 /* This frame matches if the window is any of its widgets. */
394 if (x->hourglass_window == wdesc)
395 return f;
396 else if (x->widget)
398 #ifdef USE_GTK
399 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
400 if (gwdesc != 0
401 && (gwdesc == x->widget
402 || gwdesc == x->edit_widget
403 || gwdesc == x->vbox_widget))
404 return f;
405 #else
406 if (wdesc == XtWindow (x->widget)
407 || wdesc == XtWindow (x->column_widget)
408 || wdesc == XtWindow (x->edit_widget))
409 return f;
410 #endif
412 else if (FRAME_X_WINDOW (f) == wdesc)
413 /* A tooltip frame. */
414 return f;
416 return 0;
419 /* Likewise, but consider only the menu bar widget. */
421 struct frame *
422 x_menubar_window_to_frame (dpyinfo, wdesc)
423 struct x_display_info *dpyinfo;
424 int wdesc;
426 Lisp_Object tail, frame;
427 struct frame *f;
428 struct x_output *x;
430 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
432 frame = XCAR (tail);
433 if (!GC_FRAMEP (frame))
434 continue;
435 f = XFRAME (frame);
436 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
437 continue;
438 x = f->output_data.x;
439 /* Match if the window is this frame's menubar. */
440 #ifdef USE_GTK
441 if (x->menubar_widget)
443 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
444 int found = 0;
446 BLOCK_INPUT;
447 if (gwdesc != 0
448 && (gwdesc == x->menubar_widget
449 || gtk_widget_get_parent (gwdesc) == x->menubar_widget))
450 found = 1;
451 UNBLOCK_INPUT;
452 if (found) return f;
454 #else
455 if (x->menubar_widget
456 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
457 return f;
458 #endif
460 return 0;
463 /* Return the frame whose principal (outermost) window is WDESC.
464 If WDESC is some other (smaller) window, we return 0. */
466 struct frame *
467 x_top_window_to_frame (dpyinfo, wdesc)
468 struct x_display_info *dpyinfo;
469 int wdesc;
471 Lisp_Object tail, frame;
472 struct frame *f;
473 struct x_output *x;
475 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
477 frame = XCAR (tail);
478 if (!GC_FRAMEP (frame))
479 continue;
480 f = XFRAME (frame);
481 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
482 continue;
483 x = f->output_data.x;
485 if (x->widget)
487 /* This frame matches if the window is its topmost widget. */
488 #ifdef USE_GTK
489 GtkWidget *gwdesc = xg_win_to_widget (wdesc);
490 if (gwdesc == x->widget)
491 return f;
492 #else
493 if (wdesc == XtWindow (x->widget))
494 return f;
495 #if 0 /* I don't know why it did this,
496 but it seems logically wrong,
497 and it causes trouble for MapNotify events. */
498 /* Match if the window is this frame's menubar. */
499 if (x->menubar_widget
500 && wdesc == XtWindow (x->menubar_widget))
501 return f;
502 #endif
503 #endif
505 else if (FRAME_X_WINDOW (f) == wdesc)
506 /* Tooltip frame. */
507 return f;
509 return 0;
511 #endif /* USE_X_TOOLKIT || USE_GTK */
515 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
516 id, which is just an int that this section returns. Bitmaps are
517 reference counted so they can be shared among frames.
519 Bitmap indices are guaranteed to be > 0, so a negative number can
520 be used to indicate no bitmap.
522 If you use x_create_bitmap_from_data, then you must keep track of
523 the bitmaps yourself. That is, creating a bitmap from the same
524 data more than once will not be caught. */
527 /* Functions to access the contents of a bitmap, given an id. */
530 x_bitmap_height (f, id)
531 FRAME_PTR f;
532 int id;
534 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
538 x_bitmap_width (f, id)
539 FRAME_PTR f;
540 int id;
542 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
546 x_bitmap_pixmap (f, id)
547 FRAME_PTR f;
548 int id;
550 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
554 /* Allocate a new bitmap record. Returns index of new record. */
556 static int
557 x_allocate_bitmap_record (f)
558 FRAME_PTR f;
560 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
561 int i;
563 if (dpyinfo->bitmaps == NULL)
565 dpyinfo->bitmaps_size = 10;
566 dpyinfo->bitmaps
567 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
568 dpyinfo->bitmaps_last = 1;
569 return 1;
572 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
573 return ++dpyinfo->bitmaps_last;
575 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
576 if (dpyinfo->bitmaps[i].refcount == 0)
577 return i + 1;
579 dpyinfo->bitmaps_size *= 2;
580 dpyinfo->bitmaps
581 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
582 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
583 return ++dpyinfo->bitmaps_last;
586 /* Add one reference to the reference count of the bitmap with id ID. */
588 void
589 x_reference_bitmap (f, id)
590 FRAME_PTR f;
591 int id;
593 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
596 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
599 x_create_bitmap_from_data (f, bits, width, height)
600 struct frame *f;
601 char *bits;
602 unsigned int width, height;
604 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
605 Pixmap bitmap;
606 int id;
608 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
609 bits, width, height);
613 if (! bitmap)
614 return -1;
616 id = x_allocate_bitmap_record (f);
617 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
618 dpyinfo->bitmaps[id - 1].file = NULL;
619 dpyinfo->bitmaps[id - 1].refcount = 1;
620 dpyinfo->bitmaps[id - 1].depth = 1;
621 dpyinfo->bitmaps[id - 1].height = height;
622 dpyinfo->bitmaps[id - 1].width = width;
624 return id;
627 /* Create bitmap from file FILE for frame F. */
630 x_create_bitmap_from_file (f, file)
631 struct frame *f;
632 Lisp_Object file;
634 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
635 unsigned int width, height;
636 Pixmap bitmap;
637 int xhot, yhot, result, id;
638 Lisp_Object found;
639 int fd;
640 char *filename;
642 /* Look for an existing bitmap with the same name. */
643 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
645 if (dpyinfo->bitmaps[id].refcount
646 && dpyinfo->bitmaps[id].file
647 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
649 ++dpyinfo->bitmaps[id].refcount;
650 return id + 1;
654 /* Search bitmap-file-path for the file, if appropriate. */
655 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
656 if (fd < 0)
657 return -1;
658 emacs_close (fd);
660 filename = (char *) SDATA (found);
662 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
663 filename, &width, &height, &bitmap, &xhot, &yhot);
664 if (result != BitmapSuccess)
665 return -1;
667 id = x_allocate_bitmap_record (f);
668 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
669 dpyinfo->bitmaps[id - 1].refcount = 1;
670 dpyinfo->bitmaps[id - 1].file
671 = (char *) xmalloc (SBYTES (file) + 1);
672 dpyinfo->bitmaps[id - 1].depth = 1;
673 dpyinfo->bitmaps[id - 1].height = height;
674 dpyinfo->bitmaps[id - 1].width = width;
675 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
677 return id;
680 /* Remove reference to bitmap with id number ID. */
682 void
683 x_destroy_bitmap (f, id)
684 FRAME_PTR f;
685 int id;
687 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
689 if (id > 0)
691 --dpyinfo->bitmaps[id - 1].refcount;
692 if (dpyinfo->bitmaps[id - 1].refcount == 0)
694 BLOCK_INPUT;
695 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
696 if (dpyinfo->bitmaps[id - 1].file)
698 xfree (dpyinfo->bitmaps[id - 1].file);
699 dpyinfo->bitmaps[id - 1].file = NULL;
701 UNBLOCK_INPUT;
706 /* Free all the bitmaps for the display specified by DPYINFO. */
708 static void
709 x_destroy_all_bitmaps (dpyinfo)
710 struct x_display_info *dpyinfo;
712 int i;
713 for (i = 0; i < dpyinfo->bitmaps_last; i++)
714 if (dpyinfo->bitmaps[i].refcount > 0)
716 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
717 if (dpyinfo->bitmaps[i].file)
718 xfree (dpyinfo->bitmaps[i].file);
720 dpyinfo->bitmaps_last = 0;
724 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
725 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
726 static void x_disable_image P_ ((struct frame *, struct image *));
728 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
729 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
730 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
731 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
732 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
733 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
734 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
735 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
736 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
737 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
738 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
739 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
740 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
741 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
742 Lisp_Object));
743 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
744 Lisp_Object));
745 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
746 Lisp_Object,
747 Lisp_Object,
748 char *, char *,
749 int));
750 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
751 Lisp_Object));
752 static void init_color_table P_ ((void));
753 static void free_color_table P_ ((void));
754 static unsigned long *colors_in_color_table P_ ((int *n));
755 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
756 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
762 /* Store the screen positions of frame F into XPTR and YPTR.
763 These are the positions of the containing window manager window,
764 not Emacs's own window. */
766 void
767 x_real_positions (f, xptr, yptr)
768 FRAME_PTR f;
769 int *xptr, *yptr;
771 int win_x, win_y, outer_x, outer_y;
772 int real_x = 0, real_y = 0;
773 int had_errors = 0;
774 Window win = f->output_data.x->parent_desc;
776 int count;
778 BLOCK_INPUT;
780 count = x_catch_errors (FRAME_X_DISPLAY (f));
782 if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
783 win = FRAME_OUTER_WINDOW (f);
785 /* This loop traverses up the containment tree until we hit the root
786 window. Window managers may intersect many windows between our window
787 and the root window. The window we find just before the root window
788 should be the outer WM window. */
789 for (;;)
791 Window wm_window, rootw;
792 Window *tmp_children;
793 unsigned int tmp_nchildren;
794 int success;
796 success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
797 &wm_window, &tmp_children, &tmp_nchildren);
799 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
801 /* Don't free tmp_children if XQueryTree failed. */
802 if (! success)
803 break;
805 XFree ((char *) tmp_children);
807 if (wm_window == rootw || had_errors)
808 break;
810 win = wm_window;
813 if (! had_errors)
815 int ign;
816 Window child, rootw;
818 /* Get the real coordinates for the WM window upper left corner */
819 XGetGeometry (FRAME_X_DISPLAY (f), win,
820 &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
822 /* Translate real coordinates to coordinates relative to our
823 window. For our window, the upper left corner is 0, 0.
824 Since the upper left corner of the WM window is outside
825 our window, win_x and win_y will be negative:
827 ------------------ ---> x
828 | title |
829 | ----------------- v y
830 | | our window
832 XTranslateCoordinates (FRAME_X_DISPLAY (f),
834 /* From-window, to-window. */
835 FRAME_X_DISPLAY_INFO (f)->root_window,
836 FRAME_X_WINDOW (f),
838 /* From-position, to-position. */
839 real_x, real_y, &win_x, &win_y,
841 /* Child of win. */
842 &child);
844 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
846 outer_x = win_x;
847 outer_y = win_y;
849 else
851 XTranslateCoordinates (FRAME_X_DISPLAY (f),
853 /* From-window, to-window. */
854 FRAME_X_DISPLAY_INFO (f)->root_window,
855 FRAME_OUTER_WINDOW (f),
857 /* From-position, to-position. */
858 real_x, real_y, &outer_x, &outer_y,
860 /* Child of win. */
861 &child);
864 had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
867 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
869 UNBLOCK_INPUT;
871 if (had_errors) return;
873 f->x_pixels_diff = -win_x;
874 f->y_pixels_diff = -win_y;
876 FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
877 FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
879 *xptr = real_x;
880 *yptr = real_y;
886 /* Gamma-correct COLOR on frame F. */
888 void
889 gamma_correct (f, color)
890 struct frame *f;
891 XColor *color;
893 if (f->gamma)
895 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
896 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
897 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
902 /* Decide if color named COLOR_NAME is valid for use on frame F. If
903 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
904 allocate the color. Value is zero if COLOR_NAME is invalid, or
905 no color could be allocated. */
908 x_defined_color (f, color_name, color, alloc_p)
909 struct frame *f;
910 char *color_name;
911 XColor *color;
912 int alloc_p;
914 int success_p;
915 Display *dpy = FRAME_X_DISPLAY (f);
916 Colormap cmap = FRAME_X_COLORMAP (f);
918 BLOCK_INPUT;
919 success_p = XParseColor (dpy, cmap, color_name, color);
920 if (success_p && alloc_p)
921 success_p = x_alloc_nearest_color (f, cmap, color);
922 UNBLOCK_INPUT;
924 return success_p;
928 /* Return the pixel color value for color COLOR_NAME on frame F. If F
929 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
930 Signal an error if color can't be allocated. */
933 x_decode_color (f, color_name, mono_color)
934 FRAME_PTR f;
935 Lisp_Object color_name;
936 int mono_color;
938 XColor cdef;
940 CHECK_STRING (color_name);
942 #if 0 /* Don't do this. It's wrong when we're not using the default
943 colormap, it makes freeing difficult, and it's probably not
944 an important optimization. */
945 if (strcmp (SDATA (color_name), "black") == 0)
946 return BLACK_PIX_DEFAULT (f);
947 else if (strcmp (SDATA (color_name), "white") == 0)
948 return WHITE_PIX_DEFAULT (f);
949 #endif
951 /* Return MONO_COLOR for monochrome frames. */
952 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
953 return mono_color;
955 /* x_defined_color is responsible for coping with failures
956 by looking for a near-miss. */
957 if (x_defined_color (f, SDATA (color_name), &cdef, 1))
958 return cdef.pixel;
960 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
961 Fcons (color_name, Qnil)));
962 return 0;
967 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
968 the previous value of that parameter, NEW_VALUE is the new value.
969 See also the comment of wait_for_wm in struct x_output. */
971 static void
972 x_set_wait_for_wm (f, new_value, old_value)
973 struct frame *f;
974 Lisp_Object new_value, old_value;
976 f->output_data.x->wait_for_wm = !NILP (new_value);
980 /* Functions called only from `x_set_frame_param'
981 to set individual parameters.
983 If FRAME_X_WINDOW (f) is 0,
984 the frame is being created and its X-window does not exist yet.
985 In that case, just record the parameter's new value
986 in the standard place; do not attempt to change the window. */
988 void
989 x_set_foreground_color (f, arg, oldval)
990 struct frame *f;
991 Lisp_Object arg, oldval;
993 struct x_output *x = f->output_data.x;
994 unsigned long fg, old_fg;
996 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
997 old_fg = x->foreground_pixel;
998 x->foreground_pixel = fg;
1000 if (FRAME_X_WINDOW (f) != 0)
1002 Display *dpy = FRAME_X_DISPLAY (f);
1004 BLOCK_INPUT;
1005 XSetForeground (dpy, x->normal_gc, fg);
1006 XSetBackground (dpy, x->reverse_gc, fg);
1008 if (x->cursor_pixel == old_fg)
1010 unload_color (f, x->cursor_pixel);
1011 x->cursor_pixel = x_copy_color (f, fg);
1012 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1015 UNBLOCK_INPUT;
1017 update_face_from_frame_parameter (f, Qforeground_color, arg);
1019 if (FRAME_VISIBLE_P (f))
1020 redraw_frame (f);
1023 unload_color (f, old_fg);
1026 void
1027 x_set_background_color (f, arg, oldval)
1028 struct frame *f;
1029 Lisp_Object arg, oldval;
1031 struct x_output *x = f->output_data.x;
1032 unsigned long bg;
1034 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1035 unload_color (f, x->background_pixel);
1036 x->background_pixel = bg;
1038 if (FRAME_X_WINDOW (f) != 0)
1040 Display *dpy = FRAME_X_DISPLAY (f);
1042 BLOCK_INPUT;
1043 XSetBackground (dpy, x->normal_gc, bg);
1044 XSetForeground (dpy, x->reverse_gc, bg);
1045 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1046 XSetForeground (dpy, x->cursor_gc, bg);
1048 #ifdef USE_GTK
1049 xg_set_background_color (f, bg);
1050 #endif
1052 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1053 toolkit scroll bars. */
1055 Lisp_Object bar;
1056 for (bar = FRAME_SCROLL_BARS (f);
1057 !NILP (bar);
1058 bar = XSCROLL_BAR (bar)->next)
1060 Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
1061 XSetWindowBackground (dpy, window, bg);
1064 #endif /* USE_TOOLKIT_SCROLL_BARS */
1066 UNBLOCK_INPUT;
1067 update_face_from_frame_parameter (f, Qbackground_color, arg);
1069 if (FRAME_VISIBLE_P (f))
1070 redraw_frame (f);
1074 void
1075 x_set_mouse_color (f, arg, oldval)
1076 struct frame *f;
1077 Lisp_Object arg, oldval;
1079 struct x_output *x = f->output_data.x;
1080 Display *dpy = FRAME_X_DISPLAY (f);
1081 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1082 Cursor hourglass_cursor, horizontal_drag_cursor;
1083 int count;
1084 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1085 unsigned long mask_color = x->background_pixel;
1087 /* Don't let pointers be invisible. */
1088 if (mask_color == pixel)
1090 x_free_colors (f, &pixel, 1);
1091 pixel = x_copy_color (f, x->foreground_pixel);
1094 unload_color (f, x->mouse_pixel);
1095 x->mouse_pixel = pixel;
1097 BLOCK_INPUT;
1099 /* It's not okay to crash if the user selects a screwy cursor. */
1100 count = x_catch_errors (dpy);
1102 if (!NILP (Vx_pointer_shape))
1104 CHECK_NUMBER (Vx_pointer_shape);
1105 cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
1107 else
1108 cursor = XCreateFontCursor (dpy, XC_xterm);
1109 x_check_errors (dpy, "bad text pointer cursor: %s");
1111 if (!NILP (Vx_nontext_pointer_shape))
1113 CHECK_NUMBER (Vx_nontext_pointer_shape);
1114 nontext_cursor
1115 = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
1117 else
1118 nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1119 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1121 if (!NILP (Vx_hourglass_pointer_shape))
1123 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1124 hourglass_cursor
1125 = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
1127 else
1128 hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
1129 x_check_errors (dpy, "bad hourglass pointer cursor: %s");
1131 x_check_errors (dpy, "bad nontext pointer cursor: %s");
1132 if (!NILP (Vx_mode_pointer_shape))
1134 CHECK_NUMBER (Vx_mode_pointer_shape);
1135 mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
1137 else
1138 mode_cursor = XCreateFontCursor (dpy, XC_xterm);
1139 x_check_errors (dpy, "bad modeline pointer cursor: %s");
1141 if (!NILP (Vx_sensitive_text_pointer_shape))
1143 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1144 hand_cursor
1145 = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
1147 else
1148 hand_cursor = XCreateFontCursor (dpy, XC_hand2);
1150 if (!NILP (Vx_window_horizontal_drag_shape))
1152 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1153 horizontal_drag_cursor
1154 = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
1156 else
1157 horizontal_drag_cursor
1158 = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
1160 /* Check and report errors with the above calls. */
1161 x_check_errors (dpy, "can't set cursor shape: %s");
1162 x_uncatch_errors (dpy, count);
1165 XColor fore_color, back_color;
1167 fore_color.pixel = x->mouse_pixel;
1168 x_query_color (f, &fore_color);
1169 back_color.pixel = mask_color;
1170 x_query_color (f, &back_color);
1172 XRecolorCursor (dpy, cursor, &fore_color, &back_color);
1173 XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
1174 XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
1175 XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
1176 XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
1177 XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
1180 if (FRAME_X_WINDOW (f) != 0)
1181 XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
1183 if (cursor != x->text_cursor
1184 && x->text_cursor != 0)
1185 XFreeCursor (dpy, x->text_cursor);
1186 x->text_cursor = cursor;
1188 if (nontext_cursor != x->nontext_cursor
1189 && x->nontext_cursor != 0)
1190 XFreeCursor (dpy, x->nontext_cursor);
1191 x->nontext_cursor = nontext_cursor;
1193 if (hourglass_cursor != x->hourglass_cursor
1194 && x->hourglass_cursor != 0)
1195 XFreeCursor (dpy, x->hourglass_cursor);
1196 x->hourglass_cursor = hourglass_cursor;
1198 if (mode_cursor != x->modeline_cursor
1199 && x->modeline_cursor != 0)
1200 XFreeCursor (dpy, f->output_data.x->modeline_cursor);
1201 x->modeline_cursor = mode_cursor;
1203 if (hand_cursor != x->hand_cursor
1204 && x->hand_cursor != 0)
1205 XFreeCursor (dpy, x->hand_cursor);
1206 x->hand_cursor = hand_cursor;
1208 if (horizontal_drag_cursor != x->horizontal_drag_cursor
1209 && x->horizontal_drag_cursor != 0)
1210 XFreeCursor (dpy, x->horizontal_drag_cursor);
1211 x->horizontal_drag_cursor = horizontal_drag_cursor;
1213 XFlush (dpy);
1214 UNBLOCK_INPUT;
1216 update_face_from_frame_parameter (f, Qmouse_color, arg);
1219 void
1220 x_set_cursor_color (f, arg, oldval)
1221 struct frame *f;
1222 Lisp_Object arg, oldval;
1224 unsigned long fore_pixel, pixel;
1225 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1226 struct x_output *x = f->output_data.x;
1228 if (!NILP (Vx_cursor_fore_pixel))
1230 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1231 WHITE_PIX_DEFAULT (f));
1232 fore_pixel_allocated_p = 1;
1234 else
1235 fore_pixel = x->background_pixel;
1237 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1238 pixel_allocated_p = 1;
1240 /* Make sure that the cursor color differs from the background color. */
1241 if (pixel == x->background_pixel)
1243 if (pixel_allocated_p)
1245 x_free_colors (f, &pixel, 1);
1246 pixel_allocated_p = 0;
1249 pixel = x->mouse_pixel;
1250 if (pixel == fore_pixel)
1252 if (fore_pixel_allocated_p)
1254 x_free_colors (f, &fore_pixel, 1);
1255 fore_pixel_allocated_p = 0;
1257 fore_pixel = x->background_pixel;
1261 unload_color (f, x->cursor_foreground_pixel);
1262 if (!fore_pixel_allocated_p)
1263 fore_pixel = x_copy_color (f, fore_pixel);
1264 x->cursor_foreground_pixel = fore_pixel;
1266 unload_color (f, x->cursor_pixel);
1267 if (!pixel_allocated_p)
1268 pixel = x_copy_color (f, pixel);
1269 x->cursor_pixel = pixel;
1271 if (FRAME_X_WINDOW (f) != 0)
1273 BLOCK_INPUT;
1274 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1275 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1276 UNBLOCK_INPUT;
1278 if (FRAME_VISIBLE_P (f))
1280 x_update_cursor (f, 0);
1281 x_update_cursor (f, 1);
1285 update_face_from_frame_parameter (f, Qcursor_color, arg);
1288 /* Set the border-color of frame F to pixel value PIX.
1289 Note that this does not fully take effect if done before
1290 F has an x-window. */
1292 void
1293 x_set_border_pixel (f, pix)
1294 struct frame *f;
1295 int pix;
1297 unload_color (f, f->output_data.x->border_pixel);
1298 f->output_data.x->border_pixel = pix;
1300 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1302 BLOCK_INPUT;
1303 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1304 (unsigned long)pix);
1305 UNBLOCK_INPUT;
1307 if (FRAME_VISIBLE_P (f))
1308 redraw_frame (f);
1312 /* Set the border-color of frame F to value described by ARG.
1313 ARG can be a string naming a color.
1314 The border-color is used for the border that is drawn by the X server.
1315 Note that this does not fully take effect if done before
1316 F has an x-window; it must be redone when the window is created.
1318 Note: this is done in two routines because of the way X10 works.
1320 Note: under X11, this is normally the province of the window manager,
1321 and so emacs' border colors may be overridden. */
1323 void
1324 x_set_border_color (f, arg, oldval)
1325 struct frame *f;
1326 Lisp_Object arg, oldval;
1328 int pix;
1330 CHECK_STRING (arg);
1331 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1332 x_set_border_pixel (f, pix);
1333 update_face_from_frame_parameter (f, Qborder_color, arg);
1337 void
1338 x_set_cursor_type (f, arg, oldval)
1339 FRAME_PTR f;
1340 Lisp_Object arg, oldval;
1342 set_frame_cursor_types (f, arg);
1344 /* Make sure the cursor gets redrawn. */
1345 cursor_type_changed = 1;
1348 void
1349 x_set_icon_type (f, arg, oldval)
1350 struct frame *f;
1351 Lisp_Object arg, oldval;
1353 int result;
1355 if (STRINGP (arg))
1357 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1358 return;
1360 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1361 return;
1363 BLOCK_INPUT;
1364 if (NILP (arg))
1365 result = x_text_icon (f,
1366 (char *) SDATA ((!NILP (f->icon_name)
1367 ? f->icon_name
1368 : f->name)));
1369 else
1370 result = x_bitmap_icon (f, arg);
1372 if (result)
1374 UNBLOCK_INPUT;
1375 error ("No icon window available");
1378 XFlush (FRAME_X_DISPLAY (f));
1379 UNBLOCK_INPUT;
1382 void
1383 x_set_icon_name (f, arg, oldval)
1384 struct frame *f;
1385 Lisp_Object arg, oldval;
1387 int result;
1389 if (STRINGP (arg))
1391 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1392 return;
1394 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1395 return;
1397 f->icon_name = arg;
1399 if (f->output_data.x->icon_bitmap != 0)
1400 return;
1402 BLOCK_INPUT;
1404 result = x_text_icon (f,
1405 (char *) SDATA ((!NILP (f->icon_name)
1406 ? f->icon_name
1407 : !NILP (f->title)
1408 ? f->title
1409 : f->name)));
1411 if (result)
1413 UNBLOCK_INPUT;
1414 error ("No icon window available");
1417 XFlush (FRAME_X_DISPLAY (f));
1418 UNBLOCK_INPUT;
1422 void
1423 x_set_menu_bar_lines (f, value, oldval)
1424 struct frame *f;
1425 Lisp_Object value, oldval;
1427 int nlines;
1428 #ifndef USE_X_TOOLKIT
1429 int olines = FRAME_MENU_BAR_LINES (f);
1430 #endif
1432 /* Right now, menu bars don't work properly in minibuf-only frames;
1433 most of the commands try to apply themselves to the minibuffer
1434 frame itself, and get an error because you can't switch buffers
1435 in or split the minibuffer window. */
1436 if (FRAME_MINIBUF_ONLY_P (f))
1437 return;
1439 if (INTEGERP (value))
1440 nlines = XINT (value);
1441 else
1442 nlines = 0;
1444 /* Make sure we redisplay all windows in this frame. */
1445 windows_or_buffers_changed++;
1447 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1448 FRAME_MENU_BAR_LINES (f) = 0;
1449 if (nlines)
1451 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1452 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1453 /* Make sure next redisplay shows the menu bar. */
1454 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1456 else
1458 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1459 free_frame_menubar (f);
1460 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1461 if (FRAME_X_P (f))
1462 f->output_data.x->menubar_widget = 0;
1464 #else /* not USE_X_TOOLKIT && not USE_GTK */
1465 FRAME_MENU_BAR_LINES (f) = nlines;
1466 change_window_heights (f->root_window, nlines - olines);
1467 #endif /* not USE_X_TOOLKIT */
1468 adjust_glyphs (f);
1472 /* Set the number of lines used for the tool bar of frame F to VALUE.
1473 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1474 is the old number of tool bar lines. This function changes the
1475 height of all windows on frame F to match the new tool bar height.
1476 The frame's height doesn't change. */
1478 void
1479 x_set_tool_bar_lines (f, value, oldval)
1480 struct frame *f;
1481 Lisp_Object value, oldval;
1483 int delta, nlines, root_height;
1484 Lisp_Object root_window;
1486 /* Treat tool bars like menu bars. */
1487 if (FRAME_MINIBUF_ONLY_P (f))
1488 return;
1490 /* Use VALUE only if an integer >= 0. */
1491 if (INTEGERP (value) && XINT (value) >= 0)
1492 nlines = XFASTINT (value);
1493 else
1494 nlines = 0;
1496 #ifdef USE_GTK
1497 FRAME_TOOL_BAR_LINES (f) = 0;
1498 if (nlines)
1500 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
1501 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1502 /* Make sure next redisplay shows the tool bar. */
1503 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1504 update_frame_tool_bar (f);
1506 else
1508 if (FRAME_EXTERNAL_TOOL_BAR (f))
1509 free_frame_tool_bar (f);
1510 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
1513 return;
1514 #endif
1516 /* Make sure we redisplay all windows in this frame. */
1517 ++windows_or_buffers_changed;
1519 delta = nlines - FRAME_TOOL_BAR_LINES (f);
1521 /* Don't resize the tool-bar to more than we have room for. */
1522 root_window = FRAME_ROOT_WINDOW (f);
1523 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
1524 if (root_height - delta < 1)
1526 delta = root_height - 1;
1527 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
1530 FRAME_TOOL_BAR_LINES (f) = nlines;
1531 change_window_heights (root_window, delta);
1532 adjust_glyphs (f);
1534 /* We also have to make sure that the internal border at the top of
1535 the frame, below the menu bar or tool bar, is redrawn when the
1536 tool bar disappears. This is so because the internal border is
1537 below the tool bar if one is displayed, but is below the menu bar
1538 if there isn't a tool bar. The tool bar draws into the area
1539 below the menu bar. */
1540 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
1542 updating_frame = f;
1543 clear_frame ();
1544 clear_current_matrices (f);
1545 updating_frame = NULL;
1548 /* If the tool bar gets smaller, the internal border below it
1549 has to be cleared. It was formerly part of the display
1550 of the larger tool bar, and updating windows won't clear it. */
1551 if (delta < 0)
1553 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1554 int width = FRAME_PIXEL_WIDTH (f);
1555 int y = nlines * FRAME_LINE_HEIGHT (f);
1557 BLOCK_INPUT;
1558 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1559 0, y, width, height, False);
1560 UNBLOCK_INPUT;
1562 if (WINDOWP (f->tool_bar_window))
1563 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1568 /* Set the foreground color for scroll bars on frame F to VALUE.
1569 VALUE should be a string, a color name. If it isn't a string or
1570 isn't a valid color name, do nothing. OLDVAL is the old value of
1571 the frame parameter. */
1573 void
1574 x_set_scroll_bar_foreground (f, value, oldval)
1575 struct frame *f;
1576 Lisp_Object value, oldval;
1578 unsigned long pixel;
1580 if (STRINGP (value))
1581 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1582 else
1583 pixel = -1;
1585 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1586 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1588 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1589 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1591 /* Remove all scroll bars because they have wrong colors. */
1592 if (condemn_scroll_bars_hook)
1593 (*condemn_scroll_bars_hook) (f);
1594 if (judge_scroll_bars_hook)
1595 (*judge_scroll_bars_hook) (f);
1597 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1598 redraw_frame (f);
1603 /* Set the background color for scroll bars on frame F to VALUE VALUE
1604 should be a string, a color name. If it isn't a string or isn't a
1605 valid color name, do nothing. OLDVAL is the old value of the frame
1606 parameter. */
1608 void
1609 x_set_scroll_bar_background (f, value, oldval)
1610 struct frame *f;
1611 Lisp_Object value, oldval;
1613 unsigned long pixel;
1615 if (STRINGP (value))
1616 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1617 else
1618 pixel = -1;
1620 if (f->output_data.x->scroll_bar_background_pixel != -1)
1621 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1623 #ifdef USE_TOOLKIT_SCROLL_BARS
1624 /* Scrollbar shadow colors. */
1625 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1627 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1628 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1630 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1632 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1633 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1635 #endif /* USE_TOOLKIT_SCROLL_BARS */
1637 f->output_data.x->scroll_bar_background_pixel = pixel;
1638 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1640 /* Remove all scroll bars because they have wrong colors. */
1641 if (condemn_scroll_bars_hook)
1642 (*condemn_scroll_bars_hook) (f);
1643 if (judge_scroll_bars_hook)
1644 (*judge_scroll_bars_hook) (f);
1646 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1647 redraw_frame (f);
1652 /* Encode Lisp string STRING as a text in a format appropriate for
1653 XICCC (X Inter Client Communication Conventions).
1655 If STRING contains only ASCII characters, do no conversion and
1656 return the string data of STRING. Otherwise, encode the text by
1657 CODING_SYSTEM, and return a newly allocated memory area which
1658 should be freed by `xfree' by a caller.
1660 SELECTIONP non-zero means the string is being encoded for an X
1661 selection, so it is safe to run pre-write conversions (which
1662 may run Lisp code).
1664 Store the byte length of resulting text in *TEXT_BYTES.
1666 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
1667 which means that the `encoding' of the result can be `STRING'.
1668 Otherwise store 0 in *STRINGP, which means that the `encoding' of
1669 the result should be `COMPOUND_TEXT'. */
1671 unsigned char *
1672 x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
1673 Lisp_Object string, coding_system;
1674 int *text_bytes, *stringp;
1675 int selectionp;
1677 unsigned char *str = SDATA (string);
1678 int chars = SCHARS (string);
1679 int bytes = SBYTES (string);
1680 int charset_info;
1681 int bufsize;
1682 unsigned char *buf;
1683 struct coding_system coding;
1684 extern Lisp_Object Qcompound_text_with_extensions;
1686 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
1687 if (charset_info == 0)
1689 /* No multibyte character in OBJ. We need not encode it. */
1690 *text_bytes = bytes;
1691 *stringp = 1;
1692 return str;
1695 setup_coding_system (coding_system, &coding);
1696 if (selectionp
1697 && SYMBOLP (coding.pre_write_conversion)
1698 && !NILP (Ffboundp (coding.pre_write_conversion)))
1700 string = run_pre_post_conversion_on_str (string, &coding, 1);
1701 str = SDATA (string);
1702 chars = SCHARS (string);
1703 bytes = SBYTES (string);
1705 coding.src_multibyte = 1;
1706 coding.dst_multibyte = 0;
1707 coding.mode |= CODING_MODE_LAST_BLOCK;
1708 if (coding.type == coding_type_iso2022)
1709 coding.flags |= CODING_FLAG_ISO_SAFE;
1710 /* We suppress producing escape sequences for composition. */
1711 coding.composing = COMPOSITION_DISABLED;
1712 bufsize = encoding_buffer_size (&coding, bytes);
1713 buf = (unsigned char *) xmalloc (bufsize);
1714 encode_coding (&coding, str, buf, bytes, bufsize);
1715 *text_bytes = coding.produced;
1716 *stringp = (charset_info == 1
1717 || (!EQ (coding_system, Qcompound_text)
1718 && !EQ (coding_system, Qcompound_text_with_extensions)));
1719 return buf;
1723 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1724 x_id_name.
1726 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1727 name; if NAME is a string, set F's name to NAME and set
1728 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1730 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1731 suggesting a new name, which lisp code should override; if
1732 F->explicit_name is set, ignore the new name; otherwise, set it. */
1734 void
1735 x_set_name (f, name, explicit)
1736 struct frame *f;
1737 Lisp_Object name;
1738 int explicit;
1740 /* Make sure that requests from lisp code override requests from
1741 Emacs redisplay code. */
1742 if (explicit)
1744 /* If we're switching from explicit to implicit, we had better
1745 update the mode lines and thereby update the title. */
1746 if (f->explicit_name && NILP (name))
1747 update_mode_lines = 1;
1749 f->explicit_name = ! NILP (name);
1751 else if (f->explicit_name)
1752 return;
1754 /* If NAME is nil, set the name to the x_id_name. */
1755 if (NILP (name))
1757 /* Check for no change needed in this very common case
1758 before we do any consing. */
1759 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
1760 SDATA (f->name)))
1761 return;
1762 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
1764 else
1765 CHECK_STRING (name);
1767 /* Don't change the name if it's already NAME. */
1768 if (! NILP (Fstring_equal (name, f->name)))
1769 return;
1771 f->name = name;
1773 /* For setting the frame title, the title parameter should override
1774 the name parameter. */
1775 if (! NILP (f->title))
1776 name = f->title;
1778 if (FRAME_X_WINDOW (f))
1780 BLOCK_INPUT;
1781 #ifdef HAVE_X11R4
1783 XTextProperty text, icon;
1784 int bytes, stringp;
1785 Lisp_Object coding_system;
1787 /* Note: Encoding strategy
1789 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1790 text.encoding. But, there are non-internationalized window
1791 managers which don't support that encoding. So, if NAME
1792 contains only ASCII and 8859-1 characters, encode it by
1793 iso-latin-1, and use "STRING" in text.encoding hoping that
1794 such window manager at least analize this format correctly,
1795 i.e. treat 8-bit bytes as 8859-1 characters.
1797 We may also be able to use "UTF8_STRING" in text.encoding
1798 in the feature which can encode all Unicode characters.
1799 But, for the moment, there's no way to know that the
1800 current window manager supports it or not. */
1801 coding_system = Qcompound_text;
1802 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1803 text.encoding = (stringp ? XA_STRING
1804 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1805 text.format = 8;
1806 text.nitems = bytes;
1808 if (NILP (f->icon_name))
1810 icon = text;
1812 else
1814 /* See the above comment "Note: Encoding strategy". */
1815 icon.value = x_encode_text (f->icon_name, coding_system, 0,
1816 &bytes, &stringp);
1817 icon.encoding = (stringp ? XA_STRING
1818 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1819 icon.format = 8;
1820 icon.nitems = bytes;
1822 #ifdef USE_GTK
1823 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1824 SDATA (name));
1825 #else /* not USE_GTK */
1826 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1827 #endif /* not USE_GTK */
1829 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1831 if (!NILP (f->icon_name)
1832 && icon.value != (unsigned char *) SDATA (f->icon_name))
1833 xfree (icon.value);
1834 if (text.value != (unsigned char *) SDATA (name))
1835 xfree (text.value);
1837 #else /* not HAVE_X11R4 */
1838 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1839 SDATA (name));
1840 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1841 SDATA (name));
1842 #endif /* not HAVE_X11R4 */
1843 UNBLOCK_INPUT;
1847 /* This function should be called when the user's lisp code has
1848 specified a name for the frame; the name will override any set by the
1849 redisplay code. */
1850 void
1851 x_explicitly_set_name (f, arg, oldval)
1852 FRAME_PTR f;
1853 Lisp_Object arg, oldval;
1855 x_set_name (f, arg, 1);
1858 /* This function should be called by Emacs redisplay code to set the
1859 name; names set this way will never override names set by the user's
1860 lisp code. */
1861 void
1862 x_implicitly_set_name (f, arg, oldval)
1863 FRAME_PTR f;
1864 Lisp_Object arg, oldval;
1866 x_set_name (f, arg, 0);
1869 /* Change the title of frame F to NAME.
1870 If NAME is nil, use the frame name as the title.
1872 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1873 name; if NAME is a string, set F's name to NAME and set
1874 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1876 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1877 suggesting a new name, which lisp code should override; if
1878 F->explicit_name is set, ignore the new name; otherwise, set it. */
1880 void
1881 x_set_title (f, name, old_name)
1882 struct frame *f;
1883 Lisp_Object name, old_name;
1885 /* Don't change the title if it's already NAME. */
1886 if (EQ (name, f->title))
1887 return;
1889 update_mode_lines = 1;
1891 f->title = name;
1893 if (NILP (name))
1894 name = f->name;
1895 else
1896 CHECK_STRING (name);
1898 if (FRAME_X_WINDOW (f))
1900 BLOCK_INPUT;
1901 #ifdef HAVE_X11R4
1903 XTextProperty text, icon;
1904 int bytes, stringp;
1905 Lisp_Object coding_system;
1907 coding_system = Qcompound_text;
1908 /* See the comment "Note: Encoding strategy" in x_set_name. */
1909 text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
1910 text.encoding = (stringp ? XA_STRING
1911 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1912 text.format = 8;
1913 text.nitems = bytes;
1915 if (NILP (f->icon_name))
1917 icon = text;
1919 else
1921 /* See the comment "Note: Encoding strategy" in x_set_name. */
1922 icon.value = x_encode_text (f->icon_name, coding_system, 0,
1923 &bytes, &stringp);
1924 icon.encoding = (stringp ? XA_STRING
1925 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1926 icon.format = 8;
1927 icon.nitems = bytes;
1930 #ifdef USE_GTK
1931 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1932 SDATA (name));
1933 #else /* not USE_GTK */
1934 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1935 #endif /* not USE_GTK */
1937 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1938 &icon);
1940 if (!NILP (f->icon_name)
1941 && icon.value != (unsigned char *) SDATA (f->icon_name))
1942 xfree (icon.value);
1943 if (text.value != (unsigned char *) SDATA (name))
1944 xfree (text.value);
1946 #else /* not HAVE_X11R4 */
1947 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1948 SDATA (name));
1949 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1950 SDATA (name));
1951 #endif /* not HAVE_X11R4 */
1952 UNBLOCK_INPUT;
1956 void
1957 x_set_scroll_bar_default_width (f)
1958 struct frame *f;
1960 int wid = FRAME_COLUMN_WIDTH (f);
1962 #ifdef USE_TOOLKIT_SCROLL_BARS
1963 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
1964 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
1965 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
1966 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width;
1967 #else
1968 /* Make the actual width at least 14 pixels and a multiple of a
1969 character width. */
1970 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
1972 /* Use all of that space (aside from required margins) for the
1973 scroll bar. */
1974 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
1975 #endif
1979 /* Record in frame F the specified or default value according to ALIST
1980 of the parameter named PROP (a Lisp symbol). If no value is
1981 specified for PROP, look for an X default for XPROP on the frame
1982 named NAME. If that is not found either, use the value DEFLT. */
1984 static Lisp_Object
1985 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
1986 foreground_p)
1987 struct frame *f;
1988 Lisp_Object alist;
1989 Lisp_Object prop;
1990 char *xprop;
1991 char *xclass;
1992 int foreground_p;
1994 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1995 Lisp_Object tem;
1997 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
1998 if (EQ (tem, Qunbound))
2000 #ifdef USE_TOOLKIT_SCROLL_BARS
2002 /* See if an X resource for the scroll bar color has been
2003 specified. */
2004 tem = display_x_get_resource (dpyinfo,
2005 build_string (foreground_p
2006 ? "foreground"
2007 : "background"),
2008 empty_string,
2009 build_string ("verticalScrollBar"),
2010 empty_string);
2011 if (!STRINGP (tem))
2013 /* If nothing has been specified, scroll bars will use a
2014 toolkit-dependent default. Because these defaults are
2015 difficult to get at without actually creating a scroll
2016 bar, use nil to indicate that no color has been
2017 specified. */
2018 tem = Qnil;
2021 #else /* not USE_TOOLKIT_SCROLL_BARS */
2023 tem = Qnil;
2025 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2028 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2029 return tem;
2034 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2036 Status
2037 XSetWMProtocols (dpy, w, protocols, count)
2038 Display *dpy;
2039 Window w;
2040 Atom *protocols;
2041 int count;
2043 Atom prop;
2044 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
2045 if (prop == None) return False;
2046 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
2047 (unsigned char *) protocols, count);
2048 return True;
2050 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2052 #ifdef USE_X_TOOLKIT
2054 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2055 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2056 already be present because of the toolkit (Motif adds some of them,
2057 for example, but Xt doesn't). */
2059 static void
2060 hack_wm_protocols (f, widget)
2061 FRAME_PTR f;
2062 Widget widget;
2064 Display *dpy = XtDisplay (widget);
2065 Window w = XtWindow (widget);
2066 int need_delete = 1;
2067 int need_focus = 1;
2068 int need_save = 1;
2070 BLOCK_INPUT;
2072 Atom type, *atoms = 0;
2073 int format = 0;
2074 unsigned long nitems = 0;
2075 unsigned long bytes_after;
2077 if ((XGetWindowProperty (dpy, w,
2078 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2079 (long)0, (long)100, False, XA_ATOM,
2080 &type, &format, &nitems, &bytes_after,
2081 (unsigned char **) &atoms)
2082 == Success)
2083 && format == 32 && type == XA_ATOM)
2084 while (nitems > 0)
2086 nitems--;
2087 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2088 need_delete = 0;
2089 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2090 need_focus = 0;
2091 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2092 need_save = 0;
2094 if (atoms) XFree ((char *) atoms);
2097 Atom props [10];
2098 int count = 0;
2099 if (need_delete)
2100 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2101 if (need_focus)
2102 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2103 if (need_save)
2104 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2105 if (count)
2106 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2107 XA_ATOM, 32, PropModeAppend,
2108 (unsigned char *) props, count);
2110 UNBLOCK_INPUT;
2112 #endif
2116 /* Support routines for XIC (X Input Context). */
2118 #ifdef HAVE_X_I18N
2120 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
2121 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
2124 /* Supported XIM styles, ordered by preference. */
2126 static XIMStyle supported_xim_styles[] =
2128 XIMPreeditPosition | XIMStatusArea,
2129 XIMPreeditPosition | XIMStatusNothing,
2130 XIMPreeditPosition | XIMStatusNone,
2131 XIMPreeditNothing | XIMStatusArea,
2132 XIMPreeditNothing | XIMStatusNothing,
2133 XIMPreeditNothing | XIMStatusNone,
2134 XIMPreeditNone | XIMStatusArea,
2135 XIMPreeditNone | XIMStatusNothing,
2136 XIMPreeditNone | XIMStatusNone,
2141 /* Create an X fontset on frame F with base font name
2142 BASE_FONTNAME.. */
2144 static XFontSet
2145 xic_create_xfontset (f, base_fontname)
2146 struct frame *f;
2147 char *base_fontname;
2149 XFontSet xfs;
2150 char **missing_list;
2151 int missing_count;
2152 char *def_string;
2154 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
2155 base_fontname, &missing_list,
2156 &missing_count, &def_string);
2157 if (missing_list)
2158 XFreeStringList (missing_list);
2160 /* No need to free def_string. */
2161 return xfs;
2165 /* Value is the best input style, given user preferences USER (already
2166 checked to be supported by Emacs), and styles supported by the
2167 input method XIM. */
2169 static XIMStyle
2170 best_xim_style (user, xim)
2171 XIMStyles *user;
2172 XIMStyles *xim;
2174 int i, j;
2176 for (i = 0; i < user->count_styles; ++i)
2177 for (j = 0; j < xim->count_styles; ++j)
2178 if (user->supported_styles[i] == xim->supported_styles[j])
2179 return user->supported_styles[i];
2181 /* Return the default style. */
2182 return XIMPreeditNothing | XIMStatusNothing;
2185 /* Create XIC for frame F. */
2187 static XIMStyle xic_style;
2189 void
2190 create_frame_xic (f)
2191 struct frame *f;
2193 XIM xim;
2194 XIC xic = NULL;
2195 XFontSet xfs = NULL;
2197 if (FRAME_XIC (f))
2198 return;
2200 xim = FRAME_X_XIM (f);
2201 if (xim)
2203 XRectangle s_area;
2204 XPoint spot;
2205 XVaNestedList preedit_attr;
2206 XVaNestedList status_attr;
2207 char *base_fontname;
2208 int fontset;
2210 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2211 spot.x = 0; spot.y = 1;
2212 /* Create X fontset. */
2213 fontset = FRAME_FONTSET (f);
2214 if (fontset < 0)
2215 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2216 else
2218 /* Determine the base fontname from the ASCII font name of
2219 FONTSET. */
2220 char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
2221 char *p = ascii_font;
2222 int i;
2224 for (i = 0; *p; p++)
2225 if (*p == '-') i++;
2226 if (i != 14)
2227 /* As the font name doesn't conform to XLFD, we can't
2228 modify it to get a suitable base fontname for the
2229 frame. */
2230 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2231 else
2233 int len = strlen (ascii_font) + 1;
2234 char *p1 = NULL;
2236 for (i = 0, p = ascii_font; i < 8; p++)
2238 if (*p == '-')
2240 i++;
2241 if (i == 3)
2242 p1 = p + 1;
2245 base_fontname = (char *) alloca (len);
2246 bzero (base_fontname, len);
2247 strcpy (base_fontname, "-*-*-");
2248 bcopy (p1, base_fontname + 5, p - p1);
2249 strcat (base_fontname, "*-*-*-*-*-*-*");
2252 xfs = xic_create_xfontset (f, base_fontname);
2254 /* Determine XIC style. */
2255 if (xic_style == 0)
2257 XIMStyles supported_list;
2258 supported_list.count_styles = (sizeof supported_xim_styles
2259 / sizeof supported_xim_styles[0]);
2260 supported_list.supported_styles = supported_xim_styles;
2261 xic_style = best_xim_style (&supported_list,
2262 FRAME_X_XIM_STYLES (f));
2265 preedit_attr = XVaCreateNestedList (0,
2266 XNFontSet, xfs,
2267 XNForeground,
2268 FRAME_FOREGROUND_PIXEL (f),
2269 XNBackground,
2270 FRAME_BACKGROUND_PIXEL (f),
2271 (xic_style & XIMPreeditPosition
2272 ? XNSpotLocation
2273 : NULL),
2274 &spot,
2275 NULL);
2276 status_attr = XVaCreateNestedList (0,
2277 XNArea,
2278 &s_area,
2279 XNFontSet,
2280 xfs,
2281 XNForeground,
2282 FRAME_FOREGROUND_PIXEL (f),
2283 XNBackground,
2284 FRAME_BACKGROUND_PIXEL (f),
2285 NULL);
2287 xic = XCreateIC (xim,
2288 XNInputStyle, xic_style,
2289 XNClientWindow, FRAME_X_WINDOW(f),
2290 XNFocusWindow, FRAME_X_WINDOW(f),
2291 XNStatusAttributes, status_attr,
2292 XNPreeditAttributes, preedit_attr,
2293 NULL);
2294 XFree (preedit_attr);
2295 XFree (status_attr);
2298 FRAME_XIC (f) = xic;
2299 FRAME_XIC_STYLE (f) = xic_style;
2300 FRAME_XIC_FONTSET (f) = xfs;
2304 /* Destroy XIC and free XIC fontset of frame F, if any. */
2306 void
2307 free_frame_xic (f)
2308 struct frame *f;
2310 if (FRAME_XIC (f) == NULL)
2311 return;
2313 XDestroyIC (FRAME_XIC (f));
2314 if (FRAME_XIC_FONTSET (f))
2315 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2317 FRAME_XIC (f) = NULL;
2318 FRAME_XIC_FONTSET (f) = NULL;
2322 /* Place preedit area for XIC of window W's frame to specified
2323 pixel position X/Y. X and Y are relative to window W. */
2325 void
2326 xic_set_preeditarea (w, x, y)
2327 struct window *w;
2328 int x, y;
2330 struct frame *f = XFRAME (w->frame);
2331 XVaNestedList attr;
2332 XPoint spot;
2334 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
2335 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2336 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2337 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2338 XFree (attr);
2342 /* Place status area for XIC in bottom right corner of frame F.. */
2344 void
2345 xic_set_statusarea (f)
2346 struct frame *f;
2348 XIC xic = FRAME_XIC (f);
2349 XVaNestedList attr;
2350 XRectangle area;
2351 XRectangle *needed;
2353 /* Negotiate geometry of status area. If input method has existing
2354 status area, use its current size. */
2355 area.x = area.y = area.width = area.height = 0;
2356 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2357 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2358 XFree (attr);
2360 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2361 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2362 XFree (attr);
2364 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2366 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2367 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2368 XFree (attr);
2371 area.width = needed->width;
2372 area.height = needed->height;
2373 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2374 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2375 - FRAME_MENUBAR_HEIGHT (f)
2376 - FRAME_TOOLBAR_HEIGHT (f)
2377 - FRAME_INTERNAL_BORDER_WIDTH (f));
2378 XFree (needed);
2380 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2381 XSetICValues(xic, XNStatusAttributes, attr, NULL);
2382 XFree (attr);
2386 /* Set X fontset for XIC of frame F, using base font name
2387 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2389 void
2390 xic_set_xfontset (f, base_fontname)
2391 struct frame *f;
2392 char *base_fontname;
2394 XVaNestedList attr;
2395 XFontSet xfs;
2397 xfs = xic_create_xfontset (f, base_fontname);
2399 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2400 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2401 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2402 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2403 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2404 XFree (attr);
2406 if (FRAME_XIC_FONTSET (f))
2407 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2408 FRAME_XIC_FONTSET (f) = xfs;
2411 #endif /* HAVE_X_I18N */
2415 #ifdef USE_X_TOOLKIT
2417 /* Create and set up the X widget for frame F. */
2419 static void
2420 x_window (f, window_prompting, minibuffer_only)
2421 struct frame *f;
2422 long window_prompting;
2423 int minibuffer_only;
2425 XClassHint class_hints;
2426 XSetWindowAttributes attributes;
2427 unsigned long attribute_mask;
2428 Widget shell_widget;
2429 Widget pane_widget;
2430 Widget frame_widget;
2431 Arg al [25];
2432 int ac;
2434 BLOCK_INPUT;
2436 /* Use the resource name as the top-level widget name
2437 for looking up resources. Make a non-Lisp copy
2438 for the window manager, so GC relocation won't bother it.
2440 Elsewhere we specify the window name for the window manager. */
2443 char *str = (char *) SDATA (Vx_resource_name);
2444 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2445 strcpy (f->namebuf, str);
2448 ac = 0;
2449 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2450 XtSetArg (al[ac], XtNinput, 1); ac++;
2451 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2452 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2453 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2454 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2455 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2456 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2457 applicationShellWidgetClass,
2458 FRAME_X_DISPLAY (f), al, ac);
2460 f->output_data.x->widget = shell_widget;
2461 /* maybe_set_screen_title_format (shell_widget); */
2463 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2464 (widget_value *) NULL,
2465 shell_widget, False,
2466 (lw_callback) NULL,
2467 (lw_callback) NULL,
2468 (lw_callback) NULL,
2469 (lw_callback) NULL);
2471 ac = 0;
2472 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2473 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2474 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2475 XtSetValues (pane_widget, al, ac);
2476 f->output_data.x->column_widget = pane_widget;
2478 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2479 the emacs screen when changing menubar. This reduces flickering. */
2481 ac = 0;
2482 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2483 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2484 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2485 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2486 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2487 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2488 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
2489 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2490 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2491 al, ac);
2493 f->output_data.x->edit_widget = frame_widget;
2495 XtManageChild (frame_widget);
2497 /* Do some needed geometry management. */
2499 int len;
2500 char *tem, shell_position[32];
2501 Arg al[2];
2502 int ac = 0;
2503 int extra_borders = 0;
2504 int menubar_size
2505 = (f->output_data.x->menubar_widget
2506 ? (f->output_data.x->menubar_widget->core.height
2507 + f->output_data.x->menubar_widget->core.border_width)
2508 : 0);
2510 #if 0 /* Experimentally, we now get the right results
2511 for -geometry -0-0 without this. 24 Aug 96, rms. */
2512 if (FRAME_EXTERNAL_MENU_BAR (f))
2514 Dimension ibw = 0;
2515 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2516 menubar_size += ibw;
2518 #endif
2520 f->output_data.x->menubar_height = menubar_size;
2522 #ifndef USE_LUCID
2523 /* Motif seems to need this amount added to the sizes
2524 specified for the shell widget. The Athena/Lucid widgets don't.
2525 Both conclusions reached experimentally. -- rms. */
2526 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2527 &extra_borders, NULL);
2528 extra_borders *= 2;
2529 #endif
2531 /* Convert our geometry parameters into a geometry string
2532 and specify it.
2533 Note that we do not specify here whether the position
2534 is a user-specified or program-specified one.
2535 We pass that information later, in x_wm_set_size_hints. */
2537 int left = f->left_pos;
2538 int xneg = window_prompting & XNegative;
2539 int top = f->top_pos;
2540 int yneg = window_prompting & YNegative;
2541 if (xneg)
2542 left = -left;
2543 if (yneg)
2544 top = -top;
2546 if (window_prompting & USPosition)
2547 sprintf (shell_position, "=%dx%d%c%d%c%d",
2548 FRAME_PIXEL_WIDTH (f) + extra_borders,
2549 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2550 (xneg ? '-' : '+'), left,
2551 (yneg ? '-' : '+'), top);
2552 else
2553 sprintf (shell_position, "=%dx%d",
2554 FRAME_PIXEL_WIDTH (f) + extra_borders,
2555 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2558 len = strlen (shell_position) + 1;
2559 /* We don't free this because we don't know whether
2560 it is safe to free it while the frame exists.
2561 It isn't worth the trouble of arranging to free it
2562 when the frame is deleted. */
2563 tem = (char *) xmalloc (len);
2564 strncpy (tem, shell_position, len);
2565 XtSetArg (al[ac], XtNgeometry, tem); ac++;
2566 XtSetValues (shell_widget, al, ac);
2569 XtManageChild (pane_widget);
2570 XtRealizeWidget (shell_widget);
2572 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2574 validate_x_resource_name ();
2576 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2577 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2578 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2580 #ifdef HAVE_X_I18N
2581 FRAME_XIC (f) = NULL;
2582 if (use_xim)
2583 create_frame_xic (f);
2584 #endif
2586 f->output_data.x->wm_hints.input = True;
2587 f->output_data.x->wm_hints.flags |= InputHint;
2588 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2589 &f->output_data.x->wm_hints);
2591 hack_wm_protocols (f, shell_widget);
2593 #ifdef HACK_EDITRES
2594 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2595 #endif
2597 /* Do a stupid property change to force the server to generate a
2598 PropertyNotify event so that the event_stream server timestamp will
2599 be initialized to something relevant to the time we created the window.
2601 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2602 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
2603 XA_ATOM, 32, PropModeAppend,
2604 (unsigned char*) NULL, 0);
2606 /* Make all the standard events reach the Emacs frame. */
2607 attributes.event_mask = STANDARD_EVENT_SET;
2609 #ifdef HAVE_X_I18N
2610 if (FRAME_XIC (f))
2612 /* XIM server might require some X events. */
2613 unsigned long fevent = NoEventMask;
2614 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2615 attributes.event_mask |= fevent;
2617 #endif /* HAVE_X_I18N */
2619 attribute_mask = CWEventMask;
2620 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2621 attribute_mask, &attributes);
2623 XtMapWidget (frame_widget);
2625 /* x_set_name normally ignores requests to set the name if the
2626 requested name is the same as the current name. This is the one
2627 place where that assumption isn't correct; f->name is set, but
2628 the X server hasn't been told. */
2630 Lisp_Object name;
2631 int explicit = f->explicit_name;
2633 f->explicit_name = 0;
2634 name = f->name;
2635 f->name = Qnil;
2636 x_set_name (f, name, explicit);
2639 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2640 f->output_data.x->text_cursor);
2642 UNBLOCK_INPUT;
2644 /* This is a no-op, except under Motif. Make sure main areas are
2645 set to something reasonable, in case we get an error later. */
2646 lw_set_main_areas (pane_widget, 0, frame_widget);
2649 #else /* not USE_X_TOOLKIT */
2650 #ifdef USE_GTK
2651 void
2652 x_window (f)
2653 FRAME_PTR f;
2655 if (! xg_create_frame_widgets (f))
2656 error ("Unable to create window");
2658 #ifdef HAVE_X_I18N
2659 FRAME_XIC (f) = NULL;
2660 if (use_xim)
2662 BLOCK_INPUT;
2663 create_frame_xic (f);
2664 if (FRAME_XIC (f))
2666 /* XIM server might require some X events. */
2667 unsigned long fevent = NoEventMask;
2668 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2670 if (fevent != NoEventMask)
2672 XSetWindowAttributes attributes;
2673 XWindowAttributes wattr;
2674 unsigned long attribute_mask;
2676 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2677 &wattr);
2678 attributes.event_mask = wattr.your_event_mask | fevent;
2679 attribute_mask = CWEventMask;
2680 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2681 attribute_mask, &attributes);
2684 UNBLOCK_INPUT;
2686 #endif
2689 #else /*! USE_GTK */
2690 /* Create and set up the X window for frame F. */
2692 void
2693 x_window (f)
2694 struct frame *f;
2697 XClassHint class_hints;
2698 XSetWindowAttributes attributes;
2699 unsigned long attribute_mask;
2701 attributes.background_pixel = f->output_data.x->background_pixel;
2702 attributes.border_pixel = f->output_data.x->border_pixel;
2703 attributes.bit_gravity = StaticGravity;
2704 attributes.backing_store = NotUseful;
2705 attributes.save_under = True;
2706 attributes.event_mask = STANDARD_EVENT_SET;
2707 attributes.colormap = FRAME_X_COLORMAP (f);
2708 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2709 | CWColormap);
2711 BLOCK_INPUT;
2712 FRAME_X_WINDOW (f)
2713 = XCreateWindow (FRAME_X_DISPLAY (f),
2714 f->output_data.x->parent_desc,
2715 f->left_pos,
2716 f->top_pos,
2717 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2718 f->border_width,
2719 CopyFromParent, /* depth */
2720 InputOutput, /* class */
2721 FRAME_X_VISUAL (f),
2722 attribute_mask, &attributes);
2724 #ifdef HAVE_X_I18N
2725 if (use_xim)
2727 create_frame_xic (f);
2728 if (FRAME_XIC (f))
2730 /* XIM server might require some X events. */
2731 unsigned long fevent = NoEventMask;
2732 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2733 attributes.event_mask |= fevent;
2734 attribute_mask = CWEventMask;
2735 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2736 attribute_mask, &attributes);
2739 #endif /* HAVE_X_I18N */
2741 validate_x_resource_name ();
2743 class_hints.res_name = (char *) SDATA (Vx_resource_name);
2744 class_hints.res_class = (char *) SDATA (Vx_resource_class);
2745 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2747 /* The menubar is part of the ordinary display;
2748 it does not count in addition to the height of the window. */
2749 f->output_data.x->menubar_height = 0;
2751 /* This indicates that we use the "Passive Input" input model.
2752 Unless we do this, we don't get the Focus{In,Out} events that we
2753 need to draw the cursor correctly. Accursed bureaucrats.
2754 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2756 f->output_data.x->wm_hints.input = True;
2757 f->output_data.x->wm_hints.flags |= InputHint;
2758 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2759 &f->output_data.x->wm_hints);
2760 f->output_data.x->wm_hints.icon_pixmap = None;
2762 /* Request "save yourself" and "delete window" commands from wm. */
2764 Atom protocols[2];
2765 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2766 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2767 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2770 /* x_set_name normally ignores requests to set the name if the
2771 requested name is the same as the current name. This is the one
2772 place where that assumption isn't correct; f->name is set, but
2773 the X server hasn't been told. */
2775 Lisp_Object name;
2776 int explicit = f->explicit_name;
2778 f->explicit_name = 0;
2779 name = f->name;
2780 f->name = Qnil;
2781 x_set_name (f, name, explicit);
2784 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2785 f->output_data.x->text_cursor);
2787 UNBLOCK_INPUT;
2789 if (FRAME_X_WINDOW (f) == 0)
2790 error ("Unable to create window");
2793 #endif /* not USE_GTK */
2794 #endif /* not USE_X_TOOLKIT */
2796 /* Handle the icon stuff for this window. Perhaps later we might
2797 want an x_set_icon_position which can be called interactively as
2798 well. */
2800 static void
2801 x_icon (f, parms)
2802 struct frame *f;
2803 Lisp_Object parms;
2805 Lisp_Object icon_x, icon_y;
2806 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2808 /* Set the position of the icon. Note that twm groups all
2809 icons in an icon window. */
2810 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2811 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2812 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2814 CHECK_NUMBER (icon_x);
2815 CHECK_NUMBER (icon_y);
2817 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2818 error ("Both left and top icon corners of icon must be specified");
2820 BLOCK_INPUT;
2822 if (! EQ (icon_x, Qunbound))
2823 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2825 /* Start up iconic or window? */
2826 x_wm_set_window_state
2827 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
2828 Qicon)
2829 ? IconicState
2830 : NormalState));
2832 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2833 ? f->icon_name
2834 : f->name)));
2836 UNBLOCK_INPUT;
2839 /* Make the GCs needed for this window, setting the
2840 background, border and mouse colors; also create the
2841 mouse cursor and the gray border tile. */
2843 static char cursor_bits[] =
2845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2851 static void
2852 x_make_gc (f)
2853 struct frame *f;
2855 XGCValues gc_values;
2857 BLOCK_INPUT;
2859 /* Create the GCs of this frame.
2860 Note that many default values are used. */
2862 /* Normal video */
2863 gc_values.font = FRAME_FONT (f)->fid;
2864 gc_values.foreground = f->output_data.x->foreground_pixel;
2865 gc_values.background = f->output_data.x->background_pixel;
2866 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
2867 f->output_data.x->normal_gc
2868 = XCreateGC (FRAME_X_DISPLAY (f),
2869 FRAME_X_WINDOW (f),
2870 GCLineWidth | GCFont | GCForeground | GCBackground,
2871 &gc_values);
2873 /* Reverse video style. */
2874 gc_values.foreground = f->output_data.x->background_pixel;
2875 gc_values.background = f->output_data.x->foreground_pixel;
2876 f->output_data.x->reverse_gc
2877 = XCreateGC (FRAME_X_DISPLAY (f),
2878 FRAME_X_WINDOW (f),
2879 GCFont | GCForeground | GCBackground | GCLineWidth,
2880 &gc_values);
2882 /* Cursor has cursor-color background, background-color foreground. */
2883 gc_values.foreground = f->output_data.x->background_pixel;
2884 gc_values.background = f->output_data.x->cursor_pixel;
2885 gc_values.fill_style = FillOpaqueStippled;
2886 gc_values.stipple
2887 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
2888 FRAME_X_DISPLAY_INFO (f)->root_window,
2889 cursor_bits, 16, 16);
2890 f->output_data.x->cursor_gc
2891 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2892 (GCFont | GCForeground | GCBackground
2893 | GCFillStyle /* | GCStipple */ | GCLineWidth),
2894 &gc_values);
2896 /* Reliefs. */
2897 f->output_data.x->white_relief.gc = 0;
2898 f->output_data.x->black_relief.gc = 0;
2900 /* Create the gray border tile used when the pointer is not in
2901 the frame. Since this depends on the frame's pixel values,
2902 this must be done on a per-frame basis. */
2903 f->output_data.x->border_tile
2904 = (XCreatePixmapFromBitmapData
2905 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2906 gray_bits, gray_width, gray_height,
2907 f->output_data.x->foreground_pixel,
2908 f->output_data.x->background_pixel,
2909 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2911 UNBLOCK_INPUT;
2915 /* Free what was was allocated in x_make_gc. */
2917 void
2918 x_free_gcs (f)
2919 struct frame *f;
2921 Display *dpy = FRAME_X_DISPLAY (f);
2923 BLOCK_INPUT;
2925 if (f->output_data.x->normal_gc)
2927 XFreeGC (dpy, f->output_data.x->normal_gc);
2928 f->output_data.x->normal_gc = 0;
2931 if (f->output_data.x->reverse_gc)
2933 XFreeGC (dpy, f->output_data.x->reverse_gc);
2934 f->output_data.x->reverse_gc = 0;
2937 if (f->output_data.x->cursor_gc)
2939 XFreeGC (dpy, f->output_data.x->cursor_gc);
2940 f->output_data.x->cursor_gc = 0;
2943 if (f->output_data.x->border_tile)
2945 XFreePixmap (dpy, f->output_data.x->border_tile);
2946 f->output_data.x->border_tile = 0;
2949 UNBLOCK_INPUT;
2953 /* Handler for signals raised during x_create_frame and
2954 x_create_top_frame. FRAME is the frame which is partially
2955 constructed. */
2957 static Lisp_Object
2958 unwind_create_frame (frame)
2959 Lisp_Object frame;
2961 struct frame *f = XFRAME (frame);
2963 /* If frame is ``official'', nothing to do. */
2964 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2966 #if GLYPH_DEBUG
2967 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2968 #endif
2970 x_free_frame_resources (f);
2972 /* Check that reference counts are indeed correct. */
2973 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2974 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2975 return Qt;
2978 return Qnil;
2982 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2983 1, 1, 0,
2984 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
2985 Returns an Emacs frame object.
2986 ALIST is an alist of frame parameters.
2987 If the parameters specify that the frame should not have a minibuffer,
2988 and do not specify a specific minibuffer window to use,
2989 then `default-minibuffer-frame' must be a frame whose minibuffer can
2990 be shared by the new frame.
2992 This function is an internal primitive--use `make-frame' instead. */)
2993 (parms)
2994 Lisp_Object parms;
2996 struct frame *f;
2997 Lisp_Object frame, tem;
2998 Lisp_Object name;
2999 int minibuffer_only = 0;
3000 long window_prompting = 0;
3001 int width, height;
3002 int count = SPECPDL_INDEX ();
3003 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3004 Lisp_Object display;
3005 struct x_display_info *dpyinfo = NULL;
3006 Lisp_Object parent;
3007 struct kboard *kb;
3009 check_x ();
3011 /* Use this general default value to start with
3012 until we know if this frame has a specified name. */
3013 Vx_resource_name = Vinvocation_name;
3015 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3016 if (EQ (display, Qunbound))
3017 display = Qnil;
3018 dpyinfo = check_x_display_info (display);
3019 #ifdef MULTI_KBOARD
3020 kb = dpyinfo->kboard;
3021 #else
3022 kb = &the_only_kboard;
3023 #endif
3025 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3026 if (!STRINGP (name)
3027 && ! EQ (name, Qunbound)
3028 && ! NILP (name))
3029 error ("Invalid frame name--not a string or nil");
3031 if (STRINGP (name))
3032 Vx_resource_name = name;
3034 /* See if parent window is specified. */
3035 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3036 if (EQ (parent, Qunbound))
3037 parent = Qnil;
3038 if (! NILP (parent))
3039 CHECK_NUMBER (parent);
3041 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3042 /* No need to protect DISPLAY because that's not used after passing
3043 it to make_frame_without_minibuffer. */
3044 frame = Qnil;
3045 GCPRO4 (parms, parent, name, frame);
3046 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3047 RES_TYPE_SYMBOL);
3048 if (EQ (tem, Qnone) || NILP (tem))
3049 f = make_frame_without_minibuffer (Qnil, kb, display);
3050 else if (EQ (tem, Qonly))
3052 f = make_minibuffer_frame ();
3053 minibuffer_only = 1;
3055 else if (WINDOWP (tem))
3056 f = make_frame_without_minibuffer (tem, kb, display);
3057 else
3058 f = make_frame (1);
3060 XSETFRAME (frame, f);
3062 /* Note that X Windows does support scroll bars. */
3063 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
3065 f->output_method = output_x_window;
3066 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
3067 bzero (f->output_data.x, sizeof (struct x_output));
3068 f->output_data.x->icon_bitmap = -1;
3069 FRAME_FONTSET (f) = -1;
3070 f->output_data.x->scroll_bar_foreground_pixel = -1;
3071 f->output_data.x->scroll_bar_background_pixel = -1;
3072 #ifdef USE_TOOLKIT_SCROLL_BARS
3073 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3074 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3075 #endif /* USE_TOOLKIT_SCROLL_BARS */
3076 record_unwind_protect (unwind_create_frame, frame);
3078 f->icon_name
3079 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3080 RES_TYPE_STRING);
3081 if (! STRINGP (f->icon_name))
3082 f->icon_name = Qnil;
3084 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
3085 #if GLYPH_DEBUG
3086 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
3087 dpyinfo_refcount = dpyinfo->reference_count;
3088 #endif /* GLYPH_DEBUG */
3089 #ifdef MULTI_KBOARD
3090 FRAME_KBOARD (f) = kb;
3091 #endif
3093 /* These colors will be set anyway later, but it's important
3094 to get the color reference counts right, so initialize them! */
3096 Lisp_Object black;
3097 struct gcpro gcpro1;
3099 /* Function x_decode_color can signal an error. Make
3100 sure to initialize color slots so that we won't try
3101 to free colors we haven't allocated. */
3102 f->output_data.x->foreground_pixel = -1;
3103 f->output_data.x->background_pixel = -1;
3104 f->output_data.x->cursor_pixel = -1;
3105 f->output_data.x->cursor_foreground_pixel = -1;
3106 f->output_data.x->border_pixel = -1;
3107 f->output_data.x->mouse_pixel = -1;
3109 black = build_string ("black");
3110 GCPRO1 (black);
3111 f->output_data.x->foreground_pixel
3112 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3113 f->output_data.x->background_pixel
3114 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3115 f->output_data.x->cursor_pixel
3116 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3117 f->output_data.x->cursor_foreground_pixel
3118 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3119 f->output_data.x->border_pixel
3120 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3121 f->output_data.x->mouse_pixel
3122 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3123 UNGCPRO;
3126 /* Specify the parent under which to make this X window. */
3128 if (!NILP (parent))
3130 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3131 f->output_data.x->explicit_parent = 1;
3133 else
3135 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3136 f->output_data.x->explicit_parent = 0;
3139 /* Set the name; the functions to which we pass f expect the name to
3140 be set. */
3141 if (EQ (name, Qunbound) || NILP (name))
3143 f->name = build_string (dpyinfo->x_id_name);
3144 f->explicit_name = 0;
3146 else
3148 f->name = name;
3149 f->explicit_name = 1;
3150 /* use the frame's title when getting resources for this frame. */
3151 specbind (Qx_resource_name, name);
3154 /* Extract the window parameters from the supplied values
3155 that are needed to determine window geometry. */
3157 Lisp_Object font;
3159 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3161 BLOCK_INPUT;
3162 /* First, try whatever font the caller has specified. */
3163 if (STRINGP (font))
3165 tem = Fquery_fontset (font, Qnil);
3166 if (STRINGP (tem))
3167 font = x_new_fontset (f, SDATA (tem));
3168 else
3169 font = x_new_font (f, SDATA (font));
3172 /* Try out a font which we hope has bold and italic variations. */
3173 if (!STRINGP (font))
3174 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3175 if (!STRINGP (font))
3176 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3177 if (! STRINGP (font))
3178 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3179 if (! STRINGP (font))
3180 /* This was formerly the first thing tried, but it finds too many fonts
3181 and takes too long. */
3182 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3183 /* If those didn't work, look for something which will at least work. */
3184 if (! STRINGP (font))
3185 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3186 UNBLOCK_INPUT;
3187 if (! STRINGP (font))
3188 font = build_string ("fixed");
3190 x_default_parameter (f, parms, Qfont, font,
3191 "font", "Font", RES_TYPE_STRING);
3194 #ifdef USE_LUCID
3195 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3196 whereby it fails to get any font. */
3197 xlwmenu_default_font = FRAME_FONT (f);
3198 #endif
3200 x_default_parameter (f, parms, Qborder_width, make_number (2),
3201 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3203 /* This defaults to 1 in order to match xterm. We recognize either
3204 internalBorderWidth or internalBorder (which is what xterm calls
3205 it). */
3206 if (NILP (Fassq (Qinternal_border_width, parms)))
3208 Lisp_Object value;
3210 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3211 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3212 if (! EQ (value, Qunbound))
3213 parms = Fcons (Fcons (Qinternal_border_width, value),
3214 parms);
3216 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
3217 "internalBorderWidth", "internalBorderWidth",
3218 RES_TYPE_NUMBER);
3219 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
3220 "verticalScrollBars", "ScrollBars",
3221 RES_TYPE_SYMBOL);
3223 /* Also do the stuff which must be set before the window exists. */
3224 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3225 "foreground", "Foreground", RES_TYPE_STRING);
3226 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3227 "background", "Background", RES_TYPE_STRING);
3228 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3229 "pointerColor", "Foreground", RES_TYPE_STRING);
3230 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3231 "cursorColor", "Foreground", RES_TYPE_STRING);
3232 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3233 "borderColor", "BorderColor", RES_TYPE_STRING);
3234 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3235 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3236 x_default_parameter (f, parms, Qline_spacing, Qnil,
3237 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3238 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3239 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3240 x_default_parameter (f, parms, Qright_fringe, Qnil,
3241 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3243 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3244 "scrollBarForeground",
3245 "ScrollBarForeground", 1);
3246 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3247 "scrollBarBackground",
3248 "ScrollBarBackground", 0);
3250 /* Init faces before x_default_parameter is called for scroll-bar
3251 parameters because that function calls x_set_scroll_bar_width,
3252 which calls change_frame_size, which calls Fset_window_buffer,
3253 which runs hooks, which call Fvertical_motion. At the end, we
3254 end up in init_iterator with a null face cache, which should not
3255 happen. */
3256 init_frame_faces (f);
3258 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3259 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3260 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
3261 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3262 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3263 "bufferPredicate", "BufferPredicate",
3264 RES_TYPE_SYMBOL);
3265 x_default_parameter (f, parms, Qtitle, Qnil,
3266 "title", "Title", RES_TYPE_STRING);
3267 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3268 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3269 x_default_parameter (f, parms, Qfullscreen, Qnil,
3270 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3272 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3274 /* Compute the size of the X window. */
3275 window_prompting = x_figure_window_size (f, parms, 1);
3277 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3278 f->no_split = minibuffer_only || EQ (tem, Qt);
3280 /* Create the X widget or window. */
3281 #ifdef USE_X_TOOLKIT
3282 x_window (f, window_prompting, minibuffer_only);
3283 #else
3284 x_window (f);
3285 #endif
3287 x_icon (f, parms);
3288 x_make_gc (f);
3290 /* Now consider the frame official. */
3291 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3292 Vframe_list = Fcons (frame, Vframe_list);
3294 /* We need to do this after creating the X window, so that the
3295 icon-creation functions can say whose icon they're describing. */
3296 x_default_parameter (f, parms, Qicon_type, Qnil,
3297 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3299 x_default_parameter (f, parms, Qauto_raise, Qnil,
3300 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3301 x_default_parameter (f, parms, Qauto_lower, Qnil,
3302 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3303 x_default_parameter (f, parms, Qcursor_type, Qbox,
3304 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3305 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3306 "scrollBarWidth", "ScrollBarWidth",
3307 RES_TYPE_NUMBER);
3309 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3310 Change will not be effected unless different from the current
3311 FRAME_LINES (f). */
3312 width = FRAME_COLS (f);
3313 height = FRAME_LINES (f);
3315 SET_FRAME_COLS (f, 0);
3316 FRAME_LINES (f) = 0;
3317 change_frame_size (f, height, width, 1, 0, 0);
3319 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3320 /* Create the menu bar. */
3321 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3323 /* If this signals an error, we haven't set size hints for the
3324 frame and we didn't make it visible. */
3325 initialize_frame_menubar (f);
3327 #ifndef USE_GTK
3328 /* This is a no-op, except under Motif where it arranges the
3329 main window for the widgets on it. */
3330 lw_set_main_areas (f->output_data.x->column_widget,
3331 f->output_data.x->menubar_widget,
3332 f->output_data.x->edit_widget);
3333 #endif /* not USE_GTK */
3335 #endif /* USE_X_TOOLKIT || USE_GTK */
3337 /* Tell the server what size and position, etc, we want, and how
3338 badly we want them. This should be done after we have the menu
3339 bar so that its size can be taken into account. */
3340 BLOCK_INPUT;
3341 x_wm_set_size_hint (f, window_prompting, 0);
3342 UNBLOCK_INPUT;
3344 /* Make the window appear on the frame and enable display, unless
3345 the caller says not to. However, with explicit parent, Emacs
3346 cannot control visibility, so don't try. */
3347 if (! f->output_data.x->explicit_parent)
3349 Lisp_Object visibility;
3351 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3352 RES_TYPE_SYMBOL);
3353 if (EQ (visibility, Qunbound))
3354 visibility = Qt;
3356 if (EQ (visibility, Qicon))
3357 x_iconify_frame (f);
3358 else if (! NILP (visibility))
3359 x_make_frame_visible (f);
3360 else
3361 /* Must have been Qnil. */
3365 UNGCPRO;
3367 /* Make sure windows on this frame appear in calls to next-window
3368 and similar functions. */
3369 Vwindow_list = Qnil;
3371 return unbind_to (count, frame);
3375 /* FRAME is used only to get a handle on the X display. We don't pass the
3376 display info directly because we're called from frame.c, which doesn't
3377 know about that structure. */
3379 Lisp_Object
3380 x_get_focus_frame (frame)
3381 struct frame *frame;
3383 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
3384 Lisp_Object xfocus;
3385 if (! dpyinfo->x_focus_frame)
3386 return Qnil;
3388 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3389 return xfocus;
3393 /* In certain situations, when the window manager follows a
3394 click-to-focus policy, there seems to be no way around calling
3395 XSetInputFocus to give another frame the input focus .
3397 In an ideal world, XSetInputFocus should generally be avoided so
3398 that applications don't interfere with the window manager's focus
3399 policy. But I think it's okay to use when it's clearly done
3400 following a user-command. */
3402 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
3403 doc: /* Set the input focus to FRAME.
3404 FRAME nil means use the selected frame. */)
3405 (frame)
3406 Lisp_Object frame;
3408 struct frame *f = check_x_frame (frame);
3409 Display *dpy = FRAME_X_DISPLAY (f);
3410 int count;
3412 BLOCK_INPUT;
3413 count = x_catch_errors (dpy);
3414 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3415 RevertToParent, CurrentTime);
3416 x_uncatch_errors (dpy, count);
3417 UNBLOCK_INPUT;
3419 return Qnil;
3423 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3424 doc: /* Internal function called by `color-defined-p', which see. */)
3425 (color, frame)
3426 Lisp_Object color, frame;
3428 XColor foo;
3429 FRAME_PTR f = check_x_frame (frame);
3431 CHECK_STRING (color);
3433 if (x_defined_color (f, SDATA (color), &foo, 0))
3434 return Qt;
3435 else
3436 return Qnil;
3439 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3440 doc: /* Internal function called by `color-values', which see. */)
3441 (color, frame)
3442 Lisp_Object color, frame;
3444 XColor foo;
3445 FRAME_PTR f = check_x_frame (frame);
3447 CHECK_STRING (color);
3449 if (x_defined_color (f, SDATA (color), &foo, 0))
3451 Lisp_Object rgb[3];
3453 rgb[0] = make_number (foo.red);
3454 rgb[1] = make_number (foo.green);
3455 rgb[2] = make_number (foo.blue);
3456 return Flist (3, rgb);
3458 else
3459 return Qnil;
3462 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3463 doc: /* Internal function called by `display-color-p', which see. */)
3464 (display)
3465 Lisp_Object display;
3467 struct x_display_info *dpyinfo = check_x_display_info (display);
3469 if (dpyinfo->n_planes <= 2)
3470 return Qnil;
3472 switch (dpyinfo->visual->class)
3474 case StaticColor:
3475 case PseudoColor:
3476 case TrueColor:
3477 case DirectColor:
3478 return Qt;
3480 default:
3481 return Qnil;
3485 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3486 0, 1, 0,
3487 doc: /* Return t if the X display supports shades of gray.
3488 Note that color displays do support shades of gray.
3489 The optional argument DISPLAY specifies which display to ask about.
3490 DISPLAY should be either a frame or a display name (a string).
3491 If omitted or nil, that stands for the selected frame's display. */)
3492 (display)
3493 Lisp_Object display;
3495 struct x_display_info *dpyinfo = check_x_display_info (display);
3497 if (dpyinfo->n_planes <= 1)
3498 return Qnil;
3500 switch (dpyinfo->visual->class)
3502 case StaticColor:
3503 case PseudoColor:
3504 case TrueColor:
3505 case DirectColor:
3506 case StaticGray:
3507 case GrayScale:
3508 return Qt;
3510 default:
3511 return Qnil;
3515 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3516 0, 1, 0,
3517 doc: /* Returns the width in pixels of the X display DISPLAY.
3518 The optional argument DISPLAY specifies which display to ask about.
3519 DISPLAY should be either a frame or a display name (a string).
3520 If omitted or nil, that stands for the selected frame's display. */)
3521 (display)
3522 Lisp_Object display;
3524 struct x_display_info *dpyinfo = check_x_display_info (display);
3526 return make_number (dpyinfo->width);
3529 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3530 Sx_display_pixel_height, 0, 1, 0,
3531 doc: /* Returns the height in pixels of the X display DISPLAY.
3532 The optional argument DISPLAY specifies which display to ask about.
3533 DISPLAY should be either a frame or a display name (a string).
3534 If omitted or nil, that stands for the selected frame's display. */)
3535 (display)
3536 Lisp_Object display;
3538 struct x_display_info *dpyinfo = check_x_display_info (display);
3540 return make_number (dpyinfo->height);
3543 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3544 0, 1, 0,
3545 doc: /* Returns the number of bitplanes of the X display DISPLAY.
3546 The optional argument DISPLAY specifies which display to ask about.
3547 DISPLAY should be either a frame or a display name (a string).
3548 If omitted or nil, that stands for the selected frame's display. */)
3549 (display)
3550 Lisp_Object display;
3552 struct x_display_info *dpyinfo = check_x_display_info (display);
3554 return make_number (dpyinfo->n_planes);
3557 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3558 0, 1, 0,
3559 doc: /* Returns the number of color cells of the X display DISPLAY.
3560 The optional argument DISPLAY specifies which display to ask about.
3561 DISPLAY should be either a frame or a display name (a string).
3562 If omitted or nil, that stands for the selected frame's display. */)
3563 (display)
3564 Lisp_Object display;
3566 struct x_display_info *dpyinfo = check_x_display_info (display);
3568 return make_number (DisplayCells (dpyinfo->display,
3569 XScreenNumberOfScreen (dpyinfo->screen)));
3572 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3573 Sx_server_max_request_size,
3574 0, 1, 0,
3575 doc: /* Returns the maximum request size of the X server of display DISPLAY.
3576 The optional argument DISPLAY specifies which display to ask about.
3577 DISPLAY should be either a frame or a display name (a string).
3578 If omitted or nil, that stands for the selected frame's display. */)
3579 (display)
3580 Lisp_Object display;
3582 struct x_display_info *dpyinfo = check_x_display_info (display);
3584 return make_number (MAXREQUEST (dpyinfo->display));
3587 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3588 doc: /* Returns the vendor ID string of the X server of display DISPLAY.
3589 The optional argument DISPLAY specifies which display to ask about.
3590 DISPLAY should be either a frame or a display name (a string).
3591 If omitted or nil, that stands for the selected frame's display. */)
3592 (display)
3593 Lisp_Object display;
3595 struct x_display_info *dpyinfo = check_x_display_info (display);
3596 char *vendor = ServerVendor (dpyinfo->display);
3598 if (! vendor) vendor = "";
3599 return build_string (vendor);
3602 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3603 doc: /* Returns the version numbers of the X server of display DISPLAY.
3604 The value is a list of three integers: the major and minor
3605 version numbers of the X Protocol in use, and the vendor-specific release
3606 number. See also the function `x-server-vendor'.
3608 The optional argument DISPLAY specifies which display to ask about.
3609 DISPLAY should be either a frame or a display name (a string).
3610 If omitted or nil, that stands for the selected frame's display. */)
3611 (display)
3612 Lisp_Object display;
3614 struct x_display_info *dpyinfo = check_x_display_info (display);
3615 Display *dpy = dpyinfo->display;
3617 return Fcons (make_number (ProtocolVersion (dpy)),
3618 Fcons (make_number (ProtocolRevision (dpy)),
3619 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3622 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3623 doc: /* Return the number of screens on the X server of display DISPLAY.
3624 The optional argument DISPLAY specifies which display to ask about.
3625 DISPLAY should be either a frame or a display name (a string).
3626 If omitted or nil, that stands for the selected frame's display. */)
3627 (display)
3628 Lisp_Object display;
3630 struct x_display_info *dpyinfo = check_x_display_info (display);
3632 return make_number (ScreenCount (dpyinfo->display));
3635 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3636 doc: /* Return the height in millimeters of the X display DISPLAY.
3637 The optional argument DISPLAY specifies which display to ask about.
3638 DISPLAY should be either a frame or a display name (a string).
3639 If omitted or nil, that stands for the selected frame's display. */)
3640 (display)
3641 Lisp_Object display;
3643 struct x_display_info *dpyinfo = check_x_display_info (display);
3645 return make_number (HeightMMOfScreen (dpyinfo->screen));
3648 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3649 doc: /* Return the width in millimeters of the X display DISPLAY.
3650 The optional argument DISPLAY specifies which display to ask about.
3651 DISPLAY should be either a frame or a display name (a string).
3652 If omitted or nil, that stands for the selected frame's display. */)
3653 (display)
3654 Lisp_Object display;
3656 struct x_display_info *dpyinfo = check_x_display_info (display);
3658 return make_number (WidthMMOfScreen (dpyinfo->screen));
3661 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3662 Sx_display_backing_store, 0, 1, 0,
3663 doc: /* Returns an indication of whether X display DISPLAY does backing store.
3664 The value may be `always', `when-mapped', or `not-useful'.
3665 The optional argument DISPLAY specifies which display to ask about.
3666 DISPLAY should be either a frame or a display name (a string).
3667 If omitted or nil, that stands for the selected frame's display. */)
3668 (display)
3669 Lisp_Object display;
3671 struct x_display_info *dpyinfo = check_x_display_info (display);
3672 Lisp_Object result;
3674 switch (DoesBackingStore (dpyinfo->screen))
3676 case Always:
3677 result = intern ("always");
3678 break;
3680 case WhenMapped:
3681 result = intern ("when-mapped");
3682 break;
3684 case NotUseful:
3685 result = intern ("not-useful");
3686 break;
3688 default:
3689 error ("Strange value for BackingStore parameter of screen");
3690 result = Qnil;
3693 return result;
3696 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3697 Sx_display_visual_class, 0, 1, 0,
3698 doc: /* Return the visual class of the X display DISPLAY.
3699 The value is one of the symbols `static-gray', `gray-scale',
3700 `static-color', `pseudo-color', `true-color', or `direct-color'.
3702 The optional argument DISPLAY specifies which display to ask about.
3703 DISPLAY should be either a frame or a display name (a string).
3704 If omitted or nil, that stands for the selected frame's display. */)
3705 (display)
3706 Lisp_Object display;
3708 struct x_display_info *dpyinfo = check_x_display_info (display);
3709 Lisp_Object result;
3711 switch (dpyinfo->visual->class)
3713 case StaticGray:
3714 result = intern ("static-gray");
3715 break;
3716 case GrayScale:
3717 result = intern ("gray-scale");
3718 break;
3719 case StaticColor:
3720 result = intern ("static-color");
3721 break;
3722 case PseudoColor:
3723 result = intern ("pseudo-color");
3724 break;
3725 case TrueColor:
3726 result = intern ("true-color");
3727 break;
3728 case DirectColor:
3729 result = intern ("direct-color");
3730 break;
3731 default:
3732 error ("Display has an unknown visual class");
3733 result = Qnil;
3736 return result;
3739 DEFUN ("x-display-save-under", Fx_display_save_under,
3740 Sx_display_save_under, 0, 1, 0,
3741 doc: /* Returns t if the X display DISPLAY supports the save-under feature.
3742 The optional argument DISPLAY specifies which display to ask about.
3743 DISPLAY should be either a frame or a display name (a string).
3744 If omitted or nil, that stands for the selected frame's display. */)
3745 (display)
3746 Lisp_Object display;
3748 struct x_display_info *dpyinfo = check_x_display_info (display);
3750 if (DoesSaveUnders (dpyinfo->screen) == True)
3751 return Qt;
3752 else
3753 return Qnil;
3757 x_pixel_width (f)
3758 register struct frame *f;
3760 return FRAME_PIXEL_WIDTH (f);
3764 x_pixel_height (f)
3765 register struct frame *f;
3767 return FRAME_PIXEL_HEIGHT (f);
3771 x_char_width (f)
3772 register struct frame *f;
3774 return FRAME_COLUMN_WIDTH (f);
3778 x_char_height (f)
3779 register struct frame *f;
3781 return FRAME_LINE_HEIGHT (f);
3785 x_screen_planes (f)
3786 register struct frame *f;
3788 return FRAME_X_DISPLAY_INFO (f)->n_planes;
3793 /************************************************************************
3794 X Displays
3795 ************************************************************************/
3798 /* Mapping visual names to visuals. */
3800 static struct visual_class
3802 char *name;
3803 int class;
3805 visual_classes[] =
3807 {"StaticGray", StaticGray},
3808 {"GrayScale", GrayScale},
3809 {"StaticColor", StaticColor},
3810 {"PseudoColor", PseudoColor},
3811 {"TrueColor", TrueColor},
3812 {"DirectColor", DirectColor},
3813 {NULL, 0}
3817 #ifndef HAVE_XSCREENNUMBEROFSCREEN
3819 /* Value is the screen number of screen SCR. This is a substitute for
3820 the X function with the same name when that doesn't exist. */
3823 XScreenNumberOfScreen (scr)
3824 register Screen *scr;
3826 Display *dpy = scr->display;
3827 int i;
3829 for (i = 0; i < dpy->nscreens; ++i)
3830 if (scr == dpy->screens + i)
3831 break;
3833 return i;
3836 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3839 /* Select the visual that should be used on display DPYINFO. Set
3840 members of DPYINFO appropriately. Called from x_term_init. */
3842 void
3843 select_visual (dpyinfo)
3844 struct x_display_info *dpyinfo;
3846 Display *dpy = dpyinfo->display;
3847 Screen *screen = dpyinfo->screen;
3848 Lisp_Object value;
3850 /* See if a visual is specified. */
3851 value = display_x_get_resource (dpyinfo,
3852 build_string ("visualClass"),
3853 build_string ("VisualClass"),
3854 Qnil, Qnil);
3855 if (STRINGP (value))
3857 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
3858 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
3859 depth, a decimal number. NAME is compared with case ignored. */
3860 char *s = (char *) alloca (SBYTES (value) + 1);
3861 char *dash;
3862 int i, class = -1;
3863 XVisualInfo vinfo;
3865 strcpy (s, SDATA (value));
3866 dash = index (s, '-');
3867 if (dash)
3869 dpyinfo->n_planes = atoi (dash + 1);
3870 *dash = '\0';
3872 else
3873 /* We won't find a matching visual with depth 0, so that
3874 an error will be printed below. */
3875 dpyinfo->n_planes = 0;
3877 /* Determine the visual class. */
3878 for (i = 0; visual_classes[i].name; ++i)
3879 if (xstricmp (s, visual_classes[i].name) == 0)
3881 class = visual_classes[i].class;
3882 break;
3885 /* Look up a matching visual for the specified class. */
3886 if (class == -1
3887 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
3888 dpyinfo->n_planes, class, &vinfo))
3889 fatal ("Invalid visual specification `%s'", SDATA (value));
3891 dpyinfo->visual = vinfo.visual;
3893 else
3895 int n_visuals;
3896 XVisualInfo *vinfo, vinfo_template;
3898 dpyinfo->visual = DefaultVisualOfScreen (screen);
3900 #ifdef HAVE_X11R4
3901 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
3902 #else
3903 vinfo_template.visualid = dpyinfo->visual->visualid;
3904 #endif
3905 vinfo_template.screen = XScreenNumberOfScreen (screen);
3906 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
3907 &vinfo_template, &n_visuals);
3908 if (n_visuals != 1)
3909 fatal ("Can't get proper X visual info");
3911 dpyinfo->n_planes = vinfo->depth;
3912 XFree ((char *) vinfo);
3917 /* Return the X display structure for the display named NAME.
3918 Open a new connection if necessary. */
3920 struct x_display_info *
3921 x_display_info_for_name (name)
3922 Lisp_Object name;
3924 Lisp_Object names;
3925 struct x_display_info *dpyinfo;
3927 CHECK_STRING (name);
3929 if (! EQ (Vwindow_system, intern ("x")))
3930 error ("Not using X Windows");
3932 for (dpyinfo = x_display_list, names = x_display_name_list;
3933 dpyinfo;
3934 dpyinfo = dpyinfo->next, names = XCDR (names))
3936 Lisp_Object tem;
3937 tem = Fstring_equal (XCAR (XCAR (names)), name);
3938 if (!NILP (tem))
3939 return dpyinfo;
3942 /* Use this general default value to start with. */
3943 Vx_resource_name = Vinvocation_name;
3945 validate_x_resource_name ();
3947 dpyinfo = x_term_init (name, (char *)0,
3948 (char *) SDATA (Vx_resource_name));
3950 if (dpyinfo == 0)
3951 error ("Cannot connect to X server %s", SDATA (name));
3953 x_in_use = 1;
3954 XSETFASTINT (Vwindow_system_version, 11);
3956 return dpyinfo;
3960 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3961 1, 3, 0,
3962 doc: /* Open a connection to an X server.
3963 DISPLAY is the name of the display to connect to.
3964 Optional second arg XRM-STRING is a string of resources in xrdb format.
3965 If the optional third arg MUST-SUCCEED is non-nil,
3966 terminate Emacs if we can't open the connection. */)
3967 (display, xrm_string, must_succeed)
3968 Lisp_Object display, xrm_string, must_succeed;
3970 unsigned char *xrm_option;
3971 struct x_display_info *dpyinfo;
3973 CHECK_STRING (display);
3974 if (! NILP (xrm_string))
3975 CHECK_STRING (xrm_string);
3977 if (! EQ (Vwindow_system, intern ("x")))
3978 error ("Not using X Windows");
3980 if (! NILP (xrm_string))
3981 xrm_option = (unsigned char *) SDATA (xrm_string);
3982 else
3983 xrm_option = (unsigned char *) 0;
3985 validate_x_resource_name ();
3987 /* This is what opens the connection and sets x_current_display.
3988 This also initializes many symbols, such as those used for input. */
3989 dpyinfo = x_term_init (display, xrm_option,
3990 (char *) SDATA (Vx_resource_name));
3992 if (dpyinfo == 0)
3994 if (!NILP (must_succeed))
3995 fatal ("Cannot connect to X server %s.\n\
3996 Check the DISPLAY environment variable or use `-d'.\n\
3997 Also use the `xauth' program to verify that you have the proper\n\
3998 authorization information needed to connect the X server.\n\
3999 An insecure way to solve the problem may be to use `xhost'.\n",
4000 SDATA (display));
4001 else
4002 error ("Cannot connect to X server %s", SDATA (display));
4005 x_in_use = 1;
4007 XSETFASTINT (Vwindow_system_version, 11);
4008 return Qnil;
4011 DEFUN ("x-close-connection", Fx_close_connection,
4012 Sx_close_connection, 1, 1, 0,
4013 doc: /* Close the connection to DISPLAY's X server.
4014 For DISPLAY, specify either a frame or a display name (a string).
4015 If DISPLAY is nil, that stands for the selected frame's display. */)
4016 (display)
4017 Lisp_Object display;
4019 struct x_display_info *dpyinfo = check_x_display_info (display);
4020 int i;
4022 if (dpyinfo->reference_count > 0)
4023 error ("Display still has frames on it");
4025 BLOCK_INPUT;
4026 /* Free the fonts in the font table. */
4027 for (i = 0; i < dpyinfo->n_fonts; i++)
4028 if (dpyinfo->font_table[i].name)
4030 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4031 xfree (dpyinfo->font_table[i].full_name);
4032 xfree (dpyinfo->font_table[i].name);
4033 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4036 x_destroy_all_bitmaps (dpyinfo);
4037 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4039 #ifdef USE_X_TOOLKIT
4040 XtCloseDisplay (dpyinfo->display);
4041 #else
4042 XCloseDisplay (dpyinfo->display);
4043 #endif
4045 x_delete_display (dpyinfo);
4046 UNBLOCK_INPUT;
4048 return Qnil;
4051 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
4052 doc: /* Return the list of display names that Emacs has connections to. */)
4055 Lisp_Object tail, result;
4057 result = Qnil;
4058 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
4059 result = Fcons (XCAR (XCAR (tail)), result);
4061 return result;
4064 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
4065 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
4066 If ON is nil, allow buffering of requests.
4067 Turning on synchronization prohibits the Xlib routines from buffering
4068 requests and seriously degrades performance, but makes debugging much
4069 easier.
4070 The optional second argument DISPLAY specifies which display to act on.
4071 DISPLAY should be either a frame or a display name (a string).
4072 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
4073 (on, display)
4074 Lisp_Object display, on;
4076 struct x_display_info *dpyinfo = check_x_display_info (display);
4078 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
4080 return Qnil;
4083 /* Wait for responses to all X commands issued so far for frame F. */
4085 void
4086 x_sync (f)
4087 FRAME_PTR f;
4089 BLOCK_INPUT;
4090 XSync (FRAME_X_DISPLAY (f), False);
4091 UNBLOCK_INPUT;
4095 /***********************************************************************
4096 Image types
4097 ***********************************************************************/
4099 /* Value is the number of elements of vector VECTOR. */
4101 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4103 /* List of supported image types. Use define_image_type to add new
4104 types. Use lookup_image_type to find a type for a given symbol. */
4106 static struct image_type *image_types;
4108 /* The symbol `image' which is the car of the lists used to represent
4109 images in Lisp. */
4111 extern Lisp_Object Qimage;
4113 /* The symbol `xbm' which is used as the type symbol for XBM images. */
4115 Lisp_Object Qxbm;
4117 /* Keywords. */
4119 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
4120 extern Lisp_Object QCdata, QCtype;
4121 Lisp_Object QCascent, QCmargin, QCrelief;
4122 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
4123 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
4125 /* Other symbols. */
4127 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
4129 /* Time in seconds after which images should be removed from the cache
4130 if not displayed. */
4132 Lisp_Object Vimage_cache_eviction_delay;
4134 /* Function prototypes. */
4136 static void define_image_type P_ ((struct image_type *type));
4137 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
4138 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
4139 static void x_laplace P_ ((struct frame *, struct image *));
4140 static void x_emboss P_ ((struct frame *, struct image *));
4141 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
4142 Lisp_Object));
4145 /* Define a new image type from TYPE. This adds a copy of TYPE to
4146 image_types and adds the symbol *TYPE->type to Vimage_types. */
4148 static void
4149 define_image_type (type)
4150 struct image_type *type;
4152 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
4153 The initialized data segment is read-only. */
4154 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
4155 bcopy (type, p, sizeof *p);
4156 p->next = image_types;
4157 image_types = p;
4158 Vimage_types = Fcons (*p->type, Vimage_types);
4162 /* Look up image type SYMBOL, and return a pointer to its image_type
4163 structure. Value is null if SYMBOL is not a known image type. */
4165 static INLINE struct image_type *
4166 lookup_image_type (symbol)
4167 Lisp_Object symbol;
4169 struct image_type *type;
4171 for (type = image_types; type; type = type->next)
4172 if (EQ (symbol, *type->type))
4173 break;
4175 return type;
4179 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
4180 valid image specification is a list whose car is the symbol
4181 `image', and whose rest is a property list. The property list must
4182 contain a value for key `:type'. That value must be the name of a
4183 supported image type. The rest of the property list depends on the
4184 image type. */
4187 valid_image_p (object)
4188 Lisp_Object object;
4190 int valid_p = 0;
4192 if (CONSP (object) && EQ (XCAR (object), Qimage))
4194 Lisp_Object tem;
4196 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
4197 if (EQ (XCAR (tem), QCtype))
4199 tem = XCDR (tem);
4200 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
4202 struct image_type *type;
4203 type = lookup_image_type (XCAR (tem));
4204 if (type)
4205 valid_p = type->valid_p (object);
4208 break;
4212 return valid_p;
4216 /* Log error message with format string FORMAT and argument ARG.
4217 Signaling an error, e.g. when an image cannot be loaded, is not a
4218 good idea because this would interrupt redisplay, and the error
4219 message display would lead to another redisplay. This function
4220 therefore simply displays a message. */
4222 static void
4223 image_error (format, arg1, arg2)
4224 char *format;
4225 Lisp_Object arg1, arg2;
4227 add_to_log (format, arg1, arg2);
4232 /***********************************************************************
4233 Image specifications
4234 ***********************************************************************/
4236 enum image_value_type
4238 IMAGE_DONT_CHECK_VALUE_TYPE,
4239 IMAGE_STRING_VALUE,
4240 IMAGE_STRING_OR_NIL_VALUE,
4241 IMAGE_SYMBOL_VALUE,
4242 IMAGE_POSITIVE_INTEGER_VALUE,
4243 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
4244 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
4245 IMAGE_ASCENT_VALUE,
4246 IMAGE_INTEGER_VALUE,
4247 IMAGE_FUNCTION_VALUE,
4248 IMAGE_NUMBER_VALUE,
4249 IMAGE_BOOL_VALUE
4252 /* Structure used when parsing image specifications. */
4254 struct image_keyword
4256 /* Name of keyword. */
4257 char *name;
4259 /* The type of value allowed. */
4260 enum image_value_type type;
4262 /* Non-zero means key must be present. */
4263 int mandatory_p;
4265 /* Used to recognize duplicate keywords in a property list. */
4266 int count;
4268 /* The value that was found. */
4269 Lisp_Object value;
4273 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
4274 int, Lisp_Object));
4275 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
4278 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
4279 has the format (image KEYWORD VALUE ...). One of the keyword/
4280 value pairs must be `:type TYPE'. KEYWORDS is a vector of
4281 image_keywords structures of size NKEYWORDS describing other
4282 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
4284 static int
4285 parse_image_spec (spec, keywords, nkeywords, type)
4286 Lisp_Object spec;
4287 struct image_keyword *keywords;
4288 int nkeywords;
4289 Lisp_Object type;
4291 int i;
4292 Lisp_Object plist;
4294 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
4295 return 0;
4297 plist = XCDR (spec);
4298 while (CONSP (plist))
4300 Lisp_Object key, value;
4302 /* First element of a pair must be a symbol. */
4303 key = XCAR (plist);
4304 plist = XCDR (plist);
4305 if (!SYMBOLP (key))
4306 return 0;
4308 /* There must follow a value. */
4309 if (!CONSP (plist))
4310 return 0;
4311 value = XCAR (plist);
4312 plist = XCDR (plist);
4314 /* Find key in KEYWORDS. Error if not found. */
4315 for (i = 0; i < nkeywords; ++i)
4316 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
4317 break;
4319 if (i == nkeywords)
4320 continue;
4322 /* Record that we recognized the keyword. If a keywords
4323 was found more than once, it's an error. */
4324 keywords[i].value = value;
4325 ++keywords[i].count;
4327 if (keywords[i].count > 1)
4328 return 0;
4330 /* Check type of value against allowed type. */
4331 switch (keywords[i].type)
4333 case IMAGE_STRING_VALUE:
4334 if (!STRINGP (value))
4335 return 0;
4336 break;
4338 case IMAGE_STRING_OR_NIL_VALUE:
4339 if (!STRINGP (value) && !NILP (value))
4340 return 0;
4341 break;
4343 case IMAGE_SYMBOL_VALUE:
4344 if (!SYMBOLP (value))
4345 return 0;
4346 break;
4348 case IMAGE_POSITIVE_INTEGER_VALUE:
4349 if (!INTEGERP (value) || XINT (value) <= 0)
4350 return 0;
4351 break;
4353 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
4354 if (INTEGERP (value) && XINT (value) >= 0)
4355 break;
4356 if (CONSP (value)
4357 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
4358 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
4359 break;
4360 return 0;
4362 case IMAGE_ASCENT_VALUE:
4363 if (SYMBOLP (value) && EQ (value, Qcenter))
4364 break;
4365 else if (INTEGERP (value)
4366 && XINT (value) >= 0
4367 && XINT (value) <= 100)
4368 break;
4369 return 0;
4371 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
4372 if (!INTEGERP (value) || XINT (value) < 0)
4373 return 0;
4374 break;
4376 case IMAGE_DONT_CHECK_VALUE_TYPE:
4377 break;
4379 case IMAGE_FUNCTION_VALUE:
4380 value = indirect_function (value);
4381 if (SUBRP (value)
4382 || COMPILEDP (value)
4383 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
4384 break;
4385 return 0;
4387 case IMAGE_NUMBER_VALUE:
4388 if (!INTEGERP (value) && !FLOATP (value))
4389 return 0;
4390 break;
4392 case IMAGE_INTEGER_VALUE:
4393 if (!INTEGERP (value))
4394 return 0;
4395 break;
4397 case IMAGE_BOOL_VALUE:
4398 if (!NILP (value) && !EQ (value, Qt))
4399 return 0;
4400 break;
4402 default:
4403 abort ();
4404 break;
4407 if (EQ (key, QCtype) && !EQ (type, value))
4408 return 0;
4411 /* Check that all mandatory fields are present. */
4412 for (i = 0; i < nkeywords; ++i)
4413 if (keywords[i].mandatory_p && keywords[i].count == 0)
4414 return 0;
4416 return NILP (plist);
4420 /* Return the value of KEY in image specification SPEC. Value is nil
4421 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
4422 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
4424 static Lisp_Object
4425 image_spec_value (spec, key, found)
4426 Lisp_Object spec, key;
4427 int *found;
4429 Lisp_Object tail;
4431 xassert (valid_image_p (spec));
4433 for (tail = XCDR (spec);
4434 CONSP (tail) && CONSP (XCDR (tail));
4435 tail = XCDR (XCDR (tail)))
4437 if (EQ (XCAR (tail), key))
4439 if (found)
4440 *found = 1;
4441 return XCAR (XCDR (tail));
4445 if (found)
4446 *found = 0;
4447 return Qnil;
4451 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
4452 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
4453 PIXELS non-nil means return the size in pixels, otherwise return the
4454 size in canonical character units.
4455 FRAME is the frame on which the image will be displayed. FRAME nil
4456 or omitted means use the selected frame. */)
4457 (spec, pixels, frame)
4458 Lisp_Object spec, pixels, frame;
4460 Lisp_Object size;
4462 size = Qnil;
4463 if (valid_image_p (spec))
4465 struct frame *f = check_x_frame (frame);
4466 int id = lookup_image (f, spec);
4467 struct image *img = IMAGE_FROM_ID (f, id);
4468 int width = img->width + 2 * img->hmargin;
4469 int height = img->height + 2 * img->vmargin;
4471 if (NILP (pixels))
4472 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
4473 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
4474 else
4475 size = Fcons (make_number (width), make_number (height));
4477 else
4478 error ("Invalid image specification");
4480 return size;
4484 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
4485 doc: /* Return t if image SPEC has a mask bitmap.
4486 FRAME is the frame on which the image will be displayed. FRAME nil
4487 or omitted means use the selected frame. */)
4488 (spec, frame)
4489 Lisp_Object spec, frame;
4491 Lisp_Object mask;
4493 mask = Qnil;
4494 if (valid_image_p (spec))
4496 struct frame *f = check_x_frame (frame);
4497 int id = lookup_image (f, spec);
4498 struct image *img = IMAGE_FROM_ID (f, id);
4499 if (img->mask)
4500 mask = Qt;
4502 else
4503 error ("Invalid image specification");
4505 return mask;
4510 /***********************************************************************
4511 Image type independent image structures
4512 ***********************************************************************/
4514 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
4515 static void free_image P_ ((struct frame *f, struct image *img));
4518 /* Allocate and return a new image structure for image specification
4519 SPEC. SPEC has a hash value of HASH. */
4521 static struct image *
4522 make_image (spec, hash)
4523 Lisp_Object spec;
4524 unsigned hash;
4526 struct image *img = (struct image *) xmalloc (sizeof *img);
4528 xassert (valid_image_p (spec));
4529 bzero (img, sizeof *img);
4530 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
4531 xassert (img->type != NULL);
4532 img->spec = spec;
4533 img->data.lisp_val = Qnil;
4534 img->ascent = DEFAULT_IMAGE_ASCENT;
4535 img->hash = hash;
4536 return img;
4540 /* Free image IMG which was used on frame F, including its resources. */
4542 static void
4543 free_image (f, img)
4544 struct frame *f;
4545 struct image *img;
4547 if (img)
4549 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4551 /* Remove IMG from the hash table of its cache. */
4552 if (img->prev)
4553 img->prev->next = img->next;
4554 else
4555 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
4557 if (img->next)
4558 img->next->prev = img->prev;
4560 c->images[img->id] = NULL;
4562 /* Free resources, then free IMG. */
4563 img->type->free (f, img);
4564 xfree (img);
4569 /* Prepare image IMG for display on frame F. Must be called before
4570 drawing an image. */
4572 void
4573 prepare_image_for_display (f, img)
4574 struct frame *f;
4575 struct image *img;
4577 EMACS_TIME t;
4579 /* We're about to display IMG, so set its timestamp to `now'. */
4580 EMACS_GET_TIME (t);
4581 img->timestamp = EMACS_SECS (t);
4583 /* If IMG doesn't have a pixmap yet, load it now, using the image
4584 type dependent loader function. */
4585 if (img->pixmap == None && !img->load_failed_p)
4586 img->load_failed_p = img->type->load (f, img) == 0;
4590 /* Value is the number of pixels for the ascent of image IMG when
4591 drawn in face FACE. */
4594 image_ascent (img, face)
4595 struct image *img;
4596 struct face *face;
4598 int height = img->height + img->vmargin;
4599 int ascent;
4601 if (img->ascent == CENTERED_IMAGE_ASCENT)
4603 if (face->font)
4604 /* This expression is arranged so that if the image can't be
4605 exactly centered, it will be moved slightly up. This is
4606 because a typical font is `top-heavy' (due to the presence
4607 uppercase letters), so the image placement should err towards
4608 being top-heavy too. It also just generally looks better. */
4609 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
4610 else
4611 ascent = height / 2;
4613 else
4614 ascent = height * img->ascent / 100.0;
4616 return ascent;
4620 /* Image background colors. */
4622 static unsigned long
4623 four_corners_best (ximg, width, height)
4624 XImage *ximg;
4625 unsigned long width, height;
4627 unsigned long corners[4], best;
4628 int i, best_count;
4630 /* Get the colors at the corners of ximg. */
4631 corners[0] = XGetPixel (ximg, 0, 0);
4632 corners[1] = XGetPixel (ximg, width - 1, 0);
4633 corners[2] = XGetPixel (ximg, width - 1, height - 1);
4634 corners[3] = XGetPixel (ximg, 0, height - 1);
4636 /* Choose the most frequently found color as background. */
4637 for (i = best_count = 0; i < 4; ++i)
4639 int j, n;
4641 for (j = n = 0; j < 4; ++j)
4642 if (corners[i] == corners[j])
4643 ++n;
4645 if (n > best_count)
4646 best = corners[i], best_count = n;
4649 return best;
4652 /* Return the `background' field of IMG. If IMG doesn't have one yet,
4653 it is guessed heuristically. If non-zero, XIMG is an existing XImage
4654 object to use for the heuristic. */
4656 unsigned long
4657 image_background (img, f, ximg)
4658 struct image *img;
4659 struct frame *f;
4660 XImage *ximg;
4662 if (! img->background_valid)
4663 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4665 int free_ximg = !ximg;
4667 if (! ximg)
4668 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4669 0, 0, img->width, img->height, ~0, ZPixmap);
4671 img->background = four_corners_best (ximg, img->width, img->height);
4673 if (free_ximg)
4674 XDestroyImage (ximg);
4676 img->background_valid = 1;
4679 return img->background;
4682 /* Return the `background_transparent' field of IMG. If IMG doesn't
4683 have one yet, it is guessed heuristically. If non-zero, MASK is an
4684 existing XImage object to use for the heuristic. */
4687 image_background_transparent (img, f, mask)
4688 struct image *img;
4689 struct frame *f;
4690 XImage *mask;
4692 if (! img->background_transparent_valid)
4693 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4695 if (img->mask)
4697 int free_mask = !mask;
4699 if (! mask)
4700 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
4701 0, 0, img->width, img->height, ~0, ZPixmap);
4703 img->background_transparent
4704 = !four_corners_best (mask, img->width, img->height);
4706 if (free_mask)
4707 XDestroyImage (mask);
4709 else
4710 img->background_transparent = 0;
4712 img->background_transparent_valid = 1;
4715 return img->background_transparent;
4719 /***********************************************************************
4720 Helper functions for X image types
4721 ***********************************************************************/
4723 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
4724 int, int));
4725 static void x_clear_image P_ ((struct frame *f, struct image *img));
4726 static unsigned long x_alloc_image_color P_ ((struct frame *f,
4727 struct image *img,
4728 Lisp_Object color_name,
4729 unsigned long dflt));
4732 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
4733 free the pixmap if any. MASK_P non-zero means clear the mask
4734 pixmap if any. COLORS_P non-zero means free colors allocated for
4735 the image, if any. */
4737 static void
4738 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
4739 struct frame *f;
4740 struct image *img;
4741 int pixmap_p, mask_p, colors_p;
4743 if (pixmap_p && img->pixmap)
4745 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
4746 img->pixmap = None;
4747 img->background_valid = 0;
4750 if (mask_p && img->mask)
4752 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4753 img->mask = None;
4754 img->background_transparent_valid = 0;
4757 if (colors_p && img->ncolors)
4759 x_free_colors (f, img->colors, img->ncolors);
4760 xfree (img->colors);
4761 img->colors = NULL;
4762 img->ncolors = 0;
4766 /* Free X resources of image IMG which is used on frame F. */
4768 static void
4769 x_clear_image (f, img)
4770 struct frame *f;
4771 struct image *img;
4773 BLOCK_INPUT;
4774 x_clear_image_1 (f, img, 1, 1, 1);
4775 UNBLOCK_INPUT;
4779 /* Allocate color COLOR_NAME for image IMG on frame F. If color
4780 cannot be allocated, use DFLT. Add a newly allocated color to
4781 IMG->colors, so that it can be freed again. Value is the pixel
4782 color. */
4784 static unsigned long
4785 x_alloc_image_color (f, img, color_name, dflt)
4786 struct frame *f;
4787 struct image *img;
4788 Lisp_Object color_name;
4789 unsigned long dflt;
4791 XColor color;
4792 unsigned long result;
4794 xassert (STRINGP (color_name));
4796 if (x_defined_color (f, SDATA (color_name), &color, 1))
4798 /* This isn't called frequently so we get away with simply
4799 reallocating the color vector to the needed size, here. */
4800 ++img->ncolors;
4801 img->colors =
4802 (unsigned long *) xrealloc (img->colors,
4803 img->ncolors * sizeof *img->colors);
4804 img->colors[img->ncolors - 1] = color.pixel;
4805 result = color.pixel;
4807 else
4808 result = dflt;
4810 return result;
4815 /***********************************************************************
4816 Image Cache
4817 ***********************************************************************/
4819 static void cache_image P_ ((struct frame *f, struct image *img));
4820 static void postprocess_image P_ ((struct frame *, struct image *));
4823 /* Return a new, initialized image cache that is allocated from the
4824 heap. Call free_image_cache to free an image cache. */
4826 struct image_cache *
4827 make_image_cache ()
4829 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
4830 int size;
4832 bzero (c, sizeof *c);
4833 c->size = 50;
4834 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
4835 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4836 c->buckets = (struct image **) xmalloc (size);
4837 bzero (c->buckets, size);
4838 return c;
4842 /* Free image cache of frame F. Be aware that X frames share images
4843 caches. */
4845 void
4846 free_image_cache (f)
4847 struct frame *f;
4849 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4850 if (c)
4852 int i;
4854 /* Cache should not be referenced by any frame when freed. */
4855 xassert (c->refcount == 0);
4857 for (i = 0; i < c->used; ++i)
4858 free_image (f, c->images[i]);
4859 xfree (c->images);
4860 xfree (c->buckets);
4861 xfree (c);
4862 FRAME_X_IMAGE_CACHE (f) = NULL;
4867 /* Clear image cache of frame F. FORCE_P non-zero means free all
4868 images. FORCE_P zero means clear only images that haven't been
4869 displayed for some time. Should be called from time to time to
4870 reduce the number of loaded images. If image-eviction-seconds is
4871 non-nil, this frees images in the cache which weren't displayed for
4872 at least that many seconds. */
4874 void
4875 clear_image_cache (f, force_p)
4876 struct frame *f;
4877 int force_p;
4879 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4881 if (c && INTEGERP (Vimage_cache_eviction_delay))
4883 EMACS_TIME t;
4884 unsigned long old;
4885 int i, nfreed;
4887 EMACS_GET_TIME (t);
4888 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
4890 /* Block input so that we won't be interrupted by a SIGIO
4891 while being in an inconsistent state. */
4892 BLOCK_INPUT;
4894 for (i = nfreed = 0; i < c->used; ++i)
4896 struct image *img = c->images[i];
4897 if (img != NULL
4898 && (force_p || img->timestamp < old))
4900 free_image (f, img);
4901 ++nfreed;
4905 /* We may be clearing the image cache because, for example,
4906 Emacs was iconified for a longer period of time. In that
4907 case, current matrices may still contain references to
4908 images freed above. So, clear these matrices. */
4909 if (nfreed)
4911 Lisp_Object tail, frame;
4913 FOR_EACH_FRAME (tail, frame)
4915 struct frame *f = XFRAME (frame);
4916 if (FRAME_X_P (f)
4917 && FRAME_X_IMAGE_CACHE (f) == c)
4918 clear_current_matrices (f);
4921 ++windows_or_buffers_changed;
4924 UNBLOCK_INPUT;
4929 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
4930 0, 1, 0,
4931 doc: /* Clear the image cache of FRAME.
4932 FRAME nil or omitted means use the selected frame.
4933 FRAME t means clear the image caches of all frames. */)
4934 (frame)
4935 Lisp_Object frame;
4937 if (EQ (frame, Qt))
4939 Lisp_Object tail;
4941 FOR_EACH_FRAME (tail, frame)
4942 if (FRAME_X_P (XFRAME (frame)))
4943 clear_image_cache (XFRAME (frame), 1);
4945 else
4946 clear_image_cache (check_x_frame (frame), 1);
4948 return Qnil;
4952 /* Compute masks and transform image IMG on frame F, as specified
4953 by the image's specification, */
4955 static void
4956 postprocess_image (f, img)
4957 struct frame *f;
4958 struct image *img;
4960 /* Manipulation of the image's mask. */
4961 if (img->pixmap)
4963 Lisp_Object conversion, spec;
4964 Lisp_Object mask;
4966 spec = img->spec;
4968 /* `:heuristic-mask t'
4969 `:mask heuristic'
4970 means build a mask heuristically.
4971 `:heuristic-mask (R G B)'
4972 `:mask (heuristic (R G B))'
4973 means build a mask from color (R G B) in the
4974 image.
4975 `:mask nil'
4976 means remove a mask, if any. */
4978 mask = image_spec_value (spec, QCheuristic_mask, NULL);
4979 if (!NILP (mask))
4980 x_build_heuristic_mask (f, img, mask);
4981 else
4983 int found_p;
4985 mask = image_spec_value (spec, QCmask, &found_p);
4987 if (EQ (mask, Qheuristic))
4988 x_build_heuristic_mask (f, img, Qt);
4989 else if (CONSP (mask)
4990 && EQ (XCAR (mask), Qheuristic))
4992 if (CONSP (XCDR (mask)))
4993 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
4994 else
4995 x_build_heuristic_mask (f, img, XCDR (mask));
4997 else if (NILP (mask) && found_p && img->mask)
4999 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5000 img->mask = None;
5005 /* Should we apply an image transformation algorithm? */
5006 conversion = image_spec_value (spec, QCconversion, NULL);
5007 if (EQ (conversion, Qdisabled))
5008 x_disable_image (f, img);
5009 else if (EQ (conversion, Qlaplace))
5010 x_laplace (f, img);
5011 else if (EQ (conversion, Qemboss))
5012 x_emboss (f, img);
5013 else if (CONSP (conversion)
5014 && EQ (XCAR (conversion), Qedge_detection))
5016 Lisp_Object tem;
5017 tem = XCDR (conversion);
5018 if (CONSP (tem))
5019 x_edge_detection (f, img,
5020 Fplist_get (tem, QCmatrix),
5021 Fplist_get (tem, QCcolor_adjustment));
5027 /* Return the id of image with Lisp specification SPEC on frame F.
5028 SPEC must be a valid Lisp image specification (see valid_image_p). */
5031 lookup_image (f, spec)
5032 struct frame *f;
5033 Lisp_Object spec;
5035 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5036 struct image *img;
5037 int i;
5038 unsigned hash;
5039 struct gcpro gcpro1;
5040 EMACS_TIME now;
5042 /* F must be a window-system frame, and SPEC must be a valid image
5043 specification. */
5044 xassert (FRAME_WINDOW_P (f));
5045 xassert (valid_image_p (spec));
5047 GCPRO1 (spec);
5049 /* Look up SPEC in the hash table of the image cache. */
5050 hash = sxhash (spec, 0);
5051 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5053 for (img = c->buckets[i]; img; img = img->next)
5054 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5055 break;
5057 /* If not found, create a new image and cache it. */
5058 if (img == NULL)
5060 extern Lisp_Object Qpostscript;
5062 BLOCK_INPUT;
5063 img = make_image (spec, hash);
5064 cache_image (f, img);
5065 img->load_failed_p = img->type->load (f, img) == 0;
5067 /* If we can't load the image, and we don't have a width and
5068 height, use some arbitrary width and height so that we can
5069 draw a rectangle for it. */
5070 if (img->load_failed_p)
5072 Lisp_Object value;
5074 value = image_spec_value (spec, QCwidth, NULL);
5075 img->width = (INTEGERP (value)
5076 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5077 value = image_spec_value (spec, QCheight, NULL);
5078 img->height = (INTEGERP (value)
5079 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5081 else
5083 /* Handle image type independent image attributes
5084 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
5085 `:background COLOR'. */
5086 Lisp_Object ascent, margin, relief, bg;
5088 ascent = image_spec_value (spec, QCascent, NULL);
5089 if (INTEGERP (ascent))
5090 img->ascent = XFASTINT (ascent);
5091 else if (EQ (ascent, Qcenter))
5092 img->ascent = CENTERED_IMAGE_ASCENT;
5094 margin = image_spec_value (spec, QCmargin, NULL);
5095 if (INTEGERP (margin) && XINT (margin) >= 0)
5096 img->vmargin = img->hmargin = XFASTINT (margin);
5097 else if (CONSP (margin) && INTEGERP (XCAR (margin))
5098 && INTEGERP (XCDR (margin)))
5100 if (XINT (XCAR (margin)) > 0)
5101 img->hmargin = XFASTINT (XCAR (margin));
5102 if (XINT (XCDR (margin)) > 0)
5103 img->vmargin = XFASTINT (XCDR (margin));
5106 relief = image_spec_value (spec, QCrelief, NULL);
5107 if (INTEGERP (relief))
5109 img->relief = XINT (relief);
5110 img->hmargin += abs (img->relief);
5111 img->vmargin += abs (img->relief);
5114 if (! img->background_valid)
5116 bg = image_spec_value (img->spec, QCbackground, NULL);
5117 if (!NILP (bg))
5119 img->background
5120 = x_alloc_image_color (f, img, bg,
5121 FRAME_BACKGROUND_PIXEL (f));
5122 img->background_valid = 1;
5126 /* Do image transformations and compute masks, unless we
5127 don't have the image yet. */
5128 if (!EQ (*img->type->type, Qpostscript))
5129 postprocess_image (f, img);
5132 UNBLOCK_INPUT;
5133 xassert (!interrupt_input_blocked);
5136 /* We're using IMG, so set its timestamp to `now'. */
5137 EMACS_GET_TIME (now);
5138 img->timestamp = EMACS_SECS (now);
5140 UNGCPRO;
5142 /* Value is the image id. */
5143 return img->id;
5147 /* Cache image IMG in the image cache of frame F. */
5149 static void
5150 cache_image (f, img)
5151 struct frame *f;
5152 struct image *img;
5154 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5155 int i;
5157 /* Find a free slot in c->images. */
5158 for (i = 0; i < c->used; ++i)
5159 if (c->images[i] == NULL)
5160 break;
5162 /* If no free slot found, maybe enlarge c->images. */
5163 if (i == c->used && c->used == c->size)
5165 c->size *= 2;
5166 c->images = (struct image **) xrealloc (c->images,
5167 c->size * sizeof *c->images);
5170 /* Add IMG to c->images, and assign IMG an id. */
5171 c->images[i] = img;
5172 img->id = i;
5173 if (i == c->used)
5174 ++c->used;
5176 /* Add IMG to the cache's hash table. */
5177 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5178 img->next = c->buckets[i];
5179 if (img->next)
5180 img->next->prev = img;
5181 img->prev = NULL;
5182 c->buckets[i] = img;
5186 /* Call FN on every image in the image cache of frame F. Used to mark
5187 Lisp Objects in the image cache. */
5189 void
5190 forall_images_in_image_cache (f, fn)
5191 struct frame *f;
5192 void (*fn) P_ ((struct image *img));
5194 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5196 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5197 if (c)
5199 int i;
5200 for (i = 0; i < c->used; ++i)
5201 if (c->images[i])
5202 fn (c->images[i]);
5209 /***********************************************************************
5210 X support code
5211 ***********************************************************************/
5213 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5214 XImage **, Pixmap *));
5215 static void x_destroy_x_image P_ ((XImage *));
5216 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
5219 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5220 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5221 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5222 via xmalloc. Print error messages via image_error if an error
5223 occurs. Value is non-zero if successful. */
5225 static int
5226 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
5227 struct frame *f;
5228 int width, height, depth;
5229 XImage **ximg;
5230 Pixmap *pixmap;
5232 Display *display = FRAME_X_DISPLAY (f);
5233 Screen *screen = FRAME_X_SCREEN (f);
5234 Window window = FRAME_X_WINDOW (f);
5236 xassert (interrupt_input_blocked);
5238 if (depth <= 0)
5239 depth = DefaultDepthOfScreen (screen);
5240 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
5241 depth, ZPixmap, 0, NULL, width, height,
5242 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
5243 if (*ximg == NULL)
5245 image_error ("Unable to allocate X image", Qnil, Qnil);
5246 return 0;
5249 /* Allocate image raster. */
5250 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
5252 /* Allocate a pixmap of the same size. */
5253 *pixmap = XCreatePixmap (display, window, width, height, depth);
5254 if (*pixmap == None)
5256 x_destroy_x_image (*ximg);
5257 *ximg = NULL;
5258 image_error ("Unable to create X pixmap", Qnil, Qnil);
5259 return 0;
5262 return 1;
5266 /* Destroy XImage XIMG. Free XIMG->data. */
5268 static void
5269 x_destroy_x_image (ximg)
5270 XImage *ximg;
5272 xassert (interrupt_input_blocked);
5273 if (ximg)
5275 xfree (ximg->data);
5276 ximg->data = NULL;
5277 XDestroyImage (ximg);
5282 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5283 are width and height of both the image and pixmap. */
5285 static void
5286 x_put_x_image (f, ximg, pixmap, width, height)
5287 struct frame *f;
5288 XImage *ximg;
5289 Pixmap pixmap;
5290 int width, height;
5292 GC gc;
5294 xassert (interrupt_input_blocked);
5295 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
5296 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
5297 XFreeGC (FRAME_X_DISPLAY (f), gc);
5302 /***********************************************************************
5303 File Handling
5304 ***********************************************************************/
5306 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
5307 static char *slurp_file P_ ((char *, int *));
5310 /* Find image file FILE. Look in data-directory, then
5311 x-bitmap-file-path. Value is the full name of the file found, or
5312 nil if not found. */
5314 static Lisp_Object
5315 x_find_image_file (file)
5316 Lisp_Object file;
5318 Lisp_Object file_found, search_path;
5319 struct gcpro gcpro1, gcpro2;
5320 int fd;
5322 file_found = Qnil;
5323 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
5324 GCPRO2 (file_found, search_path);
5326 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5327 fd = openp (search_path, file, Qnil, &file_found, Qnil);
5329 if (fd == -1)
5330 file_found = Qnil;
5331 else
5332 close (fd);
5334 UNGCPRO;
5335 return file_found;
5339 /* Read FILE into memory. Value is a pointer to a buffer allocated
5340 with xmalloc holding FILE's contents. Value is null if an error
5341 occurred. *SIZE is set to the size of the file. */
5343 static char *
5344 slurp_file (file, size)
5345 char *file;
5346 int *size;
5348 FILE *fp = NULL;
5349 char *buf = NULL;
5350 struct stat st;
5352 if (stat (file, &st) == 0
5353 && (fp = fopen (file, "r")) != NULL
5354 && (buf = (char *) xmalloc (st.st_size),
5355 fread (buf, 1, st.st_size, fp) == st.st_size))
5357 *size = st.st_size;
5358 fclose (fp);
5360 else
5362 if (fp)
5363 fclose (fp);
5364 if (buf)
5366 xfree (buf);
5367 buf = NULL;
5371 return buf;
5376 /***********************************************************************
5377 XBM images
5378 ***********************************************************************/
5380 static int xbm_scan P_ ((char **, char *, char *, int *));
5381 static int xbm_load P_ ((struct frame *f, struct image *img));
5382 static int xbm_load_image P_ ((struct frame *f, struct image *img,
5383 char *, char *));
5384 static int xbm_image_p P_ ((Lisp_Object object));
5385 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
5386 unsigned char **));
5387 static int xbm_file_p P_ ((Lisp_Object));
5390 /* Indices of image specification fields in xbm_format, below. */
5392 enum xbm_keyword_index
5394 XBM_TYPE,
5395 XBM_FILE,
5396 XBM_WIDTH,
5397 XBM_HEIGHT,
5398 XBM_DATA,
5399 XBM_FOREGROUND,
5400 XBM_BACKGROUND,
5401 XBM_ASCENT,
5402 XBM_MARGIN,
5403 XBM_RELIEF,
5404 XBM_ALGORITHM,
5405 XBM_HEURISTIC_MASK,
5406 XBM_MASK,
5407 XBM_LAST
5410 /* Vector of image_keyword structures describing the format
5411 of valid XBM image specifications. */
5413 static struct image_keyword xbm_format[XBM_LAST] =
5415 {":type", IMAGE_SYMBOL_VALUE, 1},
5416 {":file", IMAGE_STRING_VALUE, 0},
5417 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5418 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5419 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5420 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5421 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
5422 {":ascent", IMAGE_ASCENT_VALUE, 0},
5423 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5424 {":relief", IMAGE_INTEGER_VALUE, 0},
5425 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5426 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5427 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5430 /* Structure describing the image type XBM. */
5432 static struct image_type xbm_type =
5434 &Qxbm,
5435 xbm_image_p,
5436 xbm_load,
5437 x_clear_image,
5438 NULL
5441 /* Tokens returned from xbm_scan. */
5443 enum xbm_token
5445 XBM_TK_IDENT = 256,
5446 XBM_TK_NUMBER
5450 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5451 A valid specification is a list starting with the symbol `image'
5452 The rest of the list is a property list which must contain an
5453 entry `:type xbm..
5455 If the specification specifies a file to load, it must contain
5456 an entry `:file FILENAME' where FILENAME is a string.
5458 If the specification is for a bitmap loaded from memory it must
5459 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5460 WIDTH and HEIGHT are integers > 0. DATA may be:
5462 1. a string large enough to hold the bitmap data, i.e. it must
5463 have a size >= (WIDTH + 7) / 8 * HEIGHT
5465 2. a bool-vector of size >= WIDTH * HEIGHT
5467 3. a vector of strings or bool-vectors, one for each line of the
5468 bitmap.
5470 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
5471 may not be specified in this case because they are defined in the
5472 XBM file.
5474 Both the file and data forms may contain the additional entries
5475 `:background COLOR' and `:foreground COLOR'. If not present,
5476 foreground and background of the frame on which the image is
5477 displayed is used. */
5479 static int
5480 xbm_image_p (object)
5481 Lisp_Object object;
5483 struct image_keyword kw[XBM_LAST];
5485 bcopy (xbm_format, kw, sizeof kw);
5486 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5487 return 0;
5489 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5491 if (kw[XBM_FILE].count)
5493 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5494 return 0;
5496 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
5498 /* In-memory XBM file. */
5499 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
5500 return 0;
5502 else
5504 Lisp_Object data;
5505 int width, height;
5507 /* Entries for `:width', `:height' and `:data' must be present. */
5508 if (!kw[XBM_WIDTH].count
5509 || !kw[XBM_HEIGHT].count
5510 || !kw[XBM_DATA].count)
5511 return 0;
5513 data = kw[XBM_DATA].value;
5514 width = XFASTINT (kw[XBM_WIDTH].value);
5515 height = XFASTINT (kw[XBM_HEIGHT].value);
5517 /* Check type of data, and width and height against contents of
5518 data. */
5519 if (VECTORP (data))
5521 int i;
5523 /* Number of elements of the vector must be >= height. */
5524 if (XVECTOR (data)->size < height)
5525 return 0;
5527 /* Each string or bool-vector in data must be large enough
5528 for one line of the image. */
5529 for (i = 0; i < height; ++i)
5531 Lisp_Object elt = XVECTOR (data)->contents[i];
5533 if (STRINGP (elt))
5535 if (SCHARS (elt)
5536 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
5537 return 0;
5539 else if (BOOL_VECTOR_P (elt))
5541 if (XBOOL_VECTOR (elt)->size < width)
5542 return 0;
5544 else
5545 return 0;
5548 else if (STRINGP (data))
5550 if (SCHARS (data)
5551 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
5552 return 0;
5554 else if (BOOL_VECTOR_P (data))
5556 if (XBOOL_VECTOR (data)->size < width * height)
5557 return 0;
5559 else
5560 return 0;
5563 return 1;
5567 /* Scan a bitmap file. FP is the stream to read from. Value is
5568 either an enumerator from enum xbm_token, or a character for a
5569 single-character token, or 0 at end of file. If scanning an
5570 identifier, store the lexeme of the identifier in SVAL. If
5571 scanning a number, store its value in *IVAL. */
5573 static int
5574 xbm_scan (s, end, sval, ival)
5575 char **s, *end;
5576 char *sval;
5577 int *ival;
5579 int c;
5581 loop:
5583 /* Skip white space. */
5584 while (*s < end && (c = *(*s)++, isspace (c)))
5587 if (*s >= end)
5588 c = 0;
5589 else if (isdigit (c))
5591 int value = 0, digit;
5593 if (c == '0' && *s < end)
5595 c = *(*s)++;
5596 if (c == 'x' || c == 'X')
5598 while (*s < end)
5600 c = *(*s)++;
5601 if (isdigit (c))
5602 digit = c - '0';
5603 else if (c >= 'a' && c <= 'f')
5604 digit = c - 'a' + 10;
5605 else if (c >= 'A' && c <= 'F')
5606 digit = c - 'A' + 10;
5607 else
5608 break;
5609 value = 16 * value + digit;
5612 else if (isdigit (c))
5614 value = c - '0';
5615 while (*s < end
5616 && (c = *(*s)++, isdigit (c)))
5617 value = 8 * value + c - '0';
5620 else
5622 value = c - '0';
5623 while (*s < end
5624 && (c = *(*s)++, isdigit (c)))
5625 value = 10 * value + c - '0';
5628 if (*s < end)
5629 *s = *s - 1;
5630 *ival = value;
5631 c = XBM_TK_NUMBER;
5633 else if (isalpha (c) || c == '_')
5635 *sval++ = c;
5636 while (*s < end
5637 && (c = *(*s)++, (isalnum (c) || c == '_')))
5638 *sval++ = c;
5639 *sval = 0;
5640 if (*s < end)
5641 *s = *s - 1;
5642 c = XBM_TK_IDENT;
5644 else if (c == '/' && **s == '*')
5646 /* C-style comment. */
5647 ++*s;
5648 while (**s && (**s != '*' || *(*s + 1) != '/'))
5649 ++*s;
5650 if (**s)
5652 *s += 2;
5653 goto loop;
5657 return c;
5661 /* Replacement for XReadBitmapFileData which isn't available under old
5662 X versions. CONTENTS is a pointer to a buffer to parse; END is the
5663 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
5664 the image. Return in *DATA the bitmap data allocated with xmalloc.
5665 Value is non-zero if successful. DATA null means just test if
5666 CONTENTS looks like an in-memory XBM file. */
5668 static int
5669 xbm_read_bitmap_data (contents, end, width, height, data)
5670 char *contents, *end;
5671 int *width, *height;
5672 unsigned char **data;
5674 char *s = contents;
5675 char buffer[BUFSIZ];
5676 int padding_p = 0;
5677 int v10 = 0;
5678 int bytes_per_line, i, nbytes;
5679 unsigned char *p;
5680 int value;
5681 int LA1;
5683 #define match() \
5684 LA1 = xbm_scan (&s, end, buffer, &value)
5686 #define expect(TOKEN) \
5687 if (LA1 != (TOKEN)) \
5688 goto failure; \
5689 else \
5690 match ()
5692 #define expect_ident(IDENT) \
5693 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5694 match (); \
5695 else \
5696 goto failure
5698 *width = *height = -1;
5699 if (data)
5700 *data = NULL;
5701 LA1 = xbm_scan (&s, end, buffer, &value);
5703 /* Parse defines for width, height and hot-spots. */
5704 while (LA1 == '#')
5706 match ();
5707 expect_ident ("define");
5708 expect (XBM_TK_IDENT);
5710 if (LA1 == XBM_TK_NUMBER);
5712 char *p = strrchr (buffer, '_');
5713 p = p ? p + 1 : buffer;
5714 if (strcmp (p, "width") == 0)
5715 *width = value;
5716 else if (strcmp (p, "height") == 0)
5717 *height = value;
5719 expect (XBM_TK_NUMBER);
5722 if (*width < 0 || *height < 0)
5723 goto failure;
5724 else if (data == NULL)
5725 goto success;
5727 /* Parse bits. Must start with `static'. */
5728 expect_ident ("static");
5729 if (LA1 == XBM_TK_IDENT)
5731 if (strcmp (buffer, "unsigned") == 0)
5733 match ();
5734 expect_ident ("char");
5736 else if (strcmp (buffer, "short") == 0)
5738 match ();
5739 v10 = 1;
5740 if (*width % 16 && *width % 16 < 9)
5741 padding_p = 1;
5743 else if (strcmp (buffer, "char") == 0)
5744 match ();
5745 else
5746 goto failure;
5748 else
5749 goto failure;
5751 expect (XBM_TK_IDENT);
5752 expect ('[');
5753 expect (']');
5754 expect ('=');
5755 expect ('{');
5757 bytes_per_line = (*width + 7) / 8 + padding_p;
5758 nbytes = bytes_per_line * *height;
5759 p = *data = (char *) xmalloc (nbytes);
5761 if (v10)
5763 for (i = 0; i < nbytes; i += 2)
5765 int val = value;
5766 expect (XBM_TK_NUMBER);
5768 *p++ = val;
5769 if (!padding_p || ((i + 2) % bytes_per_line))
5770 *p++ = value >> 8;
5772 if (LA1 == ',' || LA1 == '}')
5773 match ();
5774 else
5775 goto failure;
5778 else
5780 for (i = 0; i < nbytes; ++i)
5782 int val = value;
5783 expect (XBM_TK_NUMBER);
5785 *p++ = val;
5787 if (LA1 == ',' || LA1 == '}')
5788 match ();
5789 else
5790 goto failure;
5794 success:
5795 return 1;
5797 failure:
5799 if (data && *data)
5801 xfree (*data);
5802 *data = NULL;
5804 return 0;
5806 #undef match
5807 #undef expect
5808 #undef expect_ident
5812 /* Load XBM image IMG which will be displayed on frame F from buffer
5813 CONTENTS. END is the end of the buffer. Value is non-zero if
5814 successful. */
5816 static int
5817 xbm_load_image (f, img, contents, end)
5818 struct frame *f;
5819 struct image *img;
5820 char *contents, *end;
5822 int rc;
5823 unsigned char *data;
5824 int success_p = 0;
5826 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
5827 if (rc)
5829 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
5830 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5831 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5832 Lisp_Object value;
5834 xassert (img->width > 0 && img->height > 0);
5836 /* Get foreground and background colors, maybe allocate colors. */
5837 value = image_spec_value (img->spec, QCforeground, NULL);
5838 if (!NILP (value))
5839 foreground = x_alloc_image_color (f, img, value, foreground);
5840 value = image_spec_value (img->spec, QCbackground, NULL);
5841 if (!NILP (value))
5843 background = x_alloc_image_color (f, img, value, background);
5844 img->background = background;
5845 img->background_valid = 1;
5848 img->pixmap
5849 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
5850 FRAME_X_WINDOW (f),
5851 data,
5852 img->width, img->height,
5853 foreground, background,
5854 depth);
5855 xfree (data);
5857 if (img->pixmap == None)
5859 x_clear_image (f, img);
5860 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
5862 else
5863 success_p = 1;
5865 else
5866 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
5868 return success_p;
5872 /* Value is non-zero if DATA looks like an in-memory XBM file. */
5874 static int
5875 xbm_file_p (data)
5876 Lisp_Object data;
5878 int w, h;
5879 return (STRINGP (data)
5880 && xbm_read_bitmap_data (SDATA (data),
5881 (SDATA (data)
5882 + SBYTES (data)),
5883 &w, &h, NULL));
5887 /* Fill image IMG which is used on frame F with pixmap data. Value is
5888 non-zero if successful. */
5890 static int
5891 xbm_load (f, img)
5892 struct frame *f;
5893 struct image *img;
5895 int success_p = 0;
5896 Lisp_Object file_name;
5898 xassert (xbm_image_p (img->spec));
5900 /* If IMG->spec specifies a file name, create a non-file spec from it. */
5901 file_name = image_spec_value (img->spec, QCfile, NULL);
5902 if (STRINGP (file_name))
5904 Lisp_Object file;
5905 char *contents;
5906 int size;
5907 struct gcpro gcpro1;
5909 file = x_find_image_file (file_name);
5910 GCPRO1 (file);
5911 if (!STRINGP (file))
5913 image_error ("Cannot find image file `%s'", file_name, Qnil);
5914 UNGCPRO;
5915 return 0;
5918 contents = slurp_file (SDATA (file), &size);
5919 if (contents == NULL)
5921 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
5922 UNGCPRO;
5923 return 0;
5926 success_p = xbm_load_image (f, img, contents, contents + size);
5927 UNGCPRO;
5929 else
5931 struct image_keyword fmt[XBM_LAST];
5932 Lisp_Object data;
5933 int depth;
5934 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5935 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5936 char *bits;
5937 int parsed_p;
5938 int in_memory_file_p = 0;
5940 /* See if data looks like an in-memory XBM file. */
5941 data = image_spec_value (img->spec, QCdata, NULL);
5942 in_memory_file_p = xbm_file_p (data);
5944 /* Parse the image specification. */
5945 bcopy (xbm_format, fmt, sizeof fmt);
5946 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
5947 xassert (parsed_p);
5949 /* Get specified width, and height. */
5950 if (!in_memory_file_p)
5952 img->width = XFASTINT (fmt[XBM_WIDTH].value);
5953 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
5954 xassert (img->width > 0 && img->height > 0);
5957 /* Get foreground and background colors, maybe allocate colors. */
5958 if (fmt[XBM_FOREGROUND].count
5959 && STRINGP (fmt[XBM_FOREGROUND].value))
5960 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
5961 foreground);
5962 if (fmt[XBM_BACKGROUND].count
5963 && STRINGP (fmt[XBM_BACKGROUND].value))
5964 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
5965 background);
5967 if (in_memory_file_p)
5968 success_p = xbm_load_image (f, img, SDATA (data),
5969 (SDATA (data)
5970 + SBYTES (data)));
5971 else
5973 if (VECTORP (data))
5975 int i;
5976 char *p;
5977 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
5979 p = bits = (char *) alloca (nbytes * img->height);
5980 for (i = 0; i < img->height; ++i, p += nbytes)
5982 Lisp_Object line = XVECTOR (data)->contents[i];
5983 if (STRINGP (line))
5984 bcopy (SDATA (line), p, nbytes);
5985 else
5986 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
5989 else if (STRINGP (data))
5990 bits = SDATA (data);
5991 else
5992 bits = XBOOL_VECTOR (data)->data;
5994 /* Create the pixmap. */
5995 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
5996 img->pixmap
5997 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
5998 FRAME_X_WINDOW (f),
5999 bits,
6000 img->width, img->height,
6001 foreground, background,
6002 depth);
6003 if (img->pixmap)
6004 success_p = 1;
6005 else
6007 image_error ("Unable to create pixmap for XBM image `%s'",
6008 img->spec, Qnil);
6009 x_clear_image (f, img);
6014 return success_p;
6019 /***********************************************************************
6020 XPM images
6021 ***********************************************************************/
6023 #if HAVE_XPM
6025 static int xpm_image_p P_ ((Lisp_Object object));
6026 static int xpm_load P_ ((struct frame *f, struct image *img));
6027 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6029 #include "X11/xpm.h"
6031 /* The symbol `xpm' identifying XPM-format images. */
6033 Lisp_Object Qxpm;
6035 /* Indices of image specification fields in xpm_format, below. */
6037 enum xpm_keyword_index
6039 XPM_TYPE,
6040 XPM_FILE,
6041 XPM_DATA,
6042 XPM_ASCENT,
6043 XPM_MARGIN,
6044 XPM_RELIEF,
6045 XPM_ALGORITHM,
6046 XPM_HEURISTIC_MASK,
6047 XPM_MASK,
6048 XPM_COLOR_SYMBOLS,
6049 XPM_BACKGROUND,
6050 XPM_LAST
6053 /* Vector of image_keyword structures describing the format
6054 of valid XPM image specifications. */
6056 static struct image_keyword xpm_format[XPM_LAST] =
6058 {":type", IMAGE_SYMBOL_VALUE, 1},
6059 {":file", IMAGE_STRING_VALUE, 0},
6060 {":data", IMAGE_STRING_VALUE, 0},
6061 {":ascent", IMAGE_ASCENT_VALUE, 0},
6062 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6063 {":relief", IMAGE_INTEGER_VALUE, 0},
6064 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6065 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6066 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6067 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6068 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6071 /* Structure describing the image type XBM. */
6073 static struct image_type xpm_type =
6075 &Qxpm,
6076 xpm_image_p,
6077 xpm_load,
6078 x_clear_image,
6079 NULL
6083 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6084 functions for allocating image colors. Our own functions handle
6085 color allocation failures more gracefully than the ones on the XPM
6086 lib. */
6088 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6089 #define ALLOC_XPM_COLORS
6090 #endif
6092 #ifdef ALLOC_XPM_COLORS
6094 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
6095 static void xpm_free_color_cache P_ ((void));
6096 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
6097 static int xpm_color_bucket P_ ((char *));
6098 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
6099 XColor *, int));
6101 /* An entry in a hash table used to cache color definitions of named
6102 colors. This cache is necessary to speed up XPM image loading in
6103 case we do color allocations ourselves. Without it, we would need
6104 a call to XParseColor per pixel in the image. */
6106 struct xpm_cached_color
6108 /* Next in collision chain. */
6109 struct xpm_cached_color *next;
6111 /* Color definition (RGB and pixel color). */
6112 XColor color;
6114 /* Color name. */
6115 char name[1];
6118 /* The hash table used for the color cache, and its bucket vector
6119 size. */
6121 #define XPM_COLOR_CACHE_BUCKETS 1001
6122 struct xpm_cached_color **xpm_color_cache;
6124 /* Initialize the color cache. */
6126 static void
6127 xpm_init_color_cache (f, attrs)
6128 struct frame *f;
6129 XpmAttributes *attrs;
6131 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
6132 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
6133 memset (xpm_color_cache, 0, nbytes);
6134 init_color_table ();
6136 if (attrs->valuemask & XpmColorSymbols)
6138 int i;
6139 XColor color;
6141 for (i = 0; i < attrs->numsymbols; ++i)
6142 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6143 attrs->colorsymbols[i].value, &color))
6145 color.pixel = lookup_rgb_color (f, color.red, color.green,
6146 color.blue);
6147 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
6153 /* Free the color cache. */
6155 static void
6156 xpm_free_color_cache ()
6158 struct xpm_cached_color *p, *next;
6159 int i;
6161 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
6162 for (p = xpm_color_cache[i]; p; p = next)
6164 next = p->next;
6165 xfree (p);
6168 xfree (xpm_color_cache);
6169 xpm_color_cache = NULL;
6170 free_color_table ();
6174 /* Return the bucket index for color named COLOR_NAME in the color
6175 cache. */
6177 static int
6178 xpm_color_bucket (color_name)
6179 char *color_name;
6181 unsigned h = 0;
6182 char *s;
6184 for (s = color_name; *s; ++s)
6185 h = (h << 2) ^ *s;
6186 return h %= XPM_COLOR_CACHE_BUCKETS;
6190 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6191 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6192 entry added. */
6194 static struct xpm_cached_color *
6195 xpm_cache_color (f, color_name, color, bucket)
6196 struct frame *f;
6197 char *color_name;
6198 XColor *color;
6199 int bucket;
6201 size_t nbytes;
6202 struct xpm_cached_color *p;
6204 if (bucket < 0)
6205 bucket = xpm_color_bucket (color_name);
6207 nbytes = sizeof *p + strlen (color_name);
6208 p = (struct xpm_cached_color *) xmalloc (nbytes);
6209 strcpy (p->name, color_name);
6210 p->color = *color;
6211 p->next = xpm_color_cache[bucket];
6212 xpm_color_cache[bucket] = p;
6213 return p;
6217 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6218 return the cached definition in *COLOR. Otherwise, make a new
6219 entry in the cache and allocate the color. Value is zero if color
6220 allocation failed. */
6222 static int
6223 xpm_lookup_color (f, color_name, color)
6224 struct frame *f;
6225 char *color_name;
6226 XColor *color;
6228 struct xpm_cached_color *p;
6229 int h = xpm_color_bucket (color_name);
6231 for (p = xpm_color_cache[h]; p; p = p->next)
6232 if (strcmp (p->name, color_name) == 0)
6233 break;
6235 if (p != NULL)
6236 *color = p->color;
6237 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6238 color_name, color))
6240 color->pixel = lookup_rgb_color (f, color->red, color->green,
6241 color->blue);
6242 p = xpm_cache_color (f, color_name, color, h);
6244 /* You get `opaque' at least from ImageMagick converting pbm to xpm
6245 with transparency, and it's useful. */
6246 else if (strcmp ("opaque", color_name) == 0)
6248 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
6249 color->pixel = FRAME_FOREGROUND_PIXEL (f);
6250 p = xpm_cache_color (f, color_name, color, h);
6253 return p != NULL;
6257 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
6258 CLOSURE is a pointer to the frame on which we allocate the
6259 color. Return in *COLOR the allocated color. Value is non-zero
6260 if successful. */
6262 static int
6263 xpm_alloc_color (dpy, cmap, color_name, color, closure)
6264 Display *dpy;
6265 Colormap cmap;
6266 char *color_name;
6267 XColor *color;
6268 void *closure;
6270 return xpm_lookup_color ((struct frame *) closure, color_name, color);
6274 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
6275 is a pointer to the frame on which we allocate the color. Value is
6276 non-zero if successful. */
6278 static int
6279 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
6280 Display *dpy;
6281 Colormap cmap;
6282 Pixel *pixels;
6283 int npixels;
6284 void *closure;
6286 return 1;
6289 #endif /* ALLOC_XPM_COLORS */
6292 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6293 for XPM images. Such a list must consist of conses whose car and
6294 cdr are strings. */
6296 static int
6297 xpm_valid_color_symbols_p (color_symbols)
6298 Lisp_Object color_symbols;
6300 while (CONSP (color_symbols))
6302 Lisp_Object sym = XCAR (color_symbols);
6303 if (!CONSP (sym)
6304 || !STRINGP (XCAR (sym))
6305 || !STRINGP (XCDR (sym)))
6306 break;
6307 color_symbols = XCDR (color_symbols);
6310 return NILP (color_symbols);
6314 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6316 static int
6317 xpm_image_p (object)
6318 Lisp_Object object;
6320 struct image_keyword fmt[XPM_LAST];
6321 bcopy (xpm_format, fmt, sizeof fmt);
6322 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
6323 /* Either `:file' or `:data' must be present. */
6324 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
6325 /* Either no `:color-symbols' or it's a list of conses
6326 whose car and cdr are strings. */
6327 && (fmt[XPM_COLOR_SYMBOLS].count == 0
6328 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
6332 /* Load image IMG which will be displayed on frame F. Value is
6333 non-zero if successful. */
6335 static int
6336 xpm_load (f, img)
6337 struct frame *f;
6338 struct image *img;
6340 int rc;
6341 XpmAttributes attrs;
6342 Lisp_Object specified_file, color_symbols;
6344 /* Configure the XPM lib. Use the visual of frame F. Allocate
6345 close colors. Return colors allocated. */
6346 bzero (&attrs, sizeof attrs);
6347 attrs.visual = FRAME_X_VISUAL (f);
6348 attrs.colormap = FRAME_X_COLORMAP (f);
6349 attrs.valuemask |= XpmVisual;
6350 attrs.valuemask |= XpmColormap;
6352 #ifdef ALLOC_XPM_COLORS
6353 /* Allocate colors with our own functions which handle
6354 failing color allocation more gracefully. */
6355 attrs.color_closure = f;
6356 attrs.alloc_color = xpm_alloc_color;
6357 attrs.free_colors = xpm_free_colors;
6358 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
6359 #else /* not ALLOC_XPM_COLORS */
6360 /* Let the XPM lib allocate colors. */
6361 attrs.valuemask |= XpmReturnAllocPixels;
6362 #ifdef XpmAllocCloseColors
6363 attrs.alloc_close_colors = 1;
6364 attrs.valuemask |= XpmAllocCloseColors;
6365 #else /* not XpmAllocCloseColors */
6366 attrs.closeness = 600;
6367 attrs.valuemask |= XpmCloseness;
6368 #endif /* not XpmAllocCloseColors */
6369 #endif /* ALLOC_XPM_COLORS */
6371 /* If image specification contains symbolic color definitions, add
6372 these to `attrs'. */
6373 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
6374 if (CONSP (color_symbols))
6376 Lisp_Object tail;
6377 XpmColorSymbol *xpm_syms;
6378 int i, size;
6380 attrs.valuemask |= XpmColorSymbols;
6382 /* Count number of symbols. */
6383 attrs.numsymbols = 0;
6384 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
6385 ++attrs.numsymbols;
6387 /* Allocate an XpmColorSymbol array. */
6388 size = attrs.numsymbols * sizeof *xpm_syms;
6389 xpm_syms = (XpmColorSymbol *) alloca (size);
6390 bzero (xpm_syms, size);
6391 attrs.colorsymbols = xpm_syms;
6393 /* Fill the color symbol array. */
6394 for (tail = color_symbols, i = 0;
6395 CONSP (tail);
6396 ++i, tail = XCDR (tail))
6398 Lisp_Object name = XCAR (XCAR (tail));
6399 Lisp_Object color = XCDR (XCAR (tail));
6400 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
6401 strcpy (xpm_syms[i].name, SDATA (name));
6402 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
6403 strcpy (xpm_syms[i].value, SDATA (color));
6407 /* Create a pixmap for the image, either from a file, or from a
6408 string buffer containing data in the same format as an XPM file. */
6409 #ifdef ALLOC_XPM_COLORS
6410 xpm_init_color_cache (f, &attrs);
6411 #endif
6413 specified_file = image_spec_value (img->spec, QCfile, NULL);
6414 if (STRINGP (specified_file))
6416 Lisp_Object file = x_find_image_file (specified_file);
6417 if (!STRINGP (file))
6419 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6420 return 0;
6423 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6424 SDATA (file), &img->pixmap, &img->mask,
6425 &attrs);
6427 else
6429 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6430 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6431 SDATA (buffer),
6432 &img->pixmap, &img->mask,
6433 &attrs);
6436 if (rc == XpmSuccess)
6438 #ifdef ALLOC_XPM_COLORS
6439 img->colors = colors_in_color_table (&img->ncolors);
6440 #else /* not ALLOC_XPM_COLORS */
6441 int i;
6443 img->ncolors = attrs.nalloc_pixels;
6444 img->colors = (unsigned long *) xmalloc (img->ncolors
6445 * sizeof *img->colors);
6446 for (i = 0; i < attrs.nalloc_pixels; ++i)
6448 img->colors[i] = attrs.alloc_pixels[i];
6449 #ifdef DEBUG_X_COLORS
6450 register_color (img->colors[i]);
6451 #endif
6453 #endif /* not ALLOC_XPM_COLORS */
6455 img->width = attrs.width;
6456 img->height = attrs.height;
6457 xassert (img->width > 0 && img->height > 0);
6459 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6460 XpmFreeAttributes (&attrs);
6462 else
6464 switch (rc)
6466 case XpmOpenFailed:
6467 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6468 break;
6470 case XpmFileInvalid:
6471 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6472 break;
6474 case XpmNoMemory:
6475 image_error ("Out of memory (%s)", img->spec, Qnil);
6476 break;
6478 case XpmColorFailed:
6479 image_error ("Color allocation error (%s)", img->spec, Qnil);
6480 break;
6482 default:
6483 image_error ("Unknown error (%s)", img->spec, Qnil);
6484 break;
6488 #ifdef ALLOC_XPM_COLORS
6489 xpm_free_color_cache ();
6490 #endif
6491 return rc == XpmSuccess;
6494 #endif /* HAVE_XPM != 0 */
6497 /***********************************************************************
6498 Color table
6499 ***********************************************************************/
6501 /* An entry in the color table mapping an RGB color to a pixel color. */
6503 struct ct_color
6505 int r, g, b;
6506 unsigned long pixel;
6508 /* Next in color table collision list. */
6509 struct ct_color *next;
6512 /* The bucket vector size to use. Must be prime. */
6514 #define CT_SIZE 101
6516 /* Value is a hash of the RGB color given by R, G, and B. */
6518 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6520 /* The color hash table. */
6522 struct ct_color **ct_table;
6524 /* Number of entries in the color table. */
6526 int ct_colors_allocated;
6528 /* Initialize the color table. */
6530 static void
6531 init_color_table ()
6533 int size = CT_SIZE * sizeof (*ct_table);
6534 ct_table = (struct ct_color **) xmalloc (size);
6535 bzero (ct_table, size);
6536 ct_colors_allocated = 0;
6540 /* Free memory associated with the color table. */
6542 static void
6543 free_color_table ()
6545 int i;
6546 struct ct_color *p, *next;
6548 for (i = 0; i < CT_SIZE; ++i)
6549 for (p = ct_table[i]; p; p = next)
6551 next = p->next;
6552 xfree (p);
6555 xfree (ct_table);
6556 ct_table = NULL;
6560 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6561 entry for that color already is in the color table, return the
6562 pixel color of that entry. Otherwise, allocate a new color for R,
6563 G, B, and make an entry in the color table. */
6565 static unsigned long
6566 lookup_rgb_color (f, r, g, b)
6567 struct frame *f;
6568 int r, g, b;
6570 unsigned hash = CT_HASH_RGB (r, g, b);
6571 int i = hash % CT_SIZE;
6572 struct ct_color *p;
6574 for (p = ct_table[i]; p; p = p->next)
6575 if (p->r == r && p->g == g && p->b == b)
6576 break;
6578 if (p == NULL)
6580 XColor color;
6581 Colormap cmap;
6582 int rc;
6584 color.red = r;
6585 color.green = g;
6586 color.blue = b;
6588 cmap = FRAME_X_COLORMAP (f);
6589 rc = x_alloc_nearest_color (f, cmap, &color);
6591 if (rc)
6593 ++ct_colors_allocated;
6595 p = (struct ct_color *) xmalloc (sizeof *p);
6596 p->r = r;
6597 p->g = g;
6598 p->b = b;
6599 p->pixel = color.pixel;
6600 p->next = ct_table[i];
6601 ct_table[i] = p;
6603 else
6604 return FRAME_FOREGROUND_PIXEL (f);
6607 return p->pixel;
6611 /* Look up pixel color PIXEL which is used on frame F in the color
6612 table. If not already present, allocate it. Value is PIXEL. */
6614 static unsigned long
6615 lookup_pixel_color (f, pixel)
6616 struct frame *f;
6617 unsigned long pixel;
6619 int i = pixel % CT_SIZE;
6620 struct ct_color *p;
6622 for (p = ct_table[i]; p; p = p->next)
6623 if (p->pixel == pixel)
6624 break;
6626 if (p == NULL)
6628 XColor color;
6629 Colormap cmap;
6630 int rc;
6632 cmap = FRAME_X_COLORMAP (f);
6633 color.pixel = pixel;
6634 x_query_color (f, &color);
6635 rc = x_alloc_nearest_color (f, cmap, &color);
6637 if (rc)
6639 ++ct_colors_allocated;
6641 p = (struct ct_color *) xmalloc (sizeof *p);
6642 p->r = color.red;
6643 p->g = color.green;
6644 p->b = color.blue;
6645 p->pixel = pixel;
6646 p->next = ct_table[i];
6647 ct_table[i] = p;
6649 else
6650 return FRAME_FOREGROUND_PIXEL (f);
6653 return p->pixel;
6657 /* Value is a vector of all pixel colors contained in the color table,
6658 allocated via xmalloc. Set *N to the number of colors. */
6660 static unsigned long *
6661 colors_in_color_table (n)
6662 int *n;
6664 int i, j;
6665 struct ct_color *p;
6666 unsigned long *colors;
6668 if (ct_colors_allocated == 0)
6670 *n = 0;
6671 colors = NULL;
6673 else
6675 colors = (unsigned long *) xmalloc (ct_colors_allocated
6676 * sizeof *colors);
6677 *n = ct_colors_allocated;
6679 for (i = j = 0; i < CT_SIZE; ++i)
6680 for (p = ct_table[i]; p; p = p->next)
6681 colors[j++] = p->pixel;
6684 return colors;
6689 /***********************************************************************
6690 Algorithms
6691 ***********************************************************************/
6693 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
6694 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
6695 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
6697 /* Non-zero means draw a cross on images having `:conversion
6698 disabled'. */
6700 int cross_disabled_images;
6702 /* Edge detection matrices for different edge-detection
6703 strategies. */
6705 static int emboss_matrix[9] = {
6706 /* x - 1 x x + 1 */
6707 2, -1, 0, /* y - 1 */
6708 -1, 0, 1, /* y */
6709 0, 1, -2 /* y + 1 */
6712 static int laplace_matrix[9] = {
6713 /* x - 1 x x + 1 */
6714 1, 0, 0, /* y - 1 */
6715 0, 0, 0, /* y */
6716 0, 0, -1 /* y + 1 */
6719 /* Value is the intensity of the color whose red/green/blue values
6720 are R, G, and B. */
6722 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
6725 /* On frame F, return an array of XColor structures describing image
6726 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
6727 non-zero means also fill the red/green/blue members of the XColor
6728 structures. Value is a pointer to the array of XColors structures,
6729 allocated with xmalloc; it must be freed by the caller. */
6731 static XColor *
6732 x_to_xcolors (f, img, rgb_p)
6733 struct frame *f;
6734 struct image *img;
6735 int rgb_p;
6737 int x, y;
6738 XColor *colors, *p;
6739 XImage *ximg;
6741 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
6743 /* Get the X image IMG->pixmap. */
6744 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6745 0, 0, img->width, img->height, ~0, ZPixmap);
6747 /* Fill the `pixel' members of the XColor array. I wished there
6748 were an easy and portable way to circumvent XGetPixel. */
6749 p = colors;
6750 for (y = 0; y < img->height; ++y)
6752 XColor *row = p;
6754 for (x = 0; x < img->width; ++x, ++p)
6755 p->pixel = XGetPixel (ximg, x, y);
6757 if (rgb_p)
6758 x_query_colors (f, row, img->width);
6761 XDestroyImage (ximg);
6762 return colors;
6766 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
6767 RGB members are set. F is the frame on which this all happens.
6768 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
6770 static void
6771 x_from_xcolors (f, img, colors)
6772 struct frame *f;
6773 struct image *img;
6774 XColor *colors;
6776 int x, y;
6777 XImage *oimg;
6778 Pixmap pixmap;
6779 XColor *p;
6781 init_color_table ();
6783 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
6784 &oimg, &pixmap);
6785 p = colors;
6786 for (y = 0; y < img->height; ++y)
6787 for (x = 0; x < img->width; ++x, ++p)
6789 unsigned long pixel;
6790 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
6791 XPutPixel (oimg, x, y, pixel);
6794 xfree (colors);
6795 x_clear_image_1 (f, img, 1, 0, 1);
6797 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6798 x_destroy_x_image (oimg);
6799 img->pixmap = pixmap;
6800 img->colors = colors_in_color_table (&img->ncolors);
6801 free_color_table ();
6805 /* On frame F, perform edge-detection on image IMG.
6807 MATRIX is a nine-element array specifying the transformation
6808 matrix. See emboss_matrix for an example.
6810 COLOR_ADJUST is a color adjustment added to each pixel of the
6811 outgoing image. */
6813 static void
6814 x_detect_edges (f, img, matrix, color_adjust)
6815 struct frame *f;
6816 struct image *img;
6817 int matrix[9], color_adjust;
6819 XColor *colors = x_to_xcolors (f, img, 1);
6820 XColor *new, *p;
6821 int x, y, i, sum;
6823 for (i = sum = 0; i < 9; ++i)
6824 sum += abs (matrix[i]);
6826 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
6828 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
6830 for (y = 0; y < img->height; ++y)
6832 p = COLOR (new, 0, y);
6833 p->red = p->green = p->blue = 0xffff/2;
6834 p = COLOR (new, img->width - 1, y);
6835 p->red = p->green = p->blue = 0xffff/2;
6838 for (x = 1; x < img->width - 1; ++x)
6840 p = COLOR (new, x, 0);
6841 p->red = p->green = p->blue = 0xffff/2;
6842 p = COLOR (new, x, img->height - 1);
6843 p->red = p->green = p->blue = 0xffff/2;
6846 for (y = 1; y < img->height - 1; ++y)
6848 p = COLOR (new, 1, y);
6850 for (x = 1; x < img->width - 1; ++x, ++p)
6852 int r, g, b, y1, x1;
6854 r = g = b = i = 0;
6855 for (y1 = y - 1; y1 < y + 2; ++y1)
6856 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
6857 if (matrix[i])
6859 XColor *t = COLOR (colors, x1, y1);
6860 r += matrix[i] * t->red;
6861 g += matrix[i] * t->green;
6862 b += matrix[i] * t->blue;
6865 r = (r / sum + color_adjust) & 0xffff;
6866 g = (g / sum + color_adjust) & 0xffff;
6867 b = (b / sum + color_adjust) & 0xffff;
6868 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
6872 xfree (colors);
6873 x_from_xcolors (f, img, new);
6875 #undef COLOR
6879 /* Perform the pre-defined `emboss' edge-detection on image IMG
6880 on frame F. */
6882 static void
6883 x_emboss (f, img)
6884 struct frame *f;
6885 struct image *img;
6887 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
6891 /* Perform the pre-defined `laplace' edge-detection on image IMG
6892 on frame F. */
6894 static void
6895 x_laplace (f, img)
6896 struct frame *f;
6897 struct image *img;
6899 x_detect_edges (f, img, laplace_matrix, 45000);
6903 /* Perform edge-detection on image IMG on frame F, with specified
6904 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
6906 MATRIX must be either
6908 - a list of at least 9 numbers in row-major form
6909 - a vector of at least 9 numbers
6911 COLOR_ADJUST nil means use a default; otherwise it must be a
6912 number. */
6914 static void
6915 x_edge_detection (f, img, matrix, color_adjust)
6916 struct frame *f;
6917 struct image *img;
6918 Lisp_Object matrix, color_adjust;
6920 int i = 0;
6921 int trans[9];
6923 if (CONSP (matrix))
6925 for (i = 0;
6926 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
6927 ++i, matrix = XCDR (matrix))
6928 trans[i] = XFLOATINT (XCAR (matrix));
6930 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
6932 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
6933 trans[i] = XFLOATINT (AREF (matrix, i));
6936 if (NILP (color_adjust))
6937 color_adjust = make_number (0xffff / 2);
6939 if (i == 9 && NUMBERP (color_adjust))
6940 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
6944 /* Transform image IMG on frame F so that it looks disabled. */
6946 static void
6947 x_disable_image (f, img)
6948 struct frame *f;
6949 struct image *img;
6951 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6953 if (dpyinfo->n_planes >= 2)
6955 /* Color (or grayscale). Convert to gray, and equalize. Just
6956 drawing such images with a stipple can look very odd, so
6957 we're using this method instead. */
6958 XColor *colors = x_to_xcolors (f, img, 1);
6959 XColor *p, *end;
6960 const int h = 15000;
6961 const int l = 30000;
6963 for (p = colors, end = colors + img->width * img->height;
6964 p < end;
6965 ++p)
6967 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
6968 int i2 = (0xffff - h - l) * i / 0xffff + l;
6969 p->red = p->green = p->blue = i2;
6972 x_from_xcolors (f, img, colors);
6975 /* Draw a cross over the disabled image, if we must or if we
6976 should. */
6977 if (dpyinfo->n_planes < 2 || cross_disabled_images)
6979 Display *dpy = FRAME_X_DISPLAY (f);
6980 GC gc;
6982 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
6983 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
6984 XDrawLine (dpy, img->pixmap, gc, 0, 0,
6985 img->width - 1, img->height - 1);
6986 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
6987 img->width - 1, 0);
6988 XFreeGC (dpy, gc);
6990 if (img->mask)
6992 gc = XCreateGC (dpy, img->mask, 0, NULL);
6993 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
6994 XDrawLine (dpy, img->mask, gc, 0, 0,
6995 img->width - 1, img->height - 1);
6996 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
6997 img->width - 1, 0);
6998 XFreeGC (dpy, gc);
7004 /* Build a mask for image IMG which is used on frame F. FILE is the
7005 name of an image file, for error messages. HOW determines how to
7006 determine the background color of IMG. If it is a list '(R G B)',
7007 with R, G, and B being integers >= 0, take that as the color of the
7008 background. Otherwise, determine the background color of IMG
7009 heuristically. Value is non-zero if successful. */
7011 static int
7012 x_build_heuristic_mask (f, img, how)
7013 struct frame *f;
7014 struct image *img;
7015 Lisp_Object how;
7017 Display *dpy = FRAME_X_DISPLAY (f);
7018 XImage *ximg, *mask_img;
7019 int x, y, rc, use_img_background;
7020 unsigned long bg = 0;
7022 if (img->mask)
7024 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
7025 img->mask = None;
7026 img->background_transparent_valid = 0;
7029 /* Create an image and pixmap serving as mask. */
7030 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7031 &mask_img, &img->mask);
7032 if (!rc)
7033 return 0;
7035 /* Get the X image of IMG->pixmap. */
7036 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7037 ~0, ZPixmap);
7039 /* Determine the background color of ximg. If HOW is `(R G B)'
7040 take that as color. Otherwise, use the image's background color. */
7041 use_img_background = 1;
7043 if (CONSP (how))
7045 int rgb[3], i;
7047 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
7049 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7050 how = XCDR (how);
7053 if (i == 3 && NILP (how))
7055 char color_name[30];
7056 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7057 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
7058 use_img_background = 0;
7062 if (use_img_background)
7063 bg = four_corners_best (ximg, img->width, img->height);
7065 /* Set all bits in mask_img to 1 whose color in ximg is different
7066 from the background color bg. */
7067 for (y = 0; y < img->height; ++y)
7068 for (x = 0; x < img->width; ++x)
7069 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7071 /* Fill in the background_transparent field while we have the mask handy. */
7072 image_background_transparent (img, f, mask_img);
7074 /* Put mask_img into img->mask. */
7075 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7076 x_destroy_x_image (mask_img);
7077 XDestroyImage (ximg);
7079 return 1;
7084 /***********************************************************************
7085 PBM (mono, gray, color)
7086 ***********************************************************************/
7088 static int pbm_image_p P_ ((Lisp_Object object));
7089 static int pbm_load P_ ((struct frame *f, struct image *img));
7090 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7092 /* The symbol `pbm' identifying images of this type. */
7094 Lisp_Object Qpbm;
7096 /* Indices of image specification fields in gs_format, below. */
7098 enum pbm_keyword_index
7100 PBM_TYPE,
7101 PBM_FILE,
7102 PBM_DATA,
7103 PBM_ASCENT,
7104 PBM_MARGIN,
7105 PBM_RELIEF,
7106 PBM_ALGORITHM,
7107 PBM_HEURISTIC_MASK,
7108 PBM_MASK,
7109 PBM_FOREGROUND,
7110 PBM_BACKGROUND,
7111 PBM_LAST
7114 /* Vector of image_keyword structures describing the format
7115 of valid user-defined image specifications. */
7117 static struct image_keyword pbm_format[PBM_LAST] =
7119 {":type", IMAGE_SYMBOL_VALUE, 1},
7120 {":file", IMAGE_STRING_VALUE, 0},
7121 {":data", IMAGE_STRING_VALUE, 0},
7122 {":ascent", IMAGE_ASCENT_VALUE, 0},
7123 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7124 {":relief", IMAGE_INTEGER_VALUE, 0},
7125 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7126 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7127 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7128 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
7129 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7132 /* Structure describing the image type `pbm'. */
7134 static struct image_type pbm_type =
7136 &Qpbm,
7137 pbm_image_p,
7138 pbm_load,
7139 x_clear_image,
7140 NULL
7144 /* Return non-zero if OBJECT is a valid PBM image specification. */
7146 static int
7147 pbm_image_p (object)
7148 Lisp_Object object;
7150 struct image_keyword fmt[PBM_LAST];
7152 bcopy (pbm_format, fmt, sizeof fmt);
7154 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7155 return 0;
7157 /* Must specify either :data or :file. */
7158 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7162 /* Scan a decimal number from *S and return it. Advance *S while
7163 reading the number. END is the end of the string. Value is -1 at
7164 end of input. */
7166 static int
7167 pbm_scan_number (s, end)
7168 unsigned char **s, *end;
7170 int c = 0, val = -1;
7172 while (*s < end)
7174 /* Skip white-space. */
7175 while (*s < end && (c = *(*s)++, isspace (c)))
7178 if (c == '#')
7180 /* Skip comment to end of line. */
7181 while (*s < end && (c = *(*s)++, c != '\n'))
7184 else if (isdigit (c))
7186 /* Read decimal number. */
7187 val = c - '0';
7188 while (*s < end && (c = *(*s)++, isdigit (c)))
7189 val = 10 * val + c - '0';
7190 break;
7192 else
7193 break;
7196 return val;
7200 /* Load PBM image IMG for use on frame F. */
7202 static int
7203 pbm_load (f, img)
7204 struct frame *f;
7205 struct image *img;
7207 int raw_p, x, y;
7208 int width, height, max_color_idx = 0;
7209 XImage *ximg;
7210 Lisp_Object file, specified_file;
7211 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7212 struct gcpro gcpro1;
7213 unsigned char *contents = NULL;
7214 unsigned char *end, *p;
7215 int size;
7217 specified_file = image_spec_value (img->spec, QCfile, NULL);
7218 file = Qnil;
7219 GCPRO1 (file);
7221 if (STRINGP (specified_file))
7223 file = x_find_image_file (specified_file);
7224 if (!STRINGP (file))
7226 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7227 UNGCPRO;
7228 return 0;
7231 contents = slurp_file (SDATA (file), &size);
7232 if (contents == NULL)
7234 image_error ("Error reading `%s'", file, Qnil);
7235 UNGCPRO;
7236 return 0;
7239 p = contents;
7240 end = contents + size;
7242 else
7244 Lisp_Object data;
7245 data = image_spec_value (img->spec, QCdata, NULL);
7246 p = SDATA (data);
7247 end = p + SBYTES (data);
7250 /* Check magic number. */
7251 if (end - p < 2 || *p++ != 'P')
7253 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7254 error:
7255 xfree (contents);
7256 UNGCPRO;
7257 return 0;
7260 switch (*p++)
7262 case '1':
7263 raw_p = 0, type = PBM_MONO;
7264 break;
7266 case '2':
7267 raw_p = 0, type = PBM_GRAY;
7268 break;
7270 case '3':
7271 raw_p = 0, type = PBM_COLOR;
7272 break;
7274 case '4':
7275 raw_p = 1, type = PBM_MONO;
7276 break;
7278 case '5':
7279 raw_p = 1, type = PBM_GRAY;
7280 break;
7282 case '6':
7283 raw_p = 1, type = PBM_COLOR;
7284 break;
7286 default:
7287 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
7288 goto error;
7291 /* Read width, height, maximum color-component. Characters
7292 starting with `#' up to the end of a line are ignored. */
7293 width = pbm_scan_number (&p, end);
7294 height = pbm_scan_number (&p, end);
7296 if (type != PBM_MONO)
7298 max_color_idx = pbm_scan_number (&p, end);
7299 if (raw_p && max_color_idx > 255)
7300 max_color_idx = 255;
7303 if (width < 0
7304 || height < 0
7305 || (type != PBM_MONO && max_color_idx < 0))
7306 goto error;
7308 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7309 &ximg, &img->pixmap))
7310 goto error;
7312 /* Initialize the color hash table. */
7313 init_color_table ();
7315 if (type == PBM_MONO)
7317 int c = 0, g;
7318 struct image_keyword fmt[PBM_LAST];
7319 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
7320 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
7322 /* Parse the image specification. */
7323 bcopy (pbm_format, fmt, sizeof fmt);
7324 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
7326 /* Get foreground and background colors, maybe allocate colors. */
7327 if (fmt[PBM_FOREGROUND].count
7328 && STRINGP (fmt[PBM_FOREGROUND].value))
7329 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
7330 if (fmt[PBM_BACKGROUND].count
7331 && STRINGP (fmt[PBM_BACKGROUND].value))
7333 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
7334 img->background = bg;
7335 img->background_valid = 1;
7338 for (y = 0; y < height; ++y)
7339 for (x = 0; x < width; ++x)
7341 if (raw_p)
7343 if ((x & 7) == 0)
7344 c = *p++;
7345 g = c & 0x80;
7346 c <<= 1;
7348 else
7349 g = pbm_scan_number (&p, end);
7351 XPutPixel (ximg, x, y, g ? fg : bg);
7354 else
7356 for (y = 0; y < height; ++y)
7357 for (x = 0; x < width; ++x)
7359 int r, g, b;
7361 if (type == PBM_GRAY)
7362 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7363 else if (raw_p)
7365 r = *p++;
7366 g = *p++;
7367 b = *p++;
7369 else
7371 r = pbm_scan_number (&p, end);
7372 g = pbm_scan_number (&p, end);
7373 b = pbm_scan_number (&p, end);
7376 if (r < 0 || g < 0 || b < 0)
7378 xfree (ximg->data);
7379 ximg->data = NULL;
7380 XDestroyImage (ximg);
7381 image_error ("Invalid pixel value in image `%s'",
7382 img->spec, Qnil);
7383 goto error;
7386 /* RGB values are now in the range 0..max_color_idx.
7387 Scale this to the range 0..0xffff supported by X. */
7388 r = (double) r * 65535 / max_color_idx;
7389 g = (double) g * 65535 / max_color_idx;
7390 b = (double) b * 65535 / max_color_idx;
7391 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7395 /* Store in IMG->colors the colors allocated for the image, and
7396 free the color table. */
7397 img->colors = colors_in_color_table (&img->ncolors);
7398 free_color_table ();
7400 /* Maybe fill in the background field while we have ximg handy. */
7401 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7402 IMAGE_BACKGROUND (img, f, ximg);
7404 /* Put the image into a pixmap. */
7405 x_put_x_image (f, ximg, img->pixmap, width, height);
7406 x_destroy_x_image (ximg);
7408 img->width = width;
7409 img->height = height;
7411 UNGCPRO;
7412 xfree (contents);
7413 return 1;
7418 /***********************************************************************
7420 ***********************************************************************/
7422 #if HAVE_PNG
7424 #include <png.h>
7426 /* Function prototypes. */
7428 static int png_image_p P_ ((Lisp_Object object));
7429 static int png_load P_ ((struct frame *f, struct image *img));
7431 /* The symbol `png' identifying images of this type. */
7433 Lisp_Object Qpng;
7435 /* Indices of image specification fields in png_format, below. */
7437 enum png_keyword_index
7439 PNG_TYPE,
7440 PNG_DATA,
7441 PNG_FILE,
7442 PNG_ASCENT,
7443 PNG_MARGIN,
7444 PNG_RELIEF,
7445 PNG_ALGORITHM,
7446 PNG_HEURISTIC_MASK,
7447 PNG_MASK,
7448 PNG_BACKGROUND,
7449 PNG_LAST
7452 /* Vector of image_keyword structures describing the format
7453 of valid user-defined image specifications. */
7455 static struct image_keyword png_format[PNG_LAST] =
7457 {":type", IMAGE_SYMBOL_VALUE, 1},
7458 {":data", IMAGE_STRING_VALUE, 0},
7459 {":file", IMAGE_STRING_VALUE, 0},
7460 {":ascent", IMAGE_ASCENT_VALUE, 0},
7461 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7462 {":relief", IMAGE_INTEGER_VALUE, 0},
7463 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7464 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7465 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7466 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7469 /* Structure describing the image type `png'. */
7471 static struct image_type png_type =
7473 &Qpng,
7474 png_image_p,
7475 png_load,
7476 x_clear_image,
7477 NULL
7481 /* Return non-zero if OBJECT is a valid PNG image specification. */
7483 static int
7484 png_image_p (object)
7485 Lisp_Object object;
7487 struct image_keyword fmt[PNG_LAST];
7488 bcopy (png_format, fmt, sizeof fmt);
7490 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
7491 return 0;
7493 /* Must specify either the :data or :file keyword. */
7494 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7498 /* Error and warning handlers installed when the PNG library
7499 is initialized. */
7501 static void
7502 my_png_error (png_ptr, msg)
7503 png_struct *png_ptr;
7504 char *msg;
7506 xassert (png_ptr != NULL);
7507 image_error ("PNG error: %s", build_string (msg), Qnil);
7508 longjmp (png_ptr->jmpbuf, 1);
7512 static void
7513 my_png_warning (png_ptr, msg)
7514 png_struct *png_ptr;
7515 char *msg;
7517 xassert (png_ptr != NULL);
7518 image_error ("PNG warning: %s", build_string (msg), Qnil);
7521 /* Memory source for PNG decoding. */
7523 struct png_memory_storage
7525 unsigned char *bytes; /* The data */
7526 size_t len; /* How big is it? */
7527 int index; /* Where are we? */
7531 /* Function set as reader function when reading PNG image from memory.
7532 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7533 bytes from the input to DATA. */
7535 static void
7536 png_read_from_memory (png_ptr, data, length)
7537 png_structp png_ptr;
7538 png_bytep data;
7539 png_size_t length;
7541 struct png_memory_storage *tbr
7542 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7544 if (length > tbr->len - tbr->index)
7545 png_error (png_ptr, "Read error");
7547 bcopy (tbr->bytes + tbr->index, data, length);
7548 tbr->index = tbr->index + length;
7551 /* Load PNG image IMG for use on frame F. Value is non-zero if
7552 successful. */
7554 static int
7555 png_load (f, img)
7556 struct frame *f;
7557 struct image *img;
7559 Lisp_Object file, specified_file;
7560 Lisp_Object specified_data;
7561 int x, y, i;
7562 XImage *ximg, *mask_img = NULL;
7563 struct gcpro gcpro1;
7564 png_struct *png_ptr = NULL;
7565 png_info *info_ptr = NULL, *end_info = NULL;
7566 FILE *volatile fp = NULL;
7567 png_byte sig[8];
7568 png_byte * volatile pixels = NULL;
7569 png_byte ** volatile rows = NULL;
7570 png_uint_32 width, height;
7571 int bit_depth, color_type, interlace_type;
7572 png_byte channels;
7573 png_uint_32 row_bytes;
7574 int transparent_p;
7575 double screen_gamma;
7576 struct png_memory_storage tbr; /* Data to be read */
7578 /* Find out what file to load. */
7579 specified_file = image_spec_value (img->spec, QCfile, NULL);
7580 specified_data = image_spec_value (img->spec, QCdata, NULL);
7581 file = Qnil;
7582 GCPRO1 (file);
7584 if (NILP (specified_data))
7586 file = x_find_image_file (specified_file);
7587 if (!STRINGP (file))
7589 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7590 UNGCPRO;
7591 return 0;
7594 /* Open the image file. */
7595 fp = fopen (SDATA (file), "rb");
7596 if (!fp)
7598 image_error ("Cannot open image file `%s'", file, Qnil);
7599 UNGCPRO;
7600 fclose (fp);
7601 return 0;
7604 /* Check PNG signature. */
7605 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7606 || !png_check_sig (sig, sizeof sig))
7608 image_error ("Not a PNG file: `%s'", file, Qnil);
7609 UNGCPRO;
7610 fclose (fp);
7611 return 0;
7614 else
7616 /* Read from memory. */
7617 tbr.bytes = SDATA (specified_data);
7618 tbr.len = SBYTES (specified_data);
7619 tbr.index = 0;
7621 /* Check PNG signature. */
7622 if (tbr.len < sizeof sig
7623 || !png_check_sig (tbr.bytes, sizeof sig))
7625 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7626 UNGCPRO;
7627 return 0;
7630 /* Need to skip past the signature. */
7631 tbr.bytes += sizeof (sig);
7634 /* Initialize read and info structs for PNG lib. */
7635 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7636 my_png_error, my_png_warning);
7637 if (!png_ptr)
7639 if (fp) fclose (fp);
7640 UNGCPRO;
7641 return 0;
7644 info_ptr = png_create_info_struct (png_ptr);
7645 if (!info_ptr)
7647 png_destroy_read_struct (&png_ptr, NULL, NULL);
7648 if (fp) fclose (fp);
7649 UNGCPRO;
7650 return 0;
7653 end_info = png_create_info_struct (png_ptr);
7654 if (!end_info)
7656 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7657 if (fp) fclose (fp);
7658 UNGCPRO;
7659 return 0;
7662 /* Set error jump-back. We come back here when the PNG library
7663 detects an error. */
7664 if (setjmp (png_ptr->jmpbuf))
7666 error:
7667 if (png_ptr)
7668 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7669 xfree (pixels);
7670 xfree (rows);
7671 if (fp) fclose (fp);
7672 UNGCPRO;
7673 return 0;
7676 /* Read image info. */
7677 if (!NILP (specified_data))
7678 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7679 else
7680 png_init_io (png_ptr, fp);
7682 png_set_sig_bytes (png_ptr, sizeof sig);
7683 png_read_info (png_ptr, info_ptr);
7684 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7685 &interlace_type, NULL, NULL);
7687 /* If image contains simply transparency data, we prefer to
7688 construct a clipping mask. */
7689 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7690 transparent_p = 1;
7691 else
7692 transparent_p = 0;
7694 /* This function is easier to write if we only have to handle
7695 one data format: RGB or RGBA with 8 bits per channel. Let's
7696 transform other formats into that format. */
7698 /* Strip more than 8 bits per channel. */
7699 if (bit_depth == 16)
7700 png_set_strip_16 (png_ptr);
7702 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7703 if available. */
7704 png_set_expand (png_ptr);
7706 /* Convert grayscale images to RGB. */
7707 if (color_type == PNG_COLOR_TYPE_GRAY
7708 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7709 png_set_gray_to_rgb (png_ptr);
7711 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
7713 #if 0 /* Avoid double gamma correction for PNG images. */
7714 { /* Tell the PNG lib to handle gamma correction for us. */
7715 int intent;
7716 double image_gamma;
7717 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7718 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7719 /* The libpng documentation says this is right in this case. */
7720 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7721 else
7722 #endif
7723 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7724 /* Image contains gamma information. */
7725 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7726 else
7727 /* Use the standard default for the image gamma. */
7728 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7730 #endif /* if 0 */
7732 /* Handle alpha channel by combining the image with a background
7733 color. Do this only if a real alpha channel is supplied. For
7734 simple transparency, we prefer a clipping mask. */
7735 if (!transparent_p)
7737 png_color_16 *image_bg;
7738 Lisp_Object specified_bg
7739 = image_spec_value (img->spec, QCbackground, NULL);
7741 if (STRINGP (specified_bg))
7742 /* The user specified `:background', use that. */
7744 XColor color;
7745 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
7747 png_color_16 user_bg;
7749 bzero (&user_bg, sizeof user_bg);
7750 user_bg.red = color.red;
7751 user_bg.green = color.green;
7752 user_bg.blue = color.blue;
7754 png_set_background (png_ptr, &user_bg,
7755 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7758 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
7759 /* Image contains a background color with which to
7760 combine the image. */
7761 png_set_background (png_ptr, image_bg,
7762 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7763 else
7765 /* Image does not contain a background color with which
7766 to combine the image data via an alpha channel. Use
7767 the frame's background instead. */
7768 XColor color;
7769 Colormap cmap;
7770 png_color_16 frame_background;
7772 cmap = FRAME_X_COLORMAP (f);
7773 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7774 x_query_color (f, &color);
7776 bzero (&frame_background, sizeof frame_background);
7777 frame_background.red = color.red;
7778 frame_background.green = color.green;
7779 frame_background.blue = color.blue;
7781 png_set_background (png_ptr, &frame_background,
7782 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7786 /* Update info structure. */
7787 png_read_update_info (png_ptr, info_ptr);
7789 /* Get number of channels. Valid values are 1 for grayscale images
7790 and images with a palette, 2 for grayscale images with transparency
7791 information (alpha channel), 3 for RGB images, and 4 for RGB
7792 images with alpha channel, i.e. RGBA. If conversions above were
7793 sufficient we should only have 3 or 4 channels here. */
7794 channels = png_get_channels (png_ptr, info_ptr);
7795 xassert (channels == 3 || channels == 4);
7797 /* Number of bytes needed for one row of the image. */
7798 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7800 /* Allocate memory for the image. */
7801 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7802 rows = (png_byte **) xmalloc (height * sizeof *rows);
7803 for (i = 0; i < height; ++i)
7804 rows[i] = pixels + i * row_bytes;
7806 /* Read the entire image. */
7807 png_read_image (png_ptr, rows);
7808 png_read_end (png_ptr, info_ptr);
7809 if (fp)
7811 fclose (fp);
7812 fp = NULL;
7815 /* Create the X image and pixmap. */
7816 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7817 &img->pixmap))
7818 goto error;
7820 /* Create an image and pixmap serving as mask if the PNG image
7821 contains an alpha channel. */
7822 if (channels == 4
7823 && !transparent_p
7824 && !x_create_x_image_and_pixmap (f, width, height, 1,
7825 &mask_img, &img->mask))
7827 x_destroy_x_image (ximg);
7828 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
7829 img->pixmap = None;
7830 goto error;
7833 /* Fill the X image and mask from PNG data. */
7834 init_color_table ();
7836 for (y = 0; y < height; ++y)
7838 png_byte *p = rows[y];
7840 for (x = 0; x < width; ++x)
7842 unsigned r, g, b;
7844 r = *p++ << 8;
7845 g = *p++ << 8;
7846 b = *p++ << 8;
7847 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7849 /* An alpha channel, aka mask channel, associates variable
7850 transparency with an image. Where other image formats
7851 support binary transparency---fully transparent or fully
7852 opaque---PNG allows up to 254 levels of partial transparency.
7853 The PNG library implements partial transparency by combining
7854 the image with a specified background color.
7856 I'm not sure how to handle this here nicely: because the
7857 background on which the image is displayed may change, for
7858 real alpha channel support, it would be necessary to create
7859 a new image for each possible background.
7861 What I'm doing now is that a mask is created if we have
7862 boolean transparency information. Otherwise I'm using
7863 the frame's background color to combine the image with. */
7865 if (channels == 4)
7867 if (mask_img)
7868 XPutPixel (mask_img, x, y, *p > 0);
7869 ++p;
7874 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7875 /* Set IMG's background color from the PNG image, unless the user
7876 overrode it. */
7878 png_color_16 *bg;
7879 if (png_get_bKGD (png_ptr, info_ptr, &bg))
7881 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
7882 img->background_valid = 1;
7886 /* Remember colors allocated for this image. */
7887 img->colors = colors_in_color_table (&img->ncolors);
7888 free_color_table ();
7890 /* Clean up. */
7891 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7892 xfree (rows);
7893 xfree (pixels);
7895 img->width = width;
7896 img->height = height;
7898 /* Maybe fill in the background field while we have ximg handy. */
7899 IMAGE_BACKGROUND (img, f, ximg);
7901 /* Put the image into the pixmap, then free the X image and its buffer. */
7902 x_put_x_image (f, ximg, img->pixmap, width, height);
7903 x_destroy_x_image (ximg);
7905 /* Same for the mask. */
7906 if (mask_img)
7908 /* Fill in the background_transparent field while we have the mask
7909 handy. */
7910 image_background_transparent (img, f, mask_img);
7912 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7913 x_destroy_x_image (mask_img);
7916 UNGCPRO;
7917 return 1;
7920 #endif /* HAVE_PNG != 0 */
7924 /***********************************************************************
7925 JPEG
7926 ***********************************************************************/
7928 #if HAVE_JPEG
7930 /* Work around a warning about HAVE_STDLIB_H being redefined in
7931 jconfig.h. */
7932 #ifdef HAVE_STDLIB_H
7933 #define HAVE_STDLIB_H_1
7934 #undef HAVE_STDLIB_H
7935 #endif /* HAVE_STLIB_H */
7937 #include <jpeglib.h>
7938 #include <jerror.h>
7939 #include <setjmp.h>
7941 #ifdef HAVE_STLIB_H_1
7942 #define HAVE_STDLIB_H 1
7943 #endif
7945 static int jpeg_image_p P_ ((Lisp_Object object));
7946 static int jpeg_load P_ ((struct frame *f, struct image *img));
7948 /* The symbol `jpeg' identifying images of this type. */
7950 Lisp_Object Qjpeg;
7952 /* Indices of image specification fields in gs_format, below. */
7954 enum jpeg_keyword_index
7956 JPEG_TYPE,
7957 JPEG_DATA,
7958 JPEG_FILE,
7959 JPEG_ASCENT,
7960 JPEG_MARGIN,
7961 JPEG_RELIEF,
7962 JPEG_ALGORITHM,
7963 JPEG_HEURISTIC_MASK,
7964 JPEG_MASK,
7965 JPEG_BACKGROUND,
7966 JPEG_LAST
7969 /* Vector of image_keyword structures describing the format
7970 of valid user-defined image specifications. */
7972 static struct image_keyword jpeg_format[JPEG_LAST] =
7974 {":type", IMAGE_SYMBOL_VALUE, 1},
7975 {":data", IMAGE_STRING_VALUE, 0},
7976 {":file", IMAGE_STRING_VALUE, 0},
7977 {":ascent", IMAGE_ASCENT_VALUE, 0},
7978 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7979 {":relief", IMAGE_INTEGER_VALUE, 0},
7980 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7981 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7982 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7983 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7986 /* Structure describing the image type `jpeg'. */
7988 static struct image_type jpeg_type =
7990 &Qjpeg,
7991 jpeg_image_p,
7992 jpeg_load,
7993 x_clear_image,
7994 NULL
7998 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8000 static int
8001 jpeg_image_p (object)
8002 Lisp_Object object;
8004 struct image_keyword fmt[JPEG_LAST];
8006 bcopy (jpeg_format, fmt, sizeof fmt);
8008 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8009 return 0;
8011 /* Must specify either the :data or :file keyword. */
8012 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8016 struct my_jpeg_error_mgr
8018 struct jpeg_error_mgr pub;
8019 jmp_buf setjmp_buffer;
8023 static void
8024 my_error_exit (cinfo)
8025 j_common_ptr cinfo;
8027 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8028 longjmp (mgr->setjmp_buffer, 1);
8032 /* Init source method for JPEG data source manager. Called by
8033 jpeg_read_header() before any data is actually read. See
8034 libjpeg.doc from the JPEG lib distribution. */
8036 static void
8037 our_init_source (cinfo)
8038 j_decompress_ptr cinfo;
8043 /* Fill input buffer method for JPEG data source manager. Called
8044 whenever more data is needed. We read the whole image in one step,
8045 so this only adds a fake end of input marker at the end. */
8047 static boolean
8048 our_fill_input_buffer (cinfo)
8049 j_decompress_ptr cinfo;
8051 /* Insert a fake EOI marker. */
8052 struct jpeg_source_mgr *src = cinfo->src;
8053 static JOCTET buffer[2];
8055 buffer[0] = (JOCTET) 0xFF;
8056 buffer[1] = (JOCTET) JPEG_EOI;
8058 src->next_input_byte = buffer;
8059 src->bytes_in_buffer = 2;
8060 return TRUE;
8064 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8065 is the JPEG data source manager. */
8067 static void
8068 our_skip_input_data (cinfo, num_bytes)
8069 j_decompress_ptr cinfo;
8070 long num_bytes;
8072 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8074 if (src)
8076 if (num_bytes > src->bytes_in_buffer)
8077 ERREXIT (cinfo, JERR_INPUT_EOF);
8079 src->bytes_in_buffer -= num_bytes;
8080 src->next_input_byte += num_bytes;
8085 /* Method to terminate data source. Called by
8086 jpeg_finish_decompress() after all data has been processed. */
8088 static void
8089 our_term_source (cinfo)
8090 j_decompress_ptr cinfo;
8095 /* Set up the JPEG lib for reading an image from DATA which contains
8096 LEN bytes. CINFO is the decompression info structure created for
8097 reading the image. */
8099 static void
8100 jpeg_memory_src (cinfo, data, len)
8101 j_decompress_ptr cinfo;
8102 JOCTET *data;
8103 unsigned int len;
8105 struct jpeg_source_mgr *src;
8107 if (cinfo->src == NULL)
8109 /* First time for this JPEG object? */
8110 cinfo->src = (struct jpeg_source_mgr *)
8111 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8112 sizeof (struct jpeg_source_mgr));
8113 src = (struct jpeg_source_mgr *) cinfo->src;
8114 src->next_input_byte = data;
8117 src = (struct jpeg_source_mgr *) cinfo->src;
8118 src->init_source = our_init_source;
8119 src->fill_input_buffer = our_fill_input_buffer;
8120 src->skip_input_data = our_skip_input_data;
8121 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8122 src->term_source = our_term_source;
8123 src->bytes_in_buffer = len;
8124 src->next_input_byte = data;
8128 /* Load image IMG for use on frame F. Patterned after example.c
8129 from the JPEG lib. */
8131 static int
8132 jpeg_load (f, img)
8133 struct frame *f;
8134 struct image *img;
8136 struct jpeg_decompress_struct cinfo;
8137 struct my_jpeg_error_mgr mgr;
8138 Lisp_Object file, specified_file;
8139 Lisp_Object specified_data;
8140 FILE * volatile fp = NULL;
8141 JSAMPARRAY buffer;
8142 int row_stride, x, y;
8143 XImage *ximg = NULL;
8144 int rc;
8145 unsigned long *colors;
8146 int width, height;
8147 struct gcpro gcpro1;
8149 /* Open the JPEG file. */
8150 specified_file = image_spec_value (img->spec, QCfile, NULL);
8151 specified_data = image_spec_value (img->spec, QCdata, NULL);
8152 file = Qnil;
8153 GCPRO1 (file);
8155 if (NILP (specified_data))
8157 file = x_find_image_file (specified_file);
8158 if (!STRINGP (file))
8160 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8161 UNGCPRO;
8162 return 0;
8165 fp = fopen (SDATA (file), "r");
8166 if (fp == NULL)
8168 image_error ("Cannot open `%s'", file, Qnil);
8169 UNGCPRO;
8170 return 0;
8174 /* Customize libjpeg's error handling to call my_error_exit when an
8175 error is detected. This function will perform a longjmp. */
8176 cinfo.err = jpeg_std_error (&mgr.pub);
8177 mgr.pub.error_exit = my_error_exit;
8179 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8181 if (rc == 1)
8183 /* Called from my_error_exit. Display a JPEG error. */
8184 char buffer[JMSG_LENGTH_MAX];
8185 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8186 image_error ("Error reading JPEG image `%s': %s", img->spec,
8187 build_string (buffer));
8190 /* Close the input file and destroy the JPEG object. */
8191 if (fp)
8192 fclose ((FILE *) fp);
8193 jpeg_destroy_decompress (&cinfo);
8195 /* If we already have an XImage, free that. */
8196 x_destroy_x_image (ximg);
8198 /* Free pixmap and colors. */
8199 x_clear_image (f, img);
8201 UNGCPRO;
8202 return 0;
8205 /* Create the JPEG decompression object. Let it read from fp.
8206 Read the JPEG image header. */
8207 jpeg_create_decompress (&cinfo);
8209 if (NILP (specified_data))
8210 jpeg_stdio_src (&cinfo, (FILE *) fp);
8211 else
8212 jpeg_memory_src (&cinfo, SDATA (specified_data),
8213 SBYTES (specified_data));
8215 jpeg_read_header (&cinfo, TRUE);
8217 /* Customize decompression so that color quantization will be used.
8218 Start decompression. */
8219 cinfo.quantize_colors = TRUE;
8220 jpeg_start_decompress (&cinfo);
8221 width = img->width = cinfo.output_width;
8222 height = img->height = cinfo.output_height;
8224 /* Create X image and pixmap. */
8225 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8226 longjmp (mgr.setjmp_buffer, 2);
8228 /* Allocate colors. When color quantization is used,
8229 cinfo.actual_number_of_colors has been set with the number of
8230 colors generated, and cinfo.colormap is a two-dimensional array
8231 of color indices in the range 0..cinfo.actual_number_of_colors.
8232 No more than 255 colors will be generated. */
8234 int i, ir, ig, ib;
8236 if (cinfo.out_color_components > 2)
8237 ir = 0, ig = 1, ib = 2;
8238 else if (cinfo.out_color_components > 1)
8239 ir = 0, ig = 1, ib = 0;
8240 else
8241 ir = 0, ig = 0, ib = 0;
8243 /* Use the color table mechanism because it handles colors that
8244 cannot be allocated nicely. Such colors will be replaced with
8245 a default color, and we don't have to care about which colors
8246 can be freed safely, and which can't. */
8247 init_color_table ();
8248 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8249 * sizeof *colors);
8251 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8253 /* Multiply RGB values with 255 because X expects RGB values
8254 in the range 0..0xffff. */
8255 int r = cinfo.colormap[ir][i] << 8;
8256 int g = cinfo.colormap[ig][i] << 8;
8257 int b = cinfo.colormap[ib][i] << 8;
8258 colors[i] = lookup_rgb_color (f, r, g, b);
8261 /* Remember those colors actually allocated. */
8262 img->colors = colors_in_color_table (&img->ncolors);
8263 free_color_table ();
8266 /* Read pixels. */
8267 row_stride = width * cinfo.output_components;
8268 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8269 row_stride, 1);
8270 for (y = 0; y < height; ++y)
8272 jpeg_read_scanlines (&cinfo, buffer, 1);
8273 for (x = 0; x < cinfo.output_width; ++x)
8274 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8277 /* Clean up. */
8278 jpeg_finish_decompress (&cinfo);
8279 jpeg_destroy_decompress (&cinfo);
8280 if (fp)
8281 fclose ((FILE *) fp);
8283 /* Maybe fill in the background field while we have ximg handy. */
8284 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8285 IMAGE_BACKGROUND (img, f, ximg);
8287 /* Put the image into the pixmap. */
8288 x_put_x_image (f, ximg, img->pixmap, width, height);
8289 x_destroy_x_image (ximg);
8290 UNGCPRO;
8291 return 1;
8294 #endif /* HAVE_JPEG */
8298 /***********************************************************************
8299 TIFF
8300 ***********************************************************************/
8302 #if HAVE_TIFF
8304 #include <tiffio.h>
8306 static int tiff_image_p P_ ((Lisp_Object object));
8307 static int tiff_load P_ ((struct frame *f, struct image *img));
8309 /* The symbol `tiff' identifying images of this type. */
8311 Lisp_Object Qtiff;
8313 /* Indices of image specification fields in tiff_format, below. */
8315 enum tiff_keyword_index
8317 TIFF_TYPE,
8318 TIFF_DATA,
8319 TIFF_FILE,
8320 TIFF_ASCENT,
8321 TIFF_MARGIN,
8322 TIFF_RELIEF,
8323 TIFF_ALGORITHM,
8324 TIFF_HEURISTIC_MASK,
8325 TIFF_MASK,
8326 TIFF_BACKGROUND,
8327 TIFF_LAST
8330 /* Vector of image_keyword structures describing the format
8331 of valid user-defined image specifications. */
8333 static struct image_keyword tiff_format[TIFF_LAST] =
8335 {":type", IMAGE_SYMBOL_VALUE, 1},
8336 {":data", IMAGE_STRING_VALUE, 0},
8337 {":file", IMAGE_STRING_VALUE, 0},
8338 {":ascent", IMAGE_ASCENT_VALUE, 0},
8339 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8340 {":relief", IMAGE_INTEGER_VALUE, 0},
8341 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8342 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8343 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8344 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8347 /* Structure describing the image type `tiff'. */
8349 static struct image_type tiff_type =
8351 &Qtiff,
8352 tiff_image_p,
8353 tiff_load,
8354 x_clear_image,
8355 NULL
8359 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8361 static int
8362 tiff_image_p (object)
8363 Lisp_Object object;
8365 struct image_keyword fmt[TIFF_LAST];
8366 bcopy (tiff_format, fmt, sizeof fmt);
8368 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
8369 return 0;
8371 /* Must specify either the :data or :file keyword. */
8372 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8376 /* Reading from a memory buffer for TIFF images Based on the PNG
8377 memory source, but we have to provide a lot of extra functions.
8378 Blah.
8380 We really only need to implement read and seek, but I am not
8381 convinced that the TIFF library is smart enough not to destroy
8382 itself if we only hand it the function pointers we need to
8383 override. */
8385 typedef struct
8387 unsigned char *bytes;
8388 size_t len;
8389 int index;
8391 tiff_memory_source;
8394 static size_t
8395 tiff_read_from_memory (data, buf, size)
8396 thandle_t data;
8397 tdata_t buf;
8398 tsize_t size;
8400 tiff_memory_source *src = (tiff_memory_source *) data;
8402 if (size > src->len - src->index)
8403 return (size_t) -1;
8404 bcopy (src->bytes + src->index, buf, size);
8405 src->index += size;
8406 return size;
8410 static size_t
8411 tiff_write_from_memory (data, buf, size)
8412 thandle_t data;
8413 tdata_t buf;
8414 tsize_t size;
8416 return (size_t) -1;
8420 static toff_t
8421 tiff_seek_in_memory (data, off, whence)
8422 thandle_t data;
8423 toff_t off;
8424 int whence;
8426 tiff_memory_source *src = (tiff_memory_source *) data;
8427 int idx;
8429 switch (whence)
8431 case SEEK_SET: /* Go from beginning of source. */
8432 idx = off;
8433 break;
8435 case SEEK_END: /* Go from end of source. */
8436 idx = src->len + off;
8437 break;
8439 case SEEK_CUR: /* Go from current position. */
8440 idx = src->index + off;
8441 break;
8443 default: /* Invalid `whence'. */
8444 return -1;
8447 if (idx > src->len || idx < 0)
8448 return -1;
8450 src->index = idx;
8451 return src->index;
8455 static int
8456 tiff_close_memory (data)
8457 thandle_t data;
8459 /* NOOP */
8460 return 0;
8464 static int
8465 tiff_mmap_memory (data, pbase, psize)
8466 thandle_t data;
8467 tdata_t *pbase;
8468 toff_t *psize;
8470 /* It is already _IN_ memory. */
8471 return 0;
8475 static void
8476 tiff_unmap_memory (data, base, size)
8477 thandle_t data;
8478 tdata_t base;
8479 toff_t size;
8481 /* We don't need to do this. */
8485 static toff_t
8486 tiff_size_of_memory (data)
8487 thandle_t data;
8489 return ((tiff_memory_source *) data)->len;
8493 static void
8494 tiff_error_handler (title, format, ap)
8495 const char *title, *format;
8496 va_list ap;
8498 char buf[512];
8499 int len;
8501 len = sprintf (buf, "TIFF error: %s ", title);
8502 vsprintf (buf + len, format, ap);
8503 add_to_log (buf, Qnil, Qnil);
8507 static void
8508 tiff_warning_handler (title, format, ap)
8509 const char *title, *format;
8510 va_list ap;
8512 char buf[512];
8513 int len;
8515 len = sprintf (buf, "TIFF warning: %s ", title);
8516 vsprintf (buf + len, format, ap);
8517 add_to_log (buf, Qnil, Qnil);
8521 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8522 successful. */
8524 static int
8525 tiff_load (f, img)
8526 struct frame *f;
8527 struct image *img;
8529 Lisp_Object file, specified_file;
8530 Lisp_Object specified_data;
8531 TIFF *tiff;
8532 int width, height, x, y;
8533 uint32 *buf;
8534 int rc;
8535 XImage *ximg;
8536 struct gcpro gcpro1;
8537 tiff_memory_source memsrc;
8539 specified_file = image_spec_value (img->spec, QCfile, NULL);
8540 specified_data = image_spec_value (img->spec, QCdata, NULL);
8541 file = Qnil;
8542 GCPRO1 (file);
8544 TIFFSetErrorHandler (tiff_error_handler);
8545 TIFFSetWarningHandler (tiff_warning_handler);
8547 if (NILP (specified_data))
8549 /* Read from a file */
8550 file = x_find_image_file (specified_file);
8551 if (!STRINGP (file))
8553 image_error ("Cannot find image file `%s'", file, Qnil);
8554 UNGCPRO;
8555 return 0;
8558 /* Try to open the image file. */
8559 tiff = TIFFOpen (SDATA (file), "r");
8560 if (tiff == NULL)
8562 image_error ("Cannot open `%s'", file, Qnil);
8563 UNGCPRO;
8564 return 0;
8567 else
8569 /* Memory source! */
8570 memsrc.bytes = SDATA (specified_data);
8571 memsrc.len = SBYTES (specified_data);
8572 memsrc.index = 0;
8574 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8575 (TIFFReadWriteProc) tiff_read_from_memory,
8576 (TIFFReadWriteProc) tiff_write_from_memory,
8577 tiff_seek_in_memory,
8578 tiff_close_memory,
8579 tiff_size_of_memory,
8580 tiff_mmap_memory,
8581 tiff_unmap_memory);
8583 if (!tiff)
8585 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8586 UNGCPRO;
8587 return 0;
8591 /* Get width and height of the image, and allocate a raster buffer
8592 of width x height 32-bit values. */
8593 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8594 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8595 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8597 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8598 TIFFClose (tiff);
8599 if (!rc)
8601 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8602 xfree (buf);
8603 UNGCPRO;
8604 return 0;
8607 /* Create the X image and pixmap. */
8608 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8610 xfree (buf);
8611 UNGCPRO;
8612 return 0;
8615 /* Initialize the color table. */
8616 init_color_table ();
8618 /* Process the pixel raster. Origin is in the lower-left corner. */
8619 for (y = 0; y < height; ++y)
8621 uint32 *row = buf + y * width;
8623 for (x = 0; x < width; ++x)
8625 uint32 abgr = row[x];
8626 int r = TIFFGetR (abgr) << 8;
8627 int g = TIFFGetG (abgr) << 8;
8628 int b = TIFFGetB (abgr) << 8;
8629 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8633 /* Remember the colors allocated for the image. Free the color table. */
8634 img->colors = colors_in_color_table (&img->ncolors);
8635 free_color_table ();
8637 img->width = width;
8638 img->height = height;
8640 /* Maybe fill in the background field while we have ximg handy. */
8641 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8642 IMAGE_BACKGROUND (img, f, ximg);
8644 /* Put the image into the pixmap, then free the X image and its buffer. */
8645 x_put_x_image (f, ximg, img->pixmap, width, height);
8646 x_destroy_x_image (ximg);
8647 xfree (buf);
8649 UNGCPRO;
8650 return 1;
8653 #endif /* HAVE_TIFF != 0 */
8657 /***********************************************************************
8659 ***********************************************************************/
8661 #if HAVE_GIF
8663 #include <gif_lib.h>
8665 static int gif_image_p P_ ((Lisp_Object object));
8666 static int gif_load P_ ((struct frame *f, struct image *img));
8668 /* The symbol `gif' identifying images of this type. */
8670 Lisp_Object Qgif;
8672 /* Indices of image specification fields in gif_format, below. */
8674 enum gif_keyword_index
8676 GIF_TYPE,
8677 GIF_DATA,
8678 GIF_FILE,
8679 GIF_ASCENT,
8680 GIF_MARGIN,
8681 GIF_RELIEF,
8682 GIF_ALGORITHM,
8683 GIF_HEURISTIC_MASK,
8684 GIF_MASK,
8685 GIF_IMAGE,
8686 GIF_BACKGROUND,
8687 GIF_LAST
8690 /* Vector of image_keyword structures describing the format
8691 of valid user-defined image specifications. */
8693 static struct image_keyword gif_format[GIF_LAST] =
8695 {":type", IMAGE_SYMBOL_VALUE, 1},
8696 {":data", IMAGE_STRING_VALUE, 0},
8697 {":file", IMAGE_STRING_VALUE, 0},
8698 {":ascent", IMAGE_ASCENT_VALUE, 0},
8699 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8700 {":relief", IMAGE_INTEGER_VALUE, 0},
8701 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8702 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8703 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8704 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8705 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8708 /* Structure describing the image type `gif'. */
8710 static struct image_type gif_type =
8712 &Qgif,
8713 gif_image_p,
8714 gif_load,
8715 x_clear_image,
8716 NULL
8720 /* Return non-zero if OBJECT is a valid GIF image specification. */
8722 static int
8723 gif_image_p (object)
8724 Lisp_Object object;
8726 struct image_keyword fmt[GIF_LAST];
8727 bcopy (gif_format, fmt, sizeof fmt);
8729 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8730 return 0;
8732 /* Must specify either the :data or :file keyword. */
8733 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8737 /* Reading a GIF image from memory
8738 Based on the PNG memory stuff to a certain extent. */
8740 typedef struct
8742 unsigned char *bytes;
8743 size_t len;
8744 int index;
8746 gif_memory_source;
8749 /* Make the current memory source available to gif_read_from_memory.
8750 It's done this way because not all versions of libungif support
8751 a UserData field in the GifFileType structure. */
8752 static gif_memory_source *current_gif_memory_src;
8754 static int
8755 gif_read_from_memory (file, buf, len)
8756 GifFileType *file;
8757 GifByteType *buf;
8758 int len;
8760 gif_memory_source *src = current_gif_memory_src;
8762 if (len > src->len - src->index)
8763 return -1;
8765 bcopy (src->bytes + src->index, buf, len);
8766 src->index += len;
8767 return len;
8771 /* Load GIF image IMG for use on frame F. Value is non-zero if
8772 successful. */
8774 static int
8775 gif_load (f, img)
8776 struct frame *f;
8777 struct image *img;
8779 Lisp_Object file, specified_file;
8780 Lisp_Object specified_data;
8781 int rc, width, height, x, y, i;
8782 XImage *ximg;
8783 ColorMapObject *gif_color_map;
8784 unsigned long pixel_colors[256];
8785 GifFileType *gif;
8786 struct gcpro gcpro1;
8787 Lisp_Object image;
8788 int ino, image_left, image_top, image_width, image_height;
8789 gif_memory_source memsrc;
8790 unsigned char *raster;
8792 specified_file = image_spec_value (img->spec, QCfile, NULL);
8793 specified_data = image_spec_value (img->spec, QCdata, NULL);
8794 file = Qnil;
8795 GCPRO1 (file);
8797 if (NILP (specified_data))
8799 file = x_find_image_file (specified_file);
8800 if (!STRINGP (file))
8802 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8803 UNGCPRO;
8804 return 0;
8807 /* Open the GIF file. */
8808 gif = DGifOpenFileName (SDATA (file));
8809 if (gif == NULL)
8811 image_error ("Cannot open `%s'", file, Qnil);
8812 UNGCPRO;
8813 return 0;
8816 else
8818 /* Read from memory! */
8819 current_gif_memory_src = &memsrc;
8820 memsrc.bytes = SDATA (specified_data);
8821 memsrc.len = SBYTES (specified_data);
8822 memsrc.index = 0;
8824 gif = DGifOpen(&memsrc, gif_read_from_memory);
8825 if (!gif)
8827 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8828 UNGCPRO;
8829 return 0;
8833 /* Read entire contents. */
8834 rc = DGifSlurp (gif);
8835 if (rc == GIF_ERROR)
8837 image_error ("Error reading `%s'", img->spec, Qnil);
8838 DGifCloseFile (gif);
8839 UNGCPRO;
8840 return 0;
8843 image = image_spec_value (img->spec, QCindex, NULL);
8844 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8845 if (ino >= gif->ImageCount)
8847 image_error ("Invalid image number `%s' in image `%s'",
8848 image, img->spec);
8849 DGifCloseFile (gif);
8850 UNGCPRO;
8851 return 0;
8854 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
8855 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
8857 /* Create the X image and pixmap. */
8858 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8860 DGifCloseFile (gif);
8861 UNGCPRO;
8862 return 0;
8865 /* Allocate colors. */
8866 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8867 if (!gif_color_map)
8868 gif_color_map = gif->SColorMap;
8869 init_color_table ();
8870 bzero (pixel_colors, sizeof pixel_colors);
8872 for (i = 0; i < gif_color_map->ColorCount; ++i)
8874 int r = gif_color_map->Colors[i].Red << 8;
8875 int g = gif_color_map->Colors[i].Green << 8;
8876 int b = gif_color_map->Colors[i].Blue << 8;
8877 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8880 img->colors = colors_in_color_table (&img->ncolors);
8881 free_color_table ();
8883 /* Clear the part of the screen image that are not covered by
8884 the image from the GIF file. Full animated GIF support
8885 requires more than can be done here (see the gif89 spec,
8886 disposal methods). Let's simply assume that the part
8887 not covered by a sub-image is in the frame's background color. */
8888 image_top = gif->SavedImages[ino].ImageDesc.Top;
8889 image_left = gif->SavedImages[ino].ImageDesc.Left;
8890 image_width = gif->SavedImages[ino].ImageDesc.Width;
8891 image_height = gif->SavedImages[ino].ImageDesc.Height;
8893 for (y = 0; y < image_top; ++y)
8894 for (x = 0; x < width; ++x)
8895 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8897 for (y = image_top + image_height; y < height; ++y)
8898 for (x = 0; x < width; ++x)
8899 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8901 for (y = image_top; y < image_top + image_height; ++y)
8903 for (x = 0; x < image_left; ++x)
8904 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8905 for (x = image_left + image_width; x < width; ++x)
8906 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8909 /* Read the GIF image into the X image. We use a local variable
8910 `raster' here because RasterBits below is a char *, and invites
8911 problems with bytes >= 0x80. */
8912 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8914 if (gif->SavedImages[ino].ImageDesc.Interlace)
8916 static int interlace_start[] = {0, 4, 2, 1};
8917 static int interlace_increment[] = {8, 8, 4, 2};
8918 int pass;
8919 int row = interlace_start[0];
8921 pass = 0;
8923 for (y = 0; y < image_height; y++)
8925 if (row >= image_height)
8927 row = interlace_start[++pass];
8928 while (row >= image_height)
8929 row = interlace_start[++pass];
8932 for (x = 0; x < image_width; x++)
8934 int i = raster[(y * image_width) + x];
8935 XPutPixel (ximg, x + image_left, row + image_top,
8936 pixel_colors[i]);
8939 row += interlace_increment[pass];
8942 else
8944 for (y = 0; y < image_height; ++y)
8945 for (x = 0; x < image_width; ++x)
8947 int i = raster[y * image_width + x];
8948 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8952 DGifCloseFile (gif);
8954 /* Maybe fill in the background field while we have ximg handy. */
8955 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8956 IMAGE_BACKGROUND (img, f, ximg);
8958 /* Put the image into the pixmap, then free the X image and its buffer. */
8959 x_put_x_image (f, ximg, img->pixmap, width, height);
8960 x_destroy_x_image (ximg);
8962 UNGCPRO;
8963 return 1;
8966 #endif /* HAVE_GIF != 0 */
8970 /***********************************************************************
8971 Ghostscript
8972 ***********************************************************************/
8974 static int gs_image_p P_ ((Lisp_Object object));
8975 static int gs_load P_ ((struct frame *f, struct image *img));
8976 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8978 /* The symbol `postscript' identifying images of this type. */
8980 Lisp_Object Qpostscript;
8982 /* Keyword symbols. */
8984 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8986 /* Indices of image specification fields in gs_format, below. */
8988 enum gs_keyword_index
8990 GS_TYPE,
8991 GS_PT_WIDTH,
8992 GS_PT_HEIGHT,
8993 GS_FILE,
8994 GS_LOADER,
8995 GS_BOUNDING_BOX,
8996 GS_ASCENT,
8997 GS_MARGIN,
8998 GS_RELIEF,
8999 GS_ALGORITHM,
9000 GS_HEURISTIC_MASK,
9001 GS_MASK,
9002 GS_BACKGROUND,
9003 GS_LAST
9006 /* Vector of image_keyword structures describing the format
9007 of valid user-defined image specifications. */
9009 static struct image_keyword gs_format[GS_LAST] =
9011 {":type", IMAGE_SYMBOL_VALUE, 1},
9012 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9013 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9014 {":file", IMAGE_STRING_VALUE, 1},
9015 {":loader", IMAGE_FUNCTION_VALUE, 0},
9016 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9017 {":ascent", IMAGE_ASCENT_VALUE, 0},
9018 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9019 {":relief", IMAGE_INTEGER_VALUE, 0},
9020 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9021 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9022 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9023 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9026 /* Structure describing the image type `ghostscript'. */
9028 static struct image_type gs_type =
9030 &Qpostscript,
9031 gs_image_p,
9032 gs_load,
9033 gs_clear_image,
9034 NULL
9038 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9040 static void
9041 gs_clear_image (f, img)
9042 struct frame *f;
9043 struct image *img;
9045 /* IMG->data.ptr_val may contain a recorded colormap. */
9046 xfree (img->data.ptr_val);
9047 x_clear_image (f, img);
9051 /* Return non-zero if OBJECT is a valid Ghostscript image
9052 specification. */
9054 static int
9055 gs_image_p (object)
9056 Lisp_Object object;
9058 struct image_keyword fmt[GS_LAST];
9059 Lisp_Object tem;
9060 int i;
9062 bcopy (gs_format, fmt, sizeof fmt);
9064 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9065 return 0;
9067 /* Bounding box must be a list or vector containing 4 integers. */
9068 tem = fmt[GS_BOUNDING_BOX].value;
9069 if (CONSP (tem))
9071 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9072 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9073 return 0;
9074 if (!NILP (tem))
9075 return 0;
9077 else if (VECTORP (tem))
9079 if (XVECTOR (tem)->size != 4)
9080 return 0;
9081 for (i = 0; i < 4; ++i)
9082 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9083 return 0;
9085 else
9086 return 0;
9088 return 1;
9092 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9093 if successful. */
9095 static int
9096 gs_load (f, img)
9097 struct frame *f;
9098 struct image *img;
9100 char buffer[100];
9101 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9102 struct gcpro gcpro1, gcpro2;
9103 Lisp_Object frame;
9104 double in_width, in_height;
9105 Lisp_Object pixel_colors = Qnil;
9107 /* Compute pixel size of pixmap needed from the given size in the
9108 image specification. Sizes in the specification are in pt. 1 pt
9109 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9110 info. */
9111 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9112 in_width = XFASTINT (pt_width) / 72.0;
9113 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9114 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9115 in_height = XFASTINT (pt_height) / 72.0;
9116 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9118 /* Create the pixmap. */
9119 xassert (img->pixmap == None);
9120 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9121 img->width, img->height,
9122 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9124 if (!img->pixmap)
9126 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9127 return 0;
9130 /* Call the loader to fill the pixmap. It returns a process object
9131 if successful. We do not record_unwind_protect here because
9132 other places in redisplay like calling window scroll functions
9133 don't either. Let the Lisp loader use `unwind-protect' instead. */
9134 GCPRO2 (window_and_pixmap_id, pixel_colors);
9136 sprintf (buffer, "%lu %lu",
9137 (unsigned long) FRAME_X_WINDOW (f),
9138 (unsigned long) img->pixmap);
9139 window_and_pixmap_id = build_string (buffer);
9141 sprintf (buffer, "%lu %lu",
9142 FRAME_FOREGROUND_PIXEL (f),
9143 FRAME_BACKGROUND_PIXEL (f));
9144 pixel_colors = build_string (buffer);
9146 XSETFRAME (frame, f);
9147 loader = image_spec_value (img->spec, QCloader, NULL);
9148 if (NILP (loader))
9149 loader = intern ("gs-load-image");
9151 img->data.lisp_val = call6 (loader, frame, img->spec,
9152 make_number (img->width),
9153 make_number (img->height),
9154 window_and_pixmap_id,
9155 pixel_colors);
9156 UNGCPRO;
9157 return PROCESSP (img->data.lisp_val);
9161 /* Kill the Ghostscript process that was started to fill PIXMAP on
9162 frame F. Called from XTread_socket when receiving an event
9163 telling Emacs that Ghostscript has finished drawing. */
9165 void
9166 x_kill_gs_process (pixmap, f)
9167 Pixmap pixmap;
9168 struct frame *f;
9170 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9171 int class, i;
9172 struct image *img;
9174 /* Find the image containing PIXMAP. */
9175 for (i = 0; i < c->used; ++i)
9176 if (c->images[i]->pixmap == pixmap)
9177 break;
9179 /* Should someone in between have cleared the image cache, for
9180 instance, give up. */
9181 if (i == c->used)
9182 return;
9184 /* Kill the GS process. We should have found PIXMAP in the image
9185 cache and its image should contain a process object. */
9186 img = c->images[i];
9187 xassert (PROCESSP (img->data.lisp_val));
9188 Fkill_process (img->data.lisp_val, Qnil);
9189 img->data.lisp_val = Qnil;
9191 /* On displays with a mutable colormap, figure out the colors
9192 allocated for the image by looking at the pixels of an XImage for
9193 img->pixmap. */
9194 class = FRAME_X_VISUAL (f)->class;
9195 if (class != StaticColor && class != StaticGray && class != TrueColor)
9197 XImage *ximg;
9199 BLOCK_INPUT;
9201 /* Try to get an XImage for img->pixmep. */
9202 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9203 0, 0, img->width, img->height, ~0, ZPixmap);
9204 if (ximg)
9206 int x, y;
9208 /* Initialize the color table. */
9209 init_color_table ();
9211 /* For each pixel of the image, look its color up in the
9212 color table. After having done so, the color table will
9213 contain an entry for each color used by the image. */
9214 for (y = 0; y < img->height; ++y)
9215 for (x = 0; x < img->width; ++x)
9217 unsigned long pixel = XGetPixel (ximg, x, y);
9218 lookup_pixel_color (f, pixel);
9221 /* Record colors in the image. Free color table and XImage. */
9222 img->colors = colors_in_color_table (&img->ncolors);
9223 free_color_table ();
9224 XDestroyImage (ximg);
9226 #if 0 /* This doesn't seem to be the case. If we free the colors
9227 here, we get a BadAccess later in x_clear_image when
9228 freeing the colors. */
9229 /* We have allocated colors once, but Ghostscript has also
9230 allocated colors on behalf of us. So, to get the
9231 reference counts right, free them once. */
9232 if (img->ncolors)
9233 x_free_colors (f, img->colors, img->ncolors);
9234 #endif
9236 else
9237 image_error ("Cannot get X image of `%s'; colors will not be freed",
9238 img->spec, Qnil);
9240 UNBLOCK_INPUT;
9243 /* Now that we have the pixmap, compute mask and transform the
9244 image if requested. */
9245 BLOCK_INPUT;
9246 postprocess_image (f, img);
9247 UNBLOCK_INPUT;
9252 /***********************************************************************
9253 Window properties
9254 ***********************************************************************/
9256 DEFUN ("x-change-window-property", Fx_change_window_property,
9257 Sx_change_window_property, 2, 3, 0,
9258 doc: /* Change window property PROP to VALUE on the X window of FRAME.
9259 PROP and VALUE must be strings. FRAME nil or omitted means use the
9260 selected frame. Value is VALUE. */)
9261 (prop, value, frame)
9262 Lisp_Object frame, prop, value;
9264 struct frame *f = check_x_frame (frame);
9265 Atom prop_atom;
9267 CHECK_STRING (prop);
9268 CHECK_STRING (value);
9270 BLOCK_INPUT;
9271 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9272 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9273 prop_atom, XA_STRING, 8, PropModeReplace,
9274 SDATA (value), SCHARS (value));
9276 /* Make sure the property is set when we return. */
9277 XFlush (FRAME_X_DISPLAY (f));
9278 UNBLOCK_INPUT;
9280 return value;
9284 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9285 Sx_delete_window_property, 1, 2, 0,
9286 doc: /* Remove window property PROP from X window of FRAME.
9287 FRAME nil or omitted means use the selected frame. Value is PROP. */)
9288 (prop, frame)
9289 Lisp_Object prop, frame;
9291 struct frame *f = check_x_frame (frame);
9292 Atom prop_atom;
9294 CHECK_STRING (prop);
9295 BLOCK_INPUT;
9296 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9297 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9299 /* Make sure the property is removed when we return. */
9300 XFlush (FRAME_X_DISPLAY (f));
9301 UNBLOCK_INPUT;
9303 return prop;
9307 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9308 1, 2, 0,
9309 doc: /* Value is the value of window property PROP on FRAME.
9310 If FRAME is nil or omitted, use the selected frame. Value is nil
9311 if FRAME hasn't a property with name PROP or if PROP has no string
9312 value. */)
9313 (prop, frame)
9314 Lisp_Object prop, frame;
9316 struct frame *f = check_x_frame (frame);
9317 Atom prop_atom;
9318 int rc;
9319 Lisp_Object prop_value = Qnil;
9320 char *tmp_data = NULL;
9321 Atom actual_type;
9322 int actual_format;
9323 unsigned long actual_size, bytes_remaining;
9325 CHECK_STRING (prop);
9326 BLOCK_INPUT;
9327 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
9328 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9329 prop_atom, 0, 0, False, XA_STRING,
9330 &actual_type, &actual_format, &actual_size,
9331 &bytes_remaining, (unsigned char **) &tmp_data);
9332 if (rc == Success)
9334 int size = bytes_remaining;
9336 XFree (tmp_data);
9337 tmp_data = NULL;
9339 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9340 prop_atom, 0, bytes_remaining,
9341 False, XA_STRING,
9342 &actual_type, &actual_format,
9343 &actual_size, &bytes_remaining,
9344 (unsigned char **) &tmp_data);
9345 if (rc == Success && tmp_data)
9346 prop_value = make_string (tmp_data, size);
9348 XFree (tmp_data);
9351 UNBLOCK_INPUT;
9352 return prop_value;
9357 /***********************************************************************
9358 Busy cursor
9359 ***********************************************************************/
9361 /* If non-null, an asynchronous timer that, when it expires, displays
9362 an hourglass cursor on all frames. */
9364 static struct atimer *hourglass_atimer;
9366 /* Non-zero means an hourglass cursor is currently shown. */
9368 static int hourglass_shown_p;
9370 /* Number of seconds to wait before displaying an hourglass cursor. */
9372 static Lisp_Object Vhourglass_delay;
9374 /* Default number of seconds to wait before displaying an hourglass
9375 cursor. */
9377 #define DEFAULT_HOURGLASS_DELAY 1
9379 /* Function prototypes. */
9381 static void show_hourglass P_ ((struct atimer *));
9382 static void hide_hourglass P_ ((void));
9385 /* Cancel a currently active hourglass timer, and start a new one. */
9387 void
9388 start_hourglass ()
9390 EMACS_TIME delay;
9391 int secs, usecs = 0;
9393 cancel_hourglass ();
9395 if (INTEGERP (Vhourglass_delay)
9396 && XINT (Vhourglass_delay) > 0)
9397 secs = XFASTINT (Vhourglass_delay);
9398 else if (FLOATP (Vhourglass_delay)
9399 && XFLOAT_DATA (Vhourglass_delay) > 0)
9401 Lisp_Object tem;
9402 tem = Ftruncate (Vhourglass_delay, Qnil);
9403 secs = XFASTINT (tem);
9404 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
9406 else
9407 secs = DEFAULT_HOURGLASS_DELAY;
9409 EMACS_SET_SECS_USECS (delay, secs, usecs);
9410 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
9411 show_hourglass, NULL);
9415 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
9416 shown. */
9418 void
9419 cancel_hourglass ()
9421 if (hourglass_atimer)
9423 cancel_atimer (hourglass_atimer);
9424 hourglass_atimer = NULL;
9427 if (hourglass_shown_p)
9428 hide_hourglass ();
9432 /* Timer function of hourglass_atimer. TIMER is equal to
9433 hourglass_atimer.
9435 Display an hourglass pointer on all frames by mapping the frames'
9436 hourglass_window. Set the hourglass_p flag in the frames'
9437 output_data.x structure to indicate that an hourglass cursor is
9438 shown on the frames. */
9440 static void
9441 show_hourglass (timer)
9442 struct atimer *timer;
9444 /* The timer implementation will cancel this timer automatically
9445 after this function has run. Set hourglass_atimer to null
9446 so that we know the timer doesn't have to be canceled. */
9447 hourglass_atimer = NULL;
9449 if (!hourglass_shown_p)
9451 Lisp_Object rest, frame;
9453 BLOCK_INPUT;
9455 FOR_EACH_FRAME (rest, frame)
9457 struct frame *f = XFRAME (frame);
9459 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
9461 Display *dpy = FRAME_X_DISPLAY (f);
9463 #ifdef USE_X_TOOLKIT
9464 if (f->output_data.x->widget)
9465 #else
9466 if (FRAME_OUTER_WINDOW (f))
9467 #endif
9469 f->output_data.x->hourglass_p = 1;
9471 if (!f->output_data.x->hourglass_window)
9473 unsigned long mask = CWCursor;
9474 XSetWindowAttributes attrs;
9476 attrs.cursor = f->output_data.x->hourglass_cursor;
9478 f->output_data.x->hourglass_window
9479 = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
9480 0, 0, 32000, 32000, 0, 0,
9481 InputOnly,
9482 CopyFromParent,
9483 mask, &attrs);
9486 XMapRaised (dpy, f->output_data.x->hourglass_window);
9487 XFlush (dpy);
9492 hourglass_shown_p = 1;
9493 UNBLOCK_INPUT;
9498 /* Hide the hourglass pointer on all frames, if it is currently
9499 shown. */
9501 static void
9502 hide_hourglass ()
9504 if (hourglass_shown_p)
9506 Lisp_Object rest, frame;
9508 BLOCK_INPUT;
9509 FOR_EACH_FRAME (rest, frame)
9511 struct frame *f = XFRAME (frame);
9513 if (FRAME_X_P (f)
9514 /* Watch out for newly created frames. */
9515 && f->output_data.x->hourglass_window)
9517 XUnmapWindow (FRAME_X_DISPLAY (f),
9518 f->output_data.x->hourglass_window);
9519 /* Sync here because XTread_socket looks at the
9520 hourglass_p flag that is reset to zero below. */
9521 XSync (FRAME_X_DISPLAY (f), False);
9522 f->output_data.x->hourglass_p = 0;
9526 hourglass_shown_p = 0;
9527 UNBLOCK_INPUT;
9533 /***********************************************************************
9534 Tool tips
9535 ***********************************************************************/
9537 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
9538 Lisp_Object, Lisp_Object));
9539 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
9540 Lisp_Object, int, int, int *, int *));
9542 /* The frame of a currently visible tooltip. */
9544 Lisp_Object tip_frame;
9546 /* If non-nil, a timer started that hides the last tooltip when it
9547 fires. */
9549 Lisp_Object tip_timer;
9550 Window tip_window;
9552 /* If non-nil, a vector of 3 elements containing the last args
9553 with which x-show-tip was called. See there. */
9555 Lisp_Object last_show_tip_args;
9557 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
9559 Lisp_Object Vx_max_tooltip_size;
9562 static Lisp_Object
9563 unwind_create_tip_frame (frame)
9564 Lisp_Object frame;
9566 Lisp_Object deleted;
9568 deleted = unwind_create_frame (frame);
9569 if (EQ (deleted, Qt))
9571 tip_window = None;
9572 tip_frame = Qnil;
9575 return deleted;
9579 /* Create a frame for a tooltip on the display described by DPYINFO.
9580 PARMS is a list of frame parameters. TEXT is the string to
9581 display in the tip frame. Value is the frame.
9583 Note that functions called here, esp. x_default_parameter can
9584 signal errors, for instance when a specified color name is
9585 undefined. We have to make sure that we're in a consistent state
9586 when this happens. */
9588 static Lisp_Object
9589 x_create_tip_frame (dpyinfo, parms, text)
9590 struct x_display_info *dpyinfo;
9591 Lisp_Object parms, text;
9593 struct frame *f;
9594 Lisp_Object frame, tem;
9595 Lisp_Object name;
9596 long window_prompting = 0;
9597 int width, height;
9598 int count = SPECPDL_INDEX ();
9599 struct gcpro gcpro1, gcpro2, gcpro3;
9600 struct kboard *kb;
9601 int face_change_count_before = face_change_count;
9602 Lisp_Object buffer;
9603 struct buffer *old_buffer;
9605 check_x ();
9607 /* Use this general default value to start with until we know if
9608 this frame has a specified name. */
9609 Vx_resource_name = Vinvocation_name;
9611 #ifdef MULTI_KBOARD
9612 kb = dpyinfo->kboard;
9613 #else
9614 kb = &the_only_kboard;
9615 #endif
9617 /* Get the name of the frame to use for resource lookup. */
9618 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
9619 if (!STRINGP (name)
9620 && !EQ (name, Qunbound)
9621 && !NILP (name))
9622 error ("Invalid frame name--not a string or nil");
9623 Vx_resource_name = name;
9625 frame = Qnil;
9626 GCPRO3 (parms, name, frame);
9627 f = make_frame (1);
9628 XSETFRAME (frame, f);
9630 buffer = Fget_buffer_create (build_string (" *tip*"));
9631 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
9632 old_buffer = current_buffer;
9633 set_buffer_internal_1 (XBUFFER (buffer));
9634 current_buffer->truncate_lines = Qnil;
9635 Ferase_buffer ();
9636 Finsert (1, &text);
9637 set_buffer_internal_1 (old_buffer);
9639 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9640 record_unwind_protect (unwind_create_tip_frame, frame);
9642 /* By setting the output method, we're essentially saying that
9643 the frame is live, as per FRAME_LIVE_P. If we get a signal
9644 from this point on, x_destroy_window might screw up reference
9645 counts etc. */
9646 f->output_method = output_x_window;
9647 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
9648 bzero (f->output_data.x, sizeof (struct x_output));
9649 f->output_data.x->icon_bitmap = -1;
9650 FRAME_FONTSET (f) = -1;
9651 f->output_data.x->scroll_bar_foreground_pixel = -1;
9652 f->output_data.x->scroll_bar_background_pixel = -1;
9653 #ifdef USE_TOOLKIT_SCROLL_BARS
9654 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
9655 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
9656 #endif /* USE_TOOLKIT_SCROLL_BARS */
9657 f->icon_name = Qnil;
9658 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
9659 #if GLYPH_DEBUG
9660 image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
9661 dpyinfo_refcount = dpyinfo->reference_count;
9662 #endif /* GLYPH_DEBUG */
9663 #ifdef MULTI_KBOARD
9664 FRAME_KBOARD (f) = kb;
9665 #endif
9666 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9667 f->output_data.x->explicit_parent = 0;
9669 /* These colors will be set anyway later, but it's important
9670 to get the color reference counts right, so initialize them! */
9672 Lisp_Object black;
9673 struct gcpro gcpro1;
9675 black = build_string ("black");
9676 GCPRO1 (black);
9677 f->output_data.x->foreground_pixel
9678 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9679 f->output_data.x->background_pixel
9680 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9681 f->output_data.x->cursor_pixel
9682 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9683 f->output_data.x->cursor_foreground_pixel
9684 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9685 f->output_data.x->border_pixel
9686 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9687 f->output_data.x->mouse_pixel
9688 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
9689 UNGCPRO;
9692 /* Set the name; the functions to which we pass f expect the name to
9693 be set. */
9694 if (EQ (name, Qunbound) || NILP (name))
9696 f->name = build_string (dpyinfo->x_id_name);
9697 f->explicit_name = 0;
9699 else
9701 f->name = name;
9702 f->explicit_name = 1;
9703 /* use the frame's title when getting resources for this frame. */
9704 specbind (Qx_resource_name, name);
9707 /* Extract the window parameters from the supplied values that are
9708 needed to determine window geometry. */
9710 Lisp_Object font;
9712 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
9714 BLOCK_INPUT;
9715 /* First, try whatever font the caller has specified. */
9716 if (STRINGP (font))
9718 tem = Fquery_fontset (font, Qnil);
9719 if (STRINGP (tem))
9720 font = x_new_fontset (f, SDATA (tem));
9721 else
9722 font = x_new_font (f, SDATA (font));
9725 /* Try out a font which we hope has bold and italic variations. */
9726 if (!STRINGP (font))
9727 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9728 if (!STRINGP (font))
9729 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9730 if (! STRINGP (font))
9731 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9732 if (! STRINGP (font))
9733 /* This was formerly the first thing tried, but it finds too many fonts
9734 and takes too long. */
9735 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9736 /* If those didn't work, look for something which will at least work. */
9737 if (! STRINGP (font))
9738 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9739 UNBLOCK_INPUT;
9740 if (! STRINGP (font))
9741 font = build_string ("fixed");
9743 x_default_parameter (f, parms, Qfont, font,
9744 "font", "Font", RES_TYPE_STRING);
9747 x_default_parameter (f, parms, Qborder_width, make_number (2),
9748 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9750 /* This defaults to 2 in order to match xterm. We recognize either
9751 internalBorderWidth or internalBorder (which is what xterm calls
9752 it). */
9753 if (NILP (Fassq (Qinternal_border_width, parms)))
9755 Lisp_Object value;
9757 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
9758 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9759 if (! EQ (value, Qunbound))
9760 parms = Fcons (Fcons (Qinternal_border_width, value),
9761 parms);
9764 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9765 "internalBorderWidth", "internalBorderWidth",
9766 RES_TYPE_NUMBER);
9768 /* Also do the stuff which must be set before the window exists. */
9769 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9770 "foreground", "Foreground", RES_TYPE_STRING);
9771 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9772 "background", "Background", RES_TYPE_STRING);
9773 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9774 "pointerColor", "Foreground", RES_TYPE_STRING);
9775 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9776 "cursorColor", "Foreground", RES_TYPE_STRING);
9777 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9778 "borderColor", "BorderColor", RES_TYPE_STRING);
9780 /* Init faces before x_default_parameter is called for scroll-bar
9781 parameters because that function calls x_set_scroll_bar_width,
9782 which calls change_frame_size, which calls Fset_window_buffer,
9783 which runs hooks, which call Fvertical_motion. At the end, we
9784 end up in init_iterator with a null face cache, which should not
9785 happen. */
9786 init_frame_faces (f);
9788 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
9790 window_prompting = x_figure_window_size (f, parms, 0);
9793 XSetWindowAttributes attrs;
9794 unsigned long mask;
9796 BLOCK_INPUT;
9797 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
9798 if (DoesSaveUnders (dpyinfo->screen))
9799 mask |= CWSaveUnder;
9801 /* Window managers look at the override-redirect flag to determine
9802 whether or net to give windows a decoration (Xlib spec, chapter
9803 3.2.8). */
9804 attrs.override_redirect = True;
9805 attrs.save_under = True;
9806 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9807 /* Arrange for getting MapNotify and UnmapNotify events. */
9808 attrs.event_mask = StructureNotifyMask;
9809 tip_window
9810 = FRAME_X_WINDOW (f)
9811 = XCreateWindow (FRAME_X_DISPLAY (f),
9812 FRAME_X_DISPLAY_INFO (f)->root_window,
9813 /* x, y, width, height */
9814 0, 0, 1, 1,
9815 /* Border. */
9817 CopyFromParent, InputOutput, CopyFromParent,
9818 mask, &attrs);
9819 UNBLOCK_INPUT;
9822 x_make_gc (f);
9824 x_default_parameter (f, parms, Qauto_raise, Qnil,
9825 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9826 x_default_parameter (f, parms, Qauto_lower, Qnil,
9827 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9828 x_default_parameter (f, parms, Qcursor_type, Qbox,
9829 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9831 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
9832 Change will not be effected unless different from the current
9833 FRAME_LINES (f). */
9834 width = FRAME_COLS (f);
9835 height = FRAME_LINES (f);
9836 SET_FRAME_COLS (f, 0);
9837 FRAME_LINES (f) = 0;
9838 change_frame_size (f, height, width, 1, 0, 0);
9840 /* Add `tooltip' frame parameter's default value. */
9841 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
9842 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
9843 Qnil));
9845 /* Set up faces after all frame parameters are known. This call
9846 also merges in face attributes specified for new frames.
9848 Frame parameters may be changed if .Xdefaults contains
9849 specifications for the default font. For example, if there is an
9850 `Emacs.default.attributeBackground: pink', the `background-color'
9851 attribute of the frame get's set, which let's the internal border
9852 of the tooltip frame appear in pink. Prevent this. */
9854 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
9856 /* Set tip_frame here, so that */
9857 tip_frame = frame;
9858 call1 (Qface_set_after_frame_default, frame);
9860 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
9861 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
9862 Qnil));
9865 f->no_split = 1;
9867 UNGCPRO;
9869 /* It is now ok to make the frame official even if we get an error
9870 below. And the frame needs to be on Vframe_list or making it
9871 visible won't work. */
9872 Vframe_list = Fcons (frame, Vframe_list);
9874 /* Now that the frame is official, it counts as a reference to
9875 its display. */
9876 FRAME_X_DISPLAY_INFO (f)->reference_count++;
9878 /* Setting attributes of faces of the tooltip frame from resources
9879 and similar will increment face_change_count, which leads to the
9880 clearing of all current matrices. Since this isn't necessary
9881 here, avoid it by resetting face_change_count to the value it
9882 had before we created the tip frame. */
9883 face_change_count = face_change_count_before;
9885 /* Discard the unwind_protect. */
9886 return unbind_to (count, frame);
9890 /* Compute where to display tip frame F. PARMS is the list of frame
9891 parameters for F. DX and DY are specified offsets from the current
9892 location of the mouse. WIDTH and HEIGHT are the width and height
9893 of the tooltip. Return coordinates relative to the root window of
9894 the display in *ROOT_X, and *ROOT_Y. */
9896 static void
9897 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
9898 struct frame *f;
9899 Lisp_Object parms, dx, dy;
9900 int width, height;
9901 int *root_x, *root_y;
9903 Lisp_Object left, top;
9904 int win_x, win_y;
9905 Window root, child;
9906 unsigned pmask;
9908 /* User-specified position? */
9909 left = Fcdr (Fassq (Qleft, parms));
9910 top = Fcdr (Fassq (Qtop, parms));
9912 /* Move the tooltip window where the mouse pointer is. Resize and
9913 show it. */
9914 if (!INTEGERP (left) || !INTEGERP (top))
9916 BLOCK_INPUT;
9917 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
9918 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
9919 UNBLOCK_INPUT;
9922 if (INTEGERP (top))
9923 *root_y = XINT (top);
9924 else if (*root_y + XINT (dy) - height < 0)
9925 *root_y -= XINT (dy);
9926 else
9928 *root_y -= height;
9929 *root_y += XINT (dy);
9932 if (INTEGERP (left))
9933 *root_x = XINT (left);
9934 else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
9935 /* It fits to the right of the pointer. */
9936 *root_x += XINT (dx);
9937 else if (width + XINT (dx) <= *root_x)
9938 /* It fits to the left of the pointer. */
9939 *root_x -= width + XINT (dx);
9940 else
9941 /* Put it left-justified on the screen--it ought to fit that way. */
9942 *root_x = 0;
9946 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
9947 doc: /* Show STRING in a "tooltip" window on frame FRAME.
9948 A tooltip window is a small X window displaying a string.
9950 FRAME nil or omitted means use the selected frame.
9952 PARMS is an optional list of frame parameters which can be used to
9953 change the tooltip's appearance.
9955 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
9956 means use the default timeout of 5 seconds.
9958 If the list of frame parameters PARAMS contains a `left' parameters,
9959 the tooltip is displayed at that x-position. Otherwise it is
9960 displayed at the mouse position, with offset DX added (default is 5 if
9961 DX isn't specified). Likewise for the y-position; if a `top' frame
9962 parameter is specified, it determines the y-position of the tooltip
9963 window, otherwise it is displayed at the mouse position, with offset
9964 DY added (default is -10).
9966 A tooltip's maximum size is specified by `x-max-tooltip-size'.
9967 Text larger than the specified size is clipped. */)
9968 (string, frame, parms, timeout, dx, dy)
9969 Lisp_Object string, frame, parms, timeout, dx, dy;
9971 struct frame *f;
9972 struct window *w;
9973 int root_x, root_y;
9974 struct buffer *old_buffer;
9975 struct text_pos pos;
9976 int i, width, height;
9977 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9978 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9979 int count = SPECPDL_INDEX ();
9981 specbind (Qinhibit_redisplay, Qt);
9983 GCPRO4 (string, parms, frame, timeout);
9985 CHECK_STRING (string);
9986 f = check_x_frame (frame);
9987 if (NILP (timeout))
9988 timeout = make_number (5);
9989 else
9990 CHECK_NATNUM (timeout);
9992 if (NILP (dx))
9993 dx = make_number (5);
9994 else
9995 CHECK_NUMBER (dx);
9997 if (NILP (dy))
9998 dy = make_number (-10);
9999 else
10000 CHECK_NUMBER (dy);
10002 if (NILP (last_show_tip_args))
10003 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
10005 if (!NILP (tip_frame))
10007 Lisp_Object last_string = AREF (last_show_tip_args, 0);
10008 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
10009 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
10011 if (EQ (frame, last_frame)
10012 && !NILP (Fequal (last_string, string))
10013 && !NILP (Fequal (last_parms, parms)))
10015 struct frame *f = XFRAME (tip_frame);
10017 /* Only DX and DY have changed. */
10018 if (!NILP (tip_timer))
10020 Lisp_Object timer = tip_timer;
10021 tip_timer = Qnil;
10022 call1 (Qcancel_timer, timer);
10025 BLOCK_INPUT;
10026 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
10027 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
10028 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10029 root_x, root_y);
10030 UNBLOCK_INPUT;
10031 goto start_timer;
10035 /* Hide a previous tip, if any. */
10036 Fx_hide_tip ();
10038 ASET (last_show_tip_args, 0, string);
10039 ASET (last_show_tip_args, 1, frame);
10040 ASET (last_show_tip_args, 2, parms);
10042 /* Add default values to frame parameters. */
10043 if (NILP (Fassq (Qname, parms)))
10044 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10045 if (NILP (Fassq (Qinternal_border_width, parms)))
10046 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10047 if (NILP (Fassq (Qborder_width, parms)))
10048 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10049 if (NILP (Fassq (Qborder_color, parms)))
10050 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10051 if (NILP (Fassq (Qbackground_color, parms)))
10052 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10053 parms);
10055 /* Create a frame for the tooltip, and record it in the global
10056 variable tip_frame. */
10057 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
10058 f = XFRAME (frame);
10060 /* Set up the frame's root window. */
10061 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10062 w->left_col = w->top_line = make_number (0);
10064 if (CONSP (Vx_max_tooltip_size)
10065 && INTEGERP (XCAR (Vx_max_tooltip_size))
10066 && XINT (XCAR (Vx_max_tooltip_size)) > 0
10067 && INTEGERP (XCDR (Vx_max_tooltip_size))
10068 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
10070 w->total_cols = XCAR (Vx_max_tooltip_size);
10071 w->total_lines = XCDR (Vx_max_tooltip_size);
10073 else
10075 w->total_cols = make_number (80);
10076 w->total_lines = make_number (40);
10079 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
10080 adjust_glyphs (f);
10081 w->pseudo_window_p = 1;
10083 /* Display the tooltip text in a temporary buffer. */
10084 old_buffer = current_buffer;
10085 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
10086 current_buffer->truncate_lines = Qnil;
10087 clear_glyph_matrix (w->desired_matrix);
10088 clear_glyph_matrix (w->current_matrix);
10089 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10090 try_window (FRAME_ROOT_WINDOW (f), pos);
10092 /* Compute width and height of the tooltip. */
10093 width = height = 0;
10094 for (i = 0; i < w->desired_matrix->nrows; ++i)
10096 struct glyph_row *row = &w->desired_matrix->rows[i];
10097 struct glyph *last;
10098 int row_width;
10100 /* Stop at the first empty row at the end. */
10101 if (!row->enabled_p || !row->displays_text_p)
10102 break;
10104 /* Let the row go over the full width of the frame. */
10105 row->full_width_p = 1;
10107 /* There's a glyph at the end of rows that is used to place
10108 the cursor there. Don't include the width of this glyph. */
10109 if (row->used[TEXT_AREA])
10111 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10112 row_width = row->pixel_width - last->pixel_width;
10114 else
10115 row_width = row->pixel_width;
10117 height += row->height;
10118 width = max (width, row_width);
10121 /* Add the frame's internal border to the width and height the X
10122 window should have. */
10123 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10124 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10126 /* Move the tooltip window where the mouse pointer is. Resize and
10127 show it. */
10128 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
10130 BLOCK_INPUT;
10131 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10132 root_x, root_y, width, height);
10133 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10134 UNBLOCK_INPUT;
10136 /* Draw into the window. */
10137 w->must_be_updated_p = 1;
10138 update_single_window (w, 1);
10140 /* Restore original current buffer. */
10141 set_buffer_internal_1 (old_buffer);
10142 windows_or_buffers_changed = old_windows_or_buffers_changed;
10144 start_timer:
10145 /* Let the tip disappear after timeout seconds. */
10146 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10147 intern ("x-hide-tip"));
10149 UNGCPRO;
10150 return unbind_to (count, Qnil);
10154 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10155 doc: /* Hide the current tooltip window, if there is any.
10156 Value is t if tooltip was open, nil otherwise. */)
10159 int count;
10160 Lisp_Object deleted, frame, timer;
10161 struct gcpro gcpro1, gcpro2;
10163 /* Return quickly if nothing to do. */
10164 if (NILP (tip_timer) && NILP (tip_frame))
10165 return Qnil;
10167 frame = tip_frame;
10168 timer = tip_timer;
10169 GCPRO2 (frame, timer);
10170 tip_frame = tip_timer = deleted = Qnil;
10172 count = SPECPDL_INDEX ();
10173 specbind (Qinhibit_redisplay, Qt);
10174 specbind (Qinhibit_quit, Qt);
10176 if (!NILP (timer))
10177 call1 (Qcancel_timer, timer);
10179 if (FRAMEP (frame))
10181 Fdelete_frame (frame, Qnil);
10182 deleted = Qt;
10184 #ifdef USE_LUCID
10185 /* Bloodcurdling hack alert: The Lucid menu bar widget's
10186 redisplay procedure is not called when a tip frame over menu
10187 items is unmapped. Redisplay the menu manually... */
10189 struct frame *f = SELECTED_FRAME ();
10190 Widget w = f->output_data.x->menubar_widget;
10191 extern void xlwmenu_redisplay P_ ((Widget));
10193 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
10194 && w != NULL)
10196 BLOCK_INPUT;
10197 xlwmenu_redisplay (w);
10198 UNBLOCK_INPUT;
10201 #endif /* USE_LUCID */
10204 UNGCPRO;
10205 return unbind_to (count, deleted);
10210 /***********************************************************************
10211 File selection dialog
10212 ***********************************************************************/
10214 #ifdef USE_MOTIF
10216 /* Callback for "OK" and "Cancel" on file selection dialog. */
10218 static void
10219 file_dialog_cb (widget, client_data, call_data)
10220 Widget widget;
10221 XtPointer call_data, client_data;
10223 int *result = (int *) client_data;
10224 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10225 *result = cb->reason;
10229 /* Callback for unmapping a file selection dialog. This is used to
10230 capture the case where a dialog is closed via a window manager's
10231 closer button, for example. Using a XmNdestroyCallback didn't work
10232 in this case. */
10234 static void
10235 file_dialog_unmap_cb (widget, client_data, call_data)
10236 Widget widget;
10237 XtPointer call_data, client_data;
10239 int *result = (int *) client_data;
10240 *result = XmCR_CANCEL;
10244 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10245 doc: /* Read file name, prompting with PROMPT in directory DIR.
10246 Use a file selection dialog.
10247 Select DEFAULT-FILENAME in the dialog's file selection box, if
10248 specified. Don't let the user enter a file name in the file
10249 selection dialog's entry field, if MUSTMATCH is non-nil. */)
10250 (prompt, dir, default_filename, mustmatch)
10251 Lisp_Object prompt, dir, default_filename, mustmatch;
10253 int result;
10254 struct frame *f = SELECTED_FRAME ();
10255 Lisp_Object file = Qnil;
10256 Widget dialog, text, list, help;
10257 Arg al[10];
10258 int ac = 0;
10259 extern XtAppContext Xt_app_con;
10260 XmString dir_xmstring, pattern_xmstring;
10261 int count = SPECPDL_INDEX ();
10262 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10264 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10265 CHECK_STRING (prompt);
10266 CHECK_STRING (dir);
10268 /* Prevent redisplay. */
10269 specbind (Qinhibit_redisplay, Qt);
10271 BLOCK_INPUT;
10273 /* Create the dialog with PROMPT as title, using DIR as initial
10274 directory and using "*" as pattern. */
10275 dir = Fexpand_file_name (dir, Qnil);
10276 dir_xmstring = XmStringCreateLocalized (SDATA (dir));
10277 pattern_xmstring = XmStringCreateLocalized ("*");
10279 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
10280 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10281 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10282 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10283 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10284 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10285 "fsb", al, ac);
10286 XmStringFree (dir_xmstring);
10287 XmStringFree (pattern_xmstring);
10289 /* Add callbacks for OK and Cancel. */
10290 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10291 (XtPointer) &result);
10292 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10293 (XtPointer) &result);
10294 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
10295 (XtPointer) &result);
10297 /* Disable the help button since we can't display help. */
10298 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10299 XtSetSensitive (help, False);
10301 /* Mark OK button as default. */
10302 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10303 XmNshowAsDefault, True, NULL);
10305 /* If MUSTMATCH is non-nil, disable the file entry field of the
10306 dialog, so that the user must select a file from the files list
10307 box. We can't remove it because we wouldn't have a way to get at
10308 the result file name, then. */
10309 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10310 if (!NILP (mustmatch))
10312 Widget label;
10313 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10314 XtSetSensitive (text, False);
10315 XtSetSensitive (label, False);
10318 /* Manage the dialog, so that list boxes get filled. */
10319 XtManageChild (dialog);
10321 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10322 must include the path for this to work. */
10323 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10324 if (STRINGP (default_filename))
10326 XmString default_xmstring;
10327 int item_pos;
10329 default_xmstring
10330 = XmStringCreateLocalized (SDATA (default_filename));
10332 if (!XmListItemExists (list, default_xmstring))
10334 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10335 XmListAddItem (list, default_xmstring, 0);
10336 item_pos = 0;
10338 else
10339 item_pos = XmListItemPos (list, default_xmstring);
10340 XmStringFree (default_xmstring);
10342 /* Select the item and scroll it into view. */
10343 XmListSelectPos (list, item_pos, True);
10344 XmListSetPos (list, item_pos);
10347 /* Process events until the user presses Cancel or OK. */
10348 result = 0;
10349 while (result == 0)
10351 XEvent event;
10352 XtAppNextEvent (Xt_app_con, &event);
10353 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) );
10356 /* Get the result. */
10357 if (result == XmCR_OK)
10359 XmString text;
10360 String data;
10362 XtVaGetValues (dialog, XmNtextString, &text, NULL);
10363 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10364 XmStringFree (text);
10365 file = build_string (data);
10366 XtFree (data);
10368 else
10369 file = Qnil;
10371 /* Clean up. */
10372 XtUnmanageChild (dialog);
10373 XtDestroyWidget (dialog);
10374 UNBLOCK_INPUT;
10375 UNGCPRO;
10377 /* Make "Cancel" equivalent to C-g. */
10378 if (NILP (file))
10379 Fsignal (Qquit, Qnil);
10381 return unbind_to (count, file);
10384 #endif /* USE_MOTIF */
10386 #ifdef USE_GTK
10388 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10389 "Read file name, prompting with PROMPT in directory DIR.\n\
10390 Use a file selection dialog.\n\
10391 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10392 specified. Don't let the user enter a file name in the file\n\
10393 selection dialog's entry field, if MUSTMATCH is non-nil.")
10394 (prompt, dir, default_filename, mustmatch)
10395 Lisp_Object prompt, dir, default_filename, mustmatch;
10397 FRAME_PTR f = SELECTED_FRAME ();
10398 char *fn;
10399 Lisp_Object file = Qnil;
10400 int count = specpdl_ptr - specpdl;
10401 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10402 char *cdef_file;
10403 char *cprompt;
10405 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10406 CHECK_STRING (prompt);
10407 CHECK_STRING (dir);
10409 /* Prevent redisplay. */
10410 specbind (Qinhibit_redisplay, Qt);
10412 BLOCK_INPUT;
10414 if (STRINGP (default_filename))
10415 cdef_file = SDATA (default_filename);
10416 else
10417 cdef_file = SDATA (dir);
10419 fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
10421 if (fn)
10423 file = build_string (fn);
10424 xfree (fn);
10427 UNBLOCK_INPUT;
10428 UNGCPRO;
10430 /* Make "Cancel" equivalent to C-g. */
10431 if (NILP (file))
10432 Fsignal (Qquit, Qnil);
10434 return unbind_to (count, file);
10437 #endif /* USE_GTK */
10440 /***********************************************************************
10441 Keyboard
10442 ***********************************************************************/
10444 #ifdef HAVE_XKBGETKEYBOARD
10445 #include <X11/XKBlib.h>
10446 #include <X11/keysym.h>
10447 #endif
10449 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
10450 Sx_backspace_delete_keys_p, 0, 1, 0,
10451 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
10452 FRAME nil means use the selected frame.
10453 Value is t if we know that both keys are present, and are mapped to the
10454 usual X keysyms. */)
10455 (frame)
10456 Lisp_Object frame;
10458 #ifdef HAVE_XKBGETKEYBOARD
10459 XkbDescPtr kb;
10460 struct frame *f = check_x_frame (frame);
10461 Display *dpy = FRAME_X_DISPLAY (f);
10462 Lisp_Object have_keys;
10463 int major, minor, op, event, error;
10465 BLOCK_INPUT;
10467 /* Check library version in case we're dynamically linked. */
10468 major = XkbMajorVersion;
10469 minor = XkbMinorVersion;
10470 if (!XkbLibraryVersion (&major, &minor))
10472 UNBLOCK_INPUT;
10473 return Qnil;
10476 /* Check that the server supports XKB. */
10477 major = XkbMajorVersion;
10478 minor = XkbMinorVersion;
10479 if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
10481 UNBLOCK_INPUT;
10482 return Qnil;
10485 have_keys = Qnil;
10486 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
10487 if (kb)
10489 int delete_keycode = 0, backspace_keycode = 0, i;
10491 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
10493 for (i = kb->min_key_code;
10494 (i < kb->max_key_code
10495 && (delete_keycode == 0 || backspace_keycode == 0));
10496 ++i)
10498 /* The XKB symbolic key names can be seen most easily in
10499 the PS file generated by `xkbprint -label name
10500 $DISPLAY'. */
10501 if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
10502 delete_keycode = i;
10503 else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
10504 backspace_keycode = i;
10507 XkbFreeNames (kb, 0, True);
10510 XkbFreeClientMap (kb, 0, True);
10512 if (delete_keycode
10513 && backspace_keycode
10514 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
10515 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
10516 have_keys = Qt;
10518 UNBLOCK_INPUT;
10519 return have_keys;
10520 #else /* not HAVE_XKBGETKEYBOARD */
10521 return Qnil;
10522 #endif /* not HAVE_XKBGETKEYBOARD */
10527 /***********************************************************************
10528 Initialization
10529 ***********************************************************************/
10531 /* Keep this list in the same order as frame_parms in frame.c.
10532 Use 0 for unsupported frame parameters. */
10534 frame_parm_handler x_frame_parm_handlers[] =
10536 x_set_autoraise,
10537 x_set_autolower,
10538 x_set_background_color,
10539 x_set_border_color,
10540 x_set_border_width,
10541 x_set_cursor_color,
10542 x_set_cursor_type,
10543 x_set_font,
10544 x_set_foreground_color,
10545 x_set_icon_name,
10546 x_set_icon_type,
10547 x_set_internal_border_width,
10548 x_set_menu_bar_lines,
10549 x_set_mouse_color,
10550 x_explicitly_set_name,
10551 x_set_scroll_bar_width,
10552 x_set_title,
10553 x_set_unsplittable,
10554 x_set_vertical_scroll_bars,
10555 x_set_visibility,
10556 x_set_tool_bar_lines,
10557 x_set_scroll_bar_foreground,
10558 x_set_scroll_bar_background,
10559 x_set_screen_gamma,
10560 x_set_line_spacing,
10561 x_set_fringe_width,
10562 x_set_fringe_width,
10563 x_set_wait_for_wm,
10564 x_set_fullscreen,
10567 void
10568 syms_of_xfns ()
10570 /* This is zero if not using X windows. */
10571 x_in_use = 0;
10573 /* The section below is built by the lisp expression at the top of the file,
10574 just above where these variables are declared. */
10575 /*&&& init symbols here &&&*/
10576 Qnone = intern ("none");
10577 staticpro (&Qnone);
10578 Qsuppress_icon = intern ("suppress-icon");
10579 staticpro (&Qsuppress_icon);
10580 Qundefined_color = intern ("undefined-color");
10581 staticpro (&Qundefined_color);
10582 Qcenter = intern ("center");
10583 staticpro (&Qcenter);
10584 Qcompound_text = intern ("compound-text");
10585 staticpro (&Qcompound_text);
10586 Qcancel_timer = intern ("cancel-timer");
10587 staticpro (&Qcancel_timer);
10588 /* This is the end of symbol initialization. */
10590 /* Text property `display' should be nonsticky by default. */
10591 Vtext_property_default_nonsticky
10592 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10595 Qlaplace = intern ("laplace");
10596 staticpro (&Qlaplace);
10597 Qemboss = intern ("emboss");
10598 staticpro (&Qemboss);
10599 Qedge_detection = intern ("edge-detection");
10600 staticpro (&Qedge_detection);
10601 Qheuristic = intern ("heuristic");
10602 staticpro (&Qheuristic);
10603 QCmatrix = intern (":matrix");
10604 staticpro (&QCmatrix);
10605 QCcolor_adjustment = intern (":color-adjustment");
10606 staticpro (&QCcolor_adjustment);
10607 QCmask = intern (":mask");
10608 staticpro (&QCmask);
10610 Fput (Qundefined_color, Qerror_conditions,
10611 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10612 Fput (Qundefined_color, Qerror_message,
10613 build_string ("Undefined color"));
10615 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10616 doc: /* Non-nil means always draw a cross over disabled images.
10617 Disabled images are those having an `:conversion disabled' property.
10618 A cross is always drawn on black & white displays. */);
10619 cross_disabled_images = 0;
10621 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10622 doc: /* List of directories to search for window system bitmap files. */);
10623 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10625 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10626 doc: /* The shape of the pointer when over text.
10627 Changing the value does not affect existing frames
10628 unless you set the mouse color. */);
10629 Vx_pointer_shape = Qnil;
10631 #if 0 /* This doesn't really do anything. */
10632 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
10633 doc: /* The shape of the pointer when not over text.
10634 This variable takes effect when you create a new frame
10635 or when you set the mouse color. */);
10636 #endif
10637 Vx_nontext_pointer_shape = Qnil;
10639 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
10640 doc: /* The shape of the pointer when Emacs is busy.
10641 This variable takes effect when you create a new frame
10642 or when you set the mouse color. */);
10643 Vx_hourglass_pointer_shape = Qnil;
10645 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
10646 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10647 display_hourglass_p = 1;
10649 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
10650 doc: /* *Seconds to wait before displaying an hourglass pointer.
10651 Value must be an integer or float. */);
10652 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
10654 #if 0 /* This doesn't really do anything. */
10655 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
10656 doc: /* The shape of the pointer when over the mode line.
10657 This variable takes effect when you create a new frame
10658 or when you set the mouse color. */);
10659 #endif
10660 Vx_mode_pointer_shape = Qnil;
10662 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10663 &Vx_sensitive_text_pointer_shape,
10664 doc: /* The shape of the pointer when over mouse-sensitive text.
10665 This variable takes effect when you create a new frame
10666 or when you set the mouse color. */);
10667 Vx_sensitive_text_pointer_shape = Qnil;
10669 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
10670 &Vx_window_horizontal_drag_shape,
10671 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
10672 This variable takes effect when you create a new frame
10673 or when you set the mouse color. */);
10674 Vx_window_horizontal_drag_shape = Qnil;
10676 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10677 doc: /* A string indicating the foreground color of the cursor box. */);
10678 Vx_cursor_fore_pixel = Qnil;
10680 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
10681 doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
10682 Text larger than this is clipped. */);
10683 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
10685 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10686 doc: /* Non-nil if no X window manager is in use.
10687 Emacs doesn't try to figure this out; this is always nil
10688 unless you set it to something else. */);
10689 /* We don't have any way to find this out, so set it to nil
10690 and maybe the user would like to set it to t. */
10691 Vx_no_window_manager = Qnil;
10693 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10694 &Vx_pixel_size_width_font_regexp,
10695 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10697 Since Emacs gets width of a font matching with this regexp from
10698 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10699 such a font. This is especially effective for such large fonts as
10700 Chinese, Japanese, and Korean. */);
10701 Vx_pixel_size_width_font_regexp = Qnil;
10703 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10704 doc: /* Time after which cached images are removed from the cache.
10705 When an image has not been displayed this many seconds, remove it
10706 from the image cache. Value must be an integer or nil with nil
10707 meaning don't clear the cache. */);
10708 Vimage_cache_eviction_delay = make_number (30 * 60);
10710 #ifdef USE_X_TOOLKIT
10711 Fprovide (intern ("x-toolkit"), Qnil);
10712 #ifdef USE_MOTIF
10713 Fprovide (intern ("motif"), Qnil);
10715 DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
10716 doc: /* Version info for LessTif/Motif. */);
10717 Vmotif_version_string = build_string (XmVERSION_STRING);
10718 #endif /* USE_MOTIF */
10719 #endif /* USE_X_TOOLKIT */
10721 /* X window properties. */
10722 defsubr (&Sx_change_window_property);
10723 defsubr (&Sx_delete_window_property);
10724 defsubr (&Sx_window_property);
10726 defsubr (&Sxw_display_color_p);
10727 defsubr (&Sx_display_grayscale_p);
10728 defsubr (&Sxw_color_defined_p);
10729 defsubr (&Sxw_color_values);
10730 defsubr (&Sx_server_max_request_size);
10731 defsubr (&Sx_server_vendor);
10732 defsubr (&Sx_server_version);
10733 defsubr (&Sx_display_pixel_width);
10734 defsubr (&Sx_display_pixel_height);
10735 defsubr (&Sx_display_mm_width);
10736 defsubr (&Sx_display_mm_height);
10737 defsubr (&Sx_display_screens);
10738 defsubr (&Sx_display_planes);
10739 defsubr (&Sx_display_color_cells);
10740 defsubr (&Sx_display_visual_class);
10741 defsubr (&Sx_display_backing_store);
10742 defsubr (&Sx_display_save_under);
10743 defsubr (&Sx_create_frame);
10744 defsubr (&Sx_open_connection);
10745 defsubr (&Sx_close_connection);
10746 defsubr (&Sx_display_list);
10747 defsubr (&Sx_synchronize);
10748 defsubr (&Sx_focus_frame);
10749 defsubr (&Sx_backspace_delete_keys_p);
10751 /* Setting callback functions for fontset handler. */
10752 get_font_info_func = x_get_font_info;
10754 #if 0 /* This function pointer doesn't seem to be used anywhere.
10755 And the pointer assigned has the wrong type, anyway. */
10756 list_fonts_func = x_list_fonts;
10757 #endif
10759 load_font_func = x_load_font;
10760 find_ccl_program_func = x_find_ccl_program;
10761 query_font_func = x_query_font;
10762 set_frame_fontset_func = x_set_font;
10763 check_window_system_func = check_x;
10765 /* Images. */
10766 Qxbm = intern ("xbm");
10767 staticpro (&Qxbm);
10768 QCconversion = intern (":conversion");
10769 staticpro (&QCconversion);
10770 QCheuristic_mask = intern (":heuristic-mask");
10771 staticpro (&QCheuristic_mask);
10772 QCcolor_symbols = intern (":color-symbols");
10773 staticpro (&QCcolor_symbols);
10774 QCascent = intern (":ascent");
10775 staticpro (&QCascent);
10776 QCmargin = intern (":margin");
10777 staticpro (&QCmargin);
10778 QCrelief = intern (":relief");
10779 staticpro (&QCrelief);
10780 Qpostscript = intern ("postscript");
10781 staticpro (&Qpostscript);
10782 QCloader = intern (":loader");
10783 staticpro (&QCloader);
10784 QCbounding_box = intern (":bounding-box");
10785 staticpro (&QCbounding_box);
10786 QCpt_width = intern (":pt-width");
10787 staticpro (&QCpt_width);
10788 QCpt_height = intern (":pt-height");
10789 staticpro (&QCpt_height);
10790 QCindex = intern (":index");
10791 staticpro (&QCindex);
10792 Qpbm = intern ("pbm");
10793 staticpro (&Qpbm);
10795 #if HAVE_XPM
10796 Qxpm = intern ("xpm");
10797 staticpro (&Qxpm);
10798 #endif
10800 #if HAVE_JPEG
10801 Qjpeg = intern ("jpeg");
10802 staticpro (&Qjpeg);
10803 #endif
10805 #if HAVE_TIFF
10806 Qtiff = intern ("tiff");
10807 staticpro (&Qtiff);
10808 #endif
10810 #if HAVE_GIF
10811 Qgif = intern ("gif");
10812 staticpro (&Qgif);
10813 #endif
10815 #if HAVE_PNG
10816 Qpng = intern ("png");
10817 staticpro (&Qpng);
10818 #endif
10820 defsubr (&Sclear_image_cache);
10821 defsubr (&Simage_size);
10822 defsubr (&Simage_mask_p);
10824 hourglass_atimer = NULL;
10825 hourglass_shown_p = 0;
10827 defsubr (&Sx_show_tip);
10828 defsubr (&Sx_hide_tip);
10829 tip_timer = Qnil;
10830 staticpro (&tip_timer);
10831 tip_frame = Qnil;
10832 staticpro (&tip_frame);
10834 last_show_tip_args = Qnil;
10835 staticpro (&last_show_tip_args);
10837 #ifdef USE_MOTIF
10838 defsubr (&Sx_file_dialog);
10839 #endif
10843 void
10844 init_xfns ()
10846 image_types = NULL;
10847 Vimage_types = Qnil;
10849 define_image_type (&xbm_type);
10850 define_image_type (&gs_type);
10851 define_image_type (&pbm_type);
10853 #if HAVE_XPM
10854 define_image_type (&xpm_type);
10855 #endif
10857 #if HAVE_JPEG
10858 define_image_type (&jpeg_type);
10859 #endif
10861 #if HAVE_TIFF
10862 define_image_type (&tiff_type);
10863 #endif
10865 #if HAVE_GIF
10866 define_image_type (&gif_type);
10867 #endif
10869 #if HAVE_PNG
10870 define_image_type (&png_type);
10871 #endif
10874 #endif /* HAVE_X_WINDOWS */