1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
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)
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. */
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
36 #include "intervals.h"
37 #include "dispextern.h"
39 #include "blockinput.h"
45 #include "termhooks.h"
51 #include <sys/types.h>
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
58 #include <X11/bitmaps/gray>
61 #include "[.bitmaps]gray.xbm"
65 #include <X11/Shell.h>
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
82 #include "../lwlib/lwlib.h"
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick
;
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct
*xlwmenu_default_font
;
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #endif /* USE_X_TOOLKIT */
112 #define min(a,b) ((a) < (b) ? (a) : (b))
113 #define max(a,b) ((a) > (b) ? (a) : (b))
116 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
118 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
121 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
122 it, and including `bitmaps/gray' more than once is a problem when
123 config.h defines `static' as an empty replacement string. */
125 int gray_bitmap_width
= gray_width
;
126 int gray_bitmap_height
= gray_height
;
127 unsigned char *gray_bitmap_bits
= gray_bits
;
129 /* The name we're using in resource queries. Most often "emacs". */
131 Lisp_Object Vx_resource_name
;
133 /* The application class we're using in resource queries.
136 Lisp_Object Vx_resource_class
;
138 /* Non-zero means we're allowed to display a busy cursor. */
140 int display_busy_cursor_p
;
142 /* The background and shape of the mouse pointer, and shape when not
143 over text or in the modeline. */
145 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
146 Lisp_Object Vx_busy_pointer_shape
;
148 /* The shape when over mouse-sensitive text. */
150 Lisp_Object Vx_sensitive_text_pointer_shape
;
152 /* Color of chars displayed in cursor box. */
154 Lisp_Object Vx_cursor_fore_pixel
;
156 /* Nonzero if using X. */
160 /* Non nil if no window manager is in use. */
162 Lisp_Object Vx_no_window_manager
;
164 /* Search path for bitmap files. */
166 Lisp_Object Vx_bitmap_file_path
;
168 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
170 Lisp_Object Vx_pixel_size_width_font_regexp
;
172 /* Evaluate this expression to rebuild the section of syms_of_xfns
173 that initializes and staticpros the symbols declared below. Note
174 that Emacs 18 has a bug that keeps C-x C-e from being able to
175 evaluate this expression.
178 ;; Accumulate a list of the symbols we want to initialize from the
179 ;; declarations at the top of the file.
180 (goto-char (point-min))
181 (search-forward "/\*&&& symbols declared here &&&*\/\n")
183 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
185 (cons (buffer-substring (match-beginning 1) (match-end 1))
188 (setq symbol-list (nreverse symbol-list))
189 ;; Delete the section of syms_of_... where we initialize the symbols.
190 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
191 (let ((start (point)))
192 (while (looking-at "^ Q")
194 (kill-region start (point)))
195 ;; Write a new symbol initialization section.
197 (insert (format " %s = intern (\"" (car symbol-list)))
198 (let ((start (point)))
199 (insert (substring (car symbol-list) 1))
200 (subst-char-in-region start (point) ?_ ?-))
201 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
202 (setq symbol-list (cdr symbol-list)))))
206 /*&&& symbols declared here &&&*/
207 Lisp_Object Qauto_raise
;
208 Lisp_Object Qauto_lower
;
210 Lisp_Object Qborder_color
;
211 Lisp_Object Qborder_width
;
213 Lisp_Object Qcursor_color
;
214 Lisp_Object Qcursor_type
;
215 Lisp_Object Qgeometry
;
216 Lisp_Object Qicon_left
;
217 Lisp_Object Qicon_top
;
218 Lisp_Object Qicon_type
;
219 Lisp_Object Qicon_name
;
220 Lisp_Object Qinternal_border_width
;
223 Lisp_Object Qmouse_color
;
225 Lisp_Object Qouter_window_id
;
226 Lisp_Object Qparent_id
;
227 Lisp_Object Qscroll_bar_width
;
228 Lisp_Object Qsuppress_icon
;
229 extern Lisp_Object Qtop
;
230 Lisp_Object Qundefined_color
;
231 Lisp_Object Qvertical_scroll_bars
;
232 Lisp_Object Qvisibility
;
233 Lisp_Object Qwindow_id
;
234 Lisp_Object Qx_frame_parameter
;
235 Lisp_Object Qx_resource_name
;
236 Lisp_Object Quser_position
;
237 Lisp_Object Quser_size
;
238 extern Lisp_Object Qdisplay
;
239 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
240 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
241 Lisp_Object Qcompound_text
;
243 /* The below are defined in frame.c. */
245 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
246 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
247 extern Lisp_Object Qtool_bar_lines
;
249 extern Lisp_Object Vwindow_system_version
;
251 Lisp_Object Qface_set_after_frame_default
;
254 /* Error if we are not connected to X. */
260 error ("X windows are not in use or not initialized");
263 /* Nonzero if we can use mouse menus.
264 You should not call this unless HAVE_MENUS is defined. */
272 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
273 and checking validity for X. */
276 check_x_frame (frame
)
282 frame
= selected_frame
;
283 CHECK_LIVE_FRAME (frame
, 0);
286 error ("Non-X frame used");
290 /* Let the user specify an X display with a frame.
291 nil stands for the selected frame--or, if that is not an X frame,
292 the first X display on the list. */
294 static struct x_display_info
*
295 check_x_display_info (frame
)
298 struct x_display_info
*dpyinfo
= NULL
;
302 struct frame
*sf
= XFRAME (selected_frame
);
304 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
305 dpyinfo
= FRAME_X_DISPLAY_INFO (sf
);
306 else if (x_display_list
!= 0)
307 dpyinfo
= x_display_list
;
309 error ("X windows are not in use or not initialized");
311 else if (STRINGP (frame
))
312 dpyinfo
= x_display_info_for_name (frame
);
317 CHECK_LIVE_FRAME (frame
, 0);
320 error ("Non-X frame used");
321 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
328 /* Return the Emacs frame-object corresponding to an X window.
329 It could be the frame's main window or an icon window. */
331 /* This function can be called during GC, so use GC_xxx type test macros. */
334 x_window_to_frame (dpyinfo
, wdesc
)
335 struct x_display_info
*dpyinfo
;
338 Lisp_Object tail
, frame
;
341 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
344 if (!GC_FRAMEP (frame
))
347 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
349 if (f
->output_data
.x
->busy_window
== wdesc
)
352 if ((f
->output_data
.x
->edit_widget
353 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
354 /* A tooltip frame? */
355 || (!f
->output_data
.x
->edit_widget
356 && FRAME_X_WINDOW (f
) == wdesc
)
357 || f
->output_data
.x
->icon_desc
== wdesc
)
359 #else /* not USE_X_TOOLKIT */
360 if (FRAME_X_WINDOW (f
) == wdesc
361 || f
->output_data
.x
->icon_desc
== wdesc
)
363 #endif /* not USE_X_TOOLKIT */
369 /* Like x_window_to_frame but also compares the window with the widget's
373 x_any_window_to_frame (dpyinfo
, wdesc
)
374 struct x_display_info
*dpyinfo
;
377 Lisp_Object tail
, frame
;
378 struct frame
*f
, *found
;
382 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
385 if (!GC_FRAMEP (frame
))
389 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
391 /* This frame matches if the window is any of its widgets. */
392 x
= f
->output_data
.x
;
393 if (x
->busy_window
== wdesc
)
397 if (wdesc
== XtWindow (x
->widget
)
398 || wdesc
== XtWindow (x
->column_widget
)
399 || wdesc
== XtWindow (x
->edit_widget
))
401 /* Match if the window is this frame's menubar. */
402 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
405 else if (FRAME_X_WINDOW (f
) == wdesc
)
406 /* A tooltip frame. */
414 /* Likewise, but exclude the menu bar widget. */
417 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
418 struct x_display_info
*dpyinfo
;
421 Lisp_Object tail
, frame
;
425 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
428 if (!GC_FRAMEP (frame
))
431 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
433 x
= f
->output_data
.x
;
434 /* This frame matches if the window is any of its widgets. */
435 if (x
->busy_window
== wdesc
)
439 if (wdesc
== XtWindow (x
->widget
)
440 || wdesc
== XtWindow (x
->column_widget
)
441 || wdesc
== XtWindow (x
->edit_widget
))
444 else if (FRAME_X_WINDOW (f
) == wdesc
)
445 /* A tooltip frame. */
451 /* Likewise, but consider only the menu bar widget. */
454 x_menubar_window_to_frame (dpyinfo
, wdesc
)
455 struct x_display_info
*dpyinfo
;
458 Lisp_Object tail
, frame
;
462 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
465 if (!GC_FRAMEP (frame
))
468 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
470 x
= f
->output_data
.x
;
471 /* Match if the window is this frame's menubar. */
472 if (x
->menubar_widget
473 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
479 /* Return the frame whose principal (outermost) window is WDESC.
480 If WDESC is some other (smaller) window, we return 0. */
483 x_top_window_to_frame (dpyinfo
, wdesc
)
484 struct x_display_info
*dpyinfo
;
487 Lisp_Object tail
, frame
;
491 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
494 if (!GC_FRAMEP (frame
))
497 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
499 x
= f
->output_data
.x
;
503 /* This frame matches if the window is its topmost widget. */
504 if (wdesc
== XtWindow (x
->widget
))
506 #if 0 /* I don't know why it did this,
507 but it seems logically wrong,
508 and it causes trouble for MapNotify events. */
509 /* Match if the window is this frame's menubar. */
510 if (x
->menubar_widget
511 && wdesc
== XtWindow (x
->menubar_widget
))
515 else if (FRAME_X_WINDOW (f
) == wdesc
)
521 #endif /* USE_X_TOOLKIT */
525 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
526 id, which is just an int that this section returns. Bitmaps are
527 reference counted so they can be shared among frames.
529 Bitmap indices are guaranteed to be > 0, so a negative number can
530 be used to indicate no bitmap.
532 If you use x_create_bitmap_from_data, then you must keep track of
533 the bitmaps yourself. That is, creating a bitmap from the same
534 data more than once will not be caught. */
537 /* Functions to access the contents of a bitmap, given an id. */
540 x_bitmap_height (f
, id
)
544 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
548 x_bitmap_width (f
, id
)
552 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
556 x_bitmap_pixmap (f
, id
)
560 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
564 /* Allocate a new bitmap record. Returns index of new record. */
567 x_allocate_bitmap_record (f
)
570 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
573 if (dpyinfo
->bitmaps
== NULL
)
575 dpyinfo
->bitmaps_size
= 10;
577 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
578 dpyinfo
->bitmaps_last
= 1;
582 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
583 return ++dpyinfo
->bitmaps_last
;
585 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
586 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
589 dpyinfo
->bitmaps_size
*= 2;
591 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
592 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
593 return ++dpyinfo
->bitmaps_last
;
596 /* Add one reference to the reference count of the bitmap with id ID. */
599 x_reference_bitmap (f
, id
)
603 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
606 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
609 x_create_bitmap_from_data (f
, bits
, width
, height
)
612 unsigned int width
, height
;
614 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
618 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
619 bits
, width
, height
);
624 id
= x_allocate_bitmap_record (f
);
625 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
626 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
627 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
628 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
629 dpyinfo
->bitmaps
[id
- 1].height
= height
;
630 dpyinfo
->bitmaps
[id
- 1].width
= width
;
635 /* Create bitmap from file FILE for frame F. */
638 x_create_bitmap_from_file (f
, file
)
642 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
643 unsigned int width
, height
;
645 int xhot
, yhot
, result
, id
;
650 /* Look for an existing bitmap with the same name. */
651 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
653 if (dpyinfo
->bitmaps
[id
].refcount
654 && dpyinfo
->bitmaps
[id
].file
655 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
657 ++dpyinfo
->bitmaps
[id
].refcount
;
662 /* Search bitmap-file-path for the file, if appropriate. */
663 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
666 /* XReadBitmapFile won't handle magic file names. */
671 filename
= (char *) XSTRING (found
)->data
;
673 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
674 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
675 if (result
!= BitmapSuccess
)
678 id
= x_allocate_bitmap_record (f
);
679 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
680 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
681 dpyinfo
->bitmaps
[id
- 1].file
682 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
683 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
684 dpyinfo
->bitmaps
[id
- 1].height
= height
;
685 dpyinfo
->bitmaps
[id
- 1].width
= width
;
686 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
691 /* Remove reference to bitmap with id number ID. */
694 x_destroy_bitmap (f
, id
)
698 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
702 --dpyinfo
->bitmaps
[id
- 1].refcount
;
703 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
706 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
707 if (dpyinfo
->bitmaps
[id
- 1].file
)
709 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
710 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
717 /* Free all the bitmaps for the display specified by DPYINFO. */
720 x_destroy_all_bitmaps (dpyinfo
)
721 struct x_display_info
*dpyinfo
;
724 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
725 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
727 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
728 if (dpyinfo
->bitmaps
[i
].file
)
729 xfree (dpyinfo
->bitmaps
[i
].file
);
731 dpyinfo
->bitmaps_last
= 0;
734 /* Connect the frame-parameter names for X frames
735 to the ways of passing the parameter values to the window system.
737 The name of a parameter, as a Lisp symbol,
738 has an `x-frame-parameter' property which is an integer in Lisp
739 that is an index in this table. */
741 struct x_frame_parm_table
744 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 static void x_change_window_heights
P_ ((Lisp_Object
, int));
748 static void x_disable_image
P_ ((struct frame
*, struct image
*));
749 static void x_create_im
P_ ((struct frame
*));
750 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
752 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
756 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
760 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
761 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
763 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
764 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
765 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
766 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
768 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
769 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
770 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
771 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
772 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
773 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
774 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
776 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
778 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
783 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
784 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
786 static void init_color_table
P_ ((void));
787 static void free_color_table
P_ ((void));
788 static unsigned long *colors_in_color_table
P_ ((int *n
));
789 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
790 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
794 static struct x_frame_parm_table x_frame_parms
[] =
796 "auto-raise", x_set_autoraise
,
797 "auto-lower", x_set_autolower
,
798 "background-color", x_set_background_color
,
799 "border-color", x_set_border_color
,
800 "border-width", x_set_border_width
,
801 "cursor-color", x_set_cursor_color
,
802 "cursor-type", x_set_cursor_type
,
804 "foreground-color", x_set_foreground_color
,
805 "icon-name", x_set_icon_name
,
806 "icon-type", x_set_icon_type
,
807 "internal-border-width", x_set_internal_border_width
,
808 "menu-bar-lines", x_set_menu_bar_lines
,
809 "mouse-color", x_set_mouse_color
,
810 "name", x_explicitly_set_name
,
811 "scroll-bar-width", x_set_scroll_bar_width
,
812 "title", x_set_title
,
813 "unsplittable", x_set_unsplittable
,
814 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
815 "visibility", x_set_visibility
,
816 "tool-bar-lines", x_set_tool_bar_lines
,
817 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
818 "scroll-bar-background", x_set_scroll_bar_background
,
819 "screen-gamma", x_set_screen_gamma
,
820 "line-spacing", x_set_line_spacing
823 /* Attach the `x-frame-parameter' properties to
824 the Lisp symbol names of parameters relevant to X. */
827 init_x_parm_symbols ()
831 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
832 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
836 /* Change the parameters of frame F as specified by ALIST.
837 If a parameter is not specially recognized, do nothing special;
838 otherwise call the `x_set_...' function for that parameter.
839 Except for certain geometry properties, always call store_frame_param
840 to store the new value in the parameter alist. */
843 x_set_frame_parameters (f
, alist
)
849 /* If both of these parameters are present, it's more efficient to
850 set them both at once. So we wait until we've looked at the
851 entire list before we set them. */
855 Lisp_Object left
, top
;
857 /* Same with these. */
858 Lisp_Object icon_left
, icon_top
;
860 /* Record in these vectors all the parms specified. */
864 int left_no_change
= 0, top_no_change
= 0;
865 int icon_left_no_change
= 0, icon_top_no_change
= 0;
867 struct gcpro gcpro1
, gcpro2
;
870 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
873 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
874 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
876 /* Extract parm names and values into those vectors. */
879 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
884 parms
[i
] = Fcar (elt
);
885 values
[i
] = Fcdr (elt
);
888 /* TAIL and ALIST are not used again below here. */
891 GCPRO2 (*parms
, *values
);
895 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
896 because their values appear in VALUES and strings are not valid. */
897 top
= left
= Qunbound
;
898 icon_left
= icon_top
= Qunbound
;
900 /* Provide default values for HEIGHT and WIDTH. */
901 if (FRAME_NEW_WIDTH (f
))
902 width
= FRAME_NEW_WIDTH (f
);
904 width
= FRAME_WIDTH (f
);
906 if (FRAME_NEW_HEIGHT (f
))
907 height
= FRAME_NEW_HEIGHT (f
);
909 height
= FRAME_HEIGHT (f
);
911 /* Process foreground_color and background_color before anything else.
912 They are independent of other properties, but other properties (e.g.,
913 cursor_color) are dependent upon them. */
914 for (p
= 0; p
< i
; p
++)
916 Lisp_Object prop
, val
;
920 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
922 register Lisp_Object param_index
, old_value
;
924 param_index
= Fget (prop
, Qx_frame_parameter
);
925 old_value
= get_frame_param (f
, prop
);
926 store_frame_param (f
, prop
, val
);
927 if (NATNUMP (param_index
)
928 && (XFASTINT (param_index
)
929 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
930 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
934 /* Now process them in reverse of specified order. */
935 for (i
--; i
>= 0; i
--)
937 Lisp_Object prop
, val
;
942 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
943 width
= XFASTINT (val
);
944 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
945 height
= XFASTINT (val
);
946 else if (EQ (prop
, Qtop
))
948 else if (EQ (prop
, Qleft
))
950 else if (EQ (prop
, Qicon_top
))
952 else if (EQ (prop
, Qicon_left
))
954 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
955 /* Processed above. */
959 register Lisp_Object param_index
, old_value
;
961 param_index
= Fget (prop
, Qx_frame_parameter
);
962 old_value
= get_frame_param (f
, prop
);
963 store_frame_param (f
, prop
, val
);
964 if (NATNUMP (param_index
)
965 && (XFASTINT (param_index
)
966 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
967 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
971 /* Don't die if just one of these was set. */
972 if (EQ (left
, Qunbound
))
975 if (f
->output_data
.x
->left_pos
< 0)
976 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
978 XSETINT (left
, f
->output_data
.x
->left_pos
);
980 if (EQ (top
, Qunbound
))
983 if (f
->output_data
.x
->top_pos
< 0)
984 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
986 XSETINT (top
, f
->output_data
.x
->top_pos
);
989 /* If one of the icon positions was not set, preserve or default it. */
990 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
992 icon_left_no_change
= 1;
993 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
994 if (NILP (icon_left
))
995 XSETINT (icon_left
, 0);
997 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
999 icon_top_no_change
= 1;
1000 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
1001 if (NILP (icon_top
))
1002 XSETINT (icon_top
, 0);
1005 /* Don't set these parameters unless they've been explicitly
1006 specified. The window might be mapped or resized while we're in
1007 this function, and we don't want to override that unless the lisp
1008 code has asked for it.
1010 Don't set these parameters unless they actually differ from the
1011 window's current parameters; the window may not actually exist
1016 check_frame_size (f
, &height
, &width
);
1018 XSETFRAME (frame
, f
);
1020 if (width
!= FRAME_WIDTH (f
)
1021 || height
!= FRAME_HEIGHT (f
)
1022 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1023 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1025 if ((!NILP (left
) || !NILP (top
))
1026 && ! (left_no_change
&& top_no_change
)
1027 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1028 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1033 /* Record the signs. */
1034 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1035 if (EQ (left
, Qminus
))
1036 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1037 else if (INTEGERP (left
))
1039 leftpos
= XINT (left
);
1041 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1043 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1044 && CONSP (XCDR (left
))
1045 && INTEGERP (XCAR (XCDR (left
))))
1047 leftpos
= - XINT (XCAR (XCDR (left
)));
1048 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1050 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1051 && CONSP (XCDR (left
))
1052 && INTEGERP (XCAR (XCDR (left
))))
1054 leftpos
= XINT (XCAR (XCDR (left
)));
1057 if (EQ (top
, Qminus
))
1058 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1059 else if (INTEGERP (top
))
1061 toppos
= XINT (top
);
1063 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1065 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1066 && CONSP (XCDR (top
))
1067 && INTEGERP (XCAR (XCDR (top
))))
1069 toppos
= - XINT (XCAR (XCDR (top
)));
1070 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1072 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1073 && CONSP (XCDR (top
))
1074 && INTEGERP (XCAR (XCDR (top
))))
1076 toppos
= XINT (XCAR (XCDR (top
)));
1080 /* Store the numeric value of the position. */
1081 f
->output_data
.x
->top_pos
= toppos
;
1082 f
->output_data
.x
->left_pos
= leftpos
;
1084 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1086 /* Actually set that position, and convert to absolute. */
1087 x_set_offset (f
, leftpos
, toppos
, -1);
1090 if ((!NILP (icon_left
) || !NILP (icon_top
))
1091 && ! (icon_left_no_change
&& icon_top_no_change
))
1092 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1098 /* Store the screen positions of frame F into XPTR and YPTR.
1099 These are the positions of the containing window manager window,
1100 not Emacs's own window. */
1103 x_real_positions (f
, xptr
, yptr
)
1110 /* This is pretty gross, but seems to be the easiest way out of
1111 the problem that arises when restarting window-managers. */
1113 #ifdef USE_X_TOOLKIT
1114 Window outer
= (f
->output_data
.x
->widget
1115 ? XtWindow (f
->output_data
.x
->widget
)
1116 : FRAME_X_WINDOW (f
));
1118 Window outer
= f
->output_data
.x
->window_desc
;
1120 Window tmp_root_window
;
1121 Window
*tmp_children
;
1122 unsigned int tmp_nchildren
;
1126 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1127 Window outer_window
;
1129 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1130 &f
->output_data
.x
->parent_desc
,
1131 &tmp_children
, &tmp_nchildren
);
1132 XFree ((char *) tmp_children
);
1136 /* Find the position of the outside upper-left corner of
1137 the inner window, with respect to the outer window. */
1138 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1139 outer_window
= f
->output_data
.x
->parent_desc
;
1141 outer_window
= outer
;
1143 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1145 /* From-window, to-window. */
1147 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1149 /* From-position, to-position. */
1150 0, 0, &win_x
, &win_y
,
1155 /* It is possible for the window returned by the XQueryNotify
1156 to become invalid by the time we call XTranslateCoordinates.
1157 That can happen when you restart some window managers.
1158 If so, we get an error in XTranslateCoordinates.
1159 Detect that and try the whole thing over. */
1160 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1162 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1166 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1173 /* Insert a description of internally-recorded parameters of frame X
1174 into the parameter alist *ALISTPTR that is to be given to the user.
1175 Only parameters that are specific to the X window system
1176 and whose values are not correctly recorded in the frame's
1177 param_alist need to be considered here. */
1180 x_report_frame_params (f
, alistptr
)
1182 Lisp_Object
*alistptr
;
1187 /* Represent negative positions (off the top or left screen edge)
1188 in a way that Fmodify_frame_parameters will understand correctly. */
1189 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1190 if (f
->output_data
.x
->left_pos
>= 0)
1191 store_in_alist (alistptr
, Qleft
, tem
);
1193 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1195 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1196 if (f
->output_data
.x
->top_pos
>= 0)
1197 store_in_alist (alistptr
, Qtop
, tem
);
1199 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1201 store_in_alist (alistptr
, Qborder_width
,
1202 make_number (f
->output_data
.x
->border_width
));
1203 store_in_alist (alistptr
, Qinternal_border_width
,
1204 make_number (f
->output_data
.x
->internal_border_width
));
1205 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1206 store_in_alist (alistptr
, Qwindow_id
,
1207 build_string (buf
));
1208 #ifdef USE_X_TOOLKIT
1209 /* Tooltip frame may not have this widget. */
1210 if (f
->output_data
.x
->widget
)
1212 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1213 store_in_alist (alistptr
, Qouter_window_id
,
1214 build_string (buf
));
1215 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1216 FRAME_SAMPLE_VISIBILITY (f
);
1217 store_in_alist (alistptr
, Qvisibility
,
1218 (FRAME_VISIBLE_P (f
) ? Qt
1219 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1220 store_in_alist (alistptr
, Qdisplay
,
1221 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1223 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1226 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1227 store_in_alist (alistptr
, Qparent_id
, tem
);
1232 /* Gamma-correct COLOR on frame F. */
1235 gamma_correct (f
, color
)
1241 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1242 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1243 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1248 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1249 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1250 allocate the color. Value is zero if COLOR_NAME is invalid, or
1251 no color could be allocated. */
1254 x_defined_color (f
, color_name
, color
, alloc_p
)
1261 Display
*dpy
= FRAME_X_DISPLAY (f
);
1262 Colormap cmap
= FRAME_X_COLORMAP (f
);
1265 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1266 if (success_p
&& alloc_p
)
1267 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1274 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1275 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1276 Signal an error if color can't be allocated. */
1279 x_decode_color (f
, color_name
, mono_color
)
1281 Lisp_Object color_name
;
1286 CHECK_STRING (color_name
, 0);
1288 #if 0 /* Don't do this. It's wrong when we're not using the default
1289 colormap, it makes freeing difficult, and it's probably not
1290 an important optimization. */
1291 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1292 return BLACK_PIX_DEFAULT (f
);
1293 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1294 return WHITE_PIX_DEFAULT (f
);
1297 /* Return MONO_COLOR for monochrome frames. */
1298 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1301 /* x_defined_color is responsible for coping with failures
1302 by looking for a near-miss. */
1303 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1306 Fsignal (Qerror
, Fcons (build_string ("Undefined color"),
1307 Fcons (color_name
, Qnil
)));
1313 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1314 the previous value of that parameter, NEW_VALUE is the new value. */
1317 x_set_line_spacing (f
, new_value
, old_value
)
1319 Lisp_Object new_value
, old_value
;
1321 if (NILP (new_value
))
1322 f
->extra_line_spacing
= 0;
1323 else if (NATNUMP (new_value
))
1324 f
->extra_line_spacing
= XFASTINT (new_value
);
1326 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1327 Fcons (new_value
, Qnil
)));
1328 if (FRAME_VISIBLE_P (f
))
1333 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1334 the previous value of that parameter, NEW_VALUE is the new value. */
1337 x_set_screen_gamma (f
, new_value
, old_value
)
1339 Lisp_Object new_value
, old_value
;
1341 if (NILP (new_value
))
1343 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1344 /* The value 0.4545 is the normal viewing gamma. */
1345 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1347 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1348 Fcons (new_value
, Qnil
)));
1350 clear_face_cache (0);
1354 /* Functions called only from `x_set_frame_param'
1355 to set individual parameters.
1357 If FRAME_X_WINDOW (f) is 0,
1358 the frame is being created and its X-window does not exist yet.
1359 In that case, just record the parameter's new value
1360 in the standard place; do not attempt to change the window. */
1363 x_set_foreground_color (f
, arg
, oldval
)
1365 Lisp_Object arg
, oldval
;
1368 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1370 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
1371 f
->output_data
.x
->foreground_pixel
= pixel
;
1373 if (FRAME_X_WINDOW (f
) != 0)
1376 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1377 f
->output_data
.x
->foreground_pixel
);
1378 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1379 f
->output_data
.x
->foreground_pixel
);
1381 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1382 if (FRAME_VISIBLE_P (f
))
1388 x_set_background_color (f
, arg
, oldval
)
1390 Lisp_Object arg
, oldval
;
1393 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1395 unload_color (f
, f
->output_data
.x
->background_pixel
);
1396 f
->output_data
.x
->background_pixel
= pixel
;
1398 if (FRAME_X_WINDOW (f
) != 0)
1401 /* The main frame area. */
1402 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1403 f
->output_data
.x
->background_pixel
);
1404 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1405 f
->output_data
.x
->background_pixel
);
1406 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1407 f
->output_data
.x
->background_pixel
);
1408 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1409 f
->output_data
.x
->background_pixel
);
1412 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1413 bar
= XSCROLL_BAR (bar
)->next
)
1414 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1415 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1416 f
->output_data
.x
->background_pixel
);
1420 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1422 if (FRAME_VISIBLE_P (f
))
1428 x_set_mouse_color (f
, arg
, oldval
)
1430 Lisp_Object arg
, oldval
;
1432 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1435 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1436 unsigned long mask_color
= f
->output_data
.x
->background_pixel
;
1438 /* Don't let pointers be invisible. */
1439 if (mask_color
== pixel
1440 && mask_color
== f
->output_data
.x
->background_pixel
)
1441 pixel
= f
->output_data
.x
->foreground_pixel
;
1443 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
1444 f
->output_data
.x
->mouse_pixel
= pixel
;
1448 /* It's not okay to crash if the user selects a screwy cursor. */
1449 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1451 if (!EQ (Qnil
, Vx_pointer_shape
))
1453 CHECK_NUMBER (Vx_pointer_shape
, 0);
1454 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1457 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1458 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1460 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1462 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1463 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1464 XINT (Vx_nontext_pointer_shape
));
1467 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1468 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1470 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
1472 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
1473 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1474 XINT (Vx_busy_pointer_shape
));
1477 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_watch
);
1478 x_check_errors (FRAME_X_DISPLAY (f
), "bad busy pointer cursor: %s");
1480 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1481 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1483 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1484 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1485 XINT (Vx_mode_pointer_shape
));
1488 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1489 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1491 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1493 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1495 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1496 XINT (Vx_sensitive_text_pointer_shape
));
1499 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1501 /* Check and report errors with the above calls. */
1502 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1503 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1506 XColor fore_color
, back_color
;
1508 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1509 x_query_color (f
, &fore_color
);
1510 back_color
.pixel
= mask_color
;
1511 x_query_color (f
, &back_color
);
1513 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1514 &fore_color
, &back_color
);
1515 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1516 &fore_color
, &back_color
);
1517 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1518 &fore_color
, &back_color
);
1519 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1520 &fore_color
, &back_color
);
1521 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1522 &fore_color
, &back_color
);
1525 if (FRAME_X_WINDOW (f
) != 0)
1526 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1528 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1529 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1530 f
->output_data
.x
->text_cursor
= cursor
;
1532 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1533 && f
->output_data
.x
->nontext_cursor
!= 0)
1534 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1535 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1537 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1538 && f
->output_data
.x
->busy_cursor
!= 0)
1539 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1540 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1542 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1543 && f
->output_data
.x
->modeline_cursor
!= 0)
1544 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1545 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1547 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1548 && f
->output_data
.x
->cross_cursor
!= 0)
1549 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1550 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1552 XFlush (FRAME_X_DISPLAY (f
));
1555 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1559 x_set_cursor_color (f
, arg
, oldval
)
1561 Lisp_Object arg
, oldval
;
1563 unsigned long fore_pixel
, pixel
;
1564 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1566 if (!NILP (Vx_cursor_fore_pixel
))
1568 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1569 WHITE_PIX_DEFAULT (f
));
1570 fore_pixel_allocated_p
= 1;
1573 fore_pixel
= f
->output_data
.x
->background_pixel
;
1575 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1576 pixel_allocated_p
= 1;
1578 /* Make sure that the cursor color differs from the background color. */
1579 if (pixel
== f
->output_data
.x
->background_pixel
)
1581 if (pixel_allocated_p
)
1583 x_free_colors (f
, &pixel
, 1);
1584 pixel_allocated_p
= 0;
1587 pixel
= f
->output_data
.x
->mouse_pixel
;
1588 if (pixel
== fore_pixel
)
1590 if (fore_pixel_allocated_p
)
1592 x_free_colors (f
, &fore_pixel
, 1);
1593 fore_pixel_allocated_p
= 0;
1595 fore_pixel
= f
->output_data
.x
->background_pixel
;
1599 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1600 if (!fore_pixel_allocated_p
)
1601 fore_pixel
= x_copy_color (f
, fore_pixel
);
1602 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1604 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1605 if (!pixel_allocated_p
)
1606 pixel
= x_copy_color (f
, pixel
);
1607 f
->output_data
.x
->cursor_pixel
= pixel
;
1609 if (FRAME_X_WINDOW (f
) != 0)
1612 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1613 f
->output_data
.x
->cursor_pixel
);
1614 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1618 if (FRAME_VISIBLE_P (f
))
1620 x_update_cursor (f
, 0);
1621 x_update_cursor (f
, 1);
1625 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1628 /* Set the border-color of frame F to value described by ARG.
1629 ARG can be a string naming a color.
1630 The border-color is used for the border that is drawn by the X server.
1631 Note that this does not fully take effect if done before
1632 F has an x-window; it must be redone when the window is created.
1634 Note: this is done in two routines because of the way X10 works.
1636 Note: under X11, this is normally the province of the window manager,
1637 and so emacs' border colors may be overridden. */
1640 x_set_border_color (f
, arg
, oldval
)
1642 Lisp_Object arg
, oldval
;
1646 CHECK_STRING (arg
, 0);
1647 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1648 x_set_border_pixel (f
, pix
);
1649 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1652 /* Set the border-color of frame F to pixel value PIX.
1653 Note that this does not fully take effect if done before
1654 F has an x-window. */
1657 x_set_border_pixel (f
, pix
)
1661 unload_color (f
, f
->output_data
.x
->border_pixel
);
1662 f
->output_data
.x
->border_pixel
= pix
;
1664 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1667 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1668 (unsigned long)pix
);
1671 if (FRAME_VISIBLE_P (f
))
1677 /* Value is the internal representation of the specified cursor type
1678 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1679 of the bar cursor. */
1681 enum text_cursor_kinds
1682 x_specified_cursor_type (arg
, width
)
1686 enum text_cursor_kinds type
;
1693 else if (CONSP (arg
)
1694 && EQ (XCAR (arg
), Qbar
)
1695 && INTEGERP (XCDR (arg
))
1696 && XINT (XCDR (arg
)) >= 0)
1699 *width
= XINT (XCDR (arg
));
1701 else if (NILP (arg
))
1704 /* Treat anything unknown as "box cursor".
1705 It was bad to signal an error; people have trouble fixing
1706 .Xdefaults with Emacs, when it has something bad in it. */
1707 type
= FILLED_BOX_CURSOR
;
1713 x_set_cursor_type (f
, arg
, oldval
)
1715 Lisp_Object arg
, oldval
;
1719 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1720 f
->output_data
.x
->cursor_width
= width
;
1722 /* Make sure the cursor gets redrawn. This is overkill, but how
1723 often do people change cursor types? */
1724 update_mode_lines
++;
1728 x_set_icon_type (f
, arg
, oldval
)
1730 Lisp_Object arg
, oldval
;
1736 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1739 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1744 result
= x_text_icon (f
,
1745 (char *) XSTRING ((!NILP (f
->icon_name
)
1749 result
= x_bitmap_icon (f
, arg
);
1754 error ("No icon window available");
1757 XFlush (FRAME_X_DISPLAY (f
));
1761 /* Return non-nil if frame F wants a bitmap icon. */
1769 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1777 x_set_icon_name (f
, arg
, oldval
)
1779 Lisp_Object arg
, oldval
;
1785 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1788 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1793 if (f
->output_data
.x
->icon_bitmap
!= 0)
1798 result
= x_text_icon (f
,
1799 (char *) XSTRING ((!NILP (f
->icon_name
)
1808 error ("No icon window available");
1811 XFlush (FRAME_X_DISPLAY (f
));
1816 x_set_font (f
, arg
, oldval
)
1818 Lisp_Object arg
, oldval
;
1821 Lisp_Object fontset_name
;
1824 CHECK_STRING (arg
, 1);
1826 fontset_name
= Fquery_fontset (arg
, Qnil
);
1829 result
= (STRINGP (fontset_name
)
1830 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1831 : x_new_font (f
, XSTRING (arg
)->data
));
1834 if (EQ (result
, Qnil
))
1835 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1836 else if (EQ (result
, Qt
))
1837 error ("The characters of the given font have varying widths");
1838 else if (STRINGP (result
))
1840 store_frame_param (f
, Qfont
, result
);
1841 recompute_basic_faces (f
);
1846 do_pending_window_change (0);
1848 /* Don't call `face-set-after-frame-default' when faces haven't been
1849 initialized yet. This is the case when called from
1850 Fx_create_frame. In that case, the X widget or window doesn't
1851 exist either, and we can end up in x_report_frame_params with a
1852 null widget which gives a segfault. */
1853 if (FRAME_FACE_CACHE (f
))
1855 XSETFRAME (frame
, f
);
1856 call1 (Qface_set_after_frame_default
, frame
);
1861 x_set_border_width (f
, arg
, oldval
)
1863 Lisp_Object arg
, oldval
;
1865 CHECK_NUMBER (arg
, 0);
1867 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1870 if (FRAME_X_WINDOW (f
) != 0)
1871 error ("Cannot change the border width of a window");
1873 f
->output_data
.x
->border_width
= XINT (arg
);
1877 x_set_internal_border_width (f
, arg
, oldval
)
1879 Lisp_Object arg
, oldval
;
1881 int old
= f
->output_data
.x
->internal_border_width
;
1883 CHECK_NUMBER (arg
, 0);
1884 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1885 if (f
->output_data
.x
->internal_border_width
< 0)
1886 f
->output_data
.x
->internal_border_width
= 0;
1888 #ifdef USE_X_TOOLKIT
1889 if (f
->output_data
.x
->edit_widget
)
1890 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1893 if (f
->output_data
.x
->internal_border_width
== old
)
1896 if (FRAME_X_WINDOW (f
) != 0)
1898 x_set_window_size (f
, 0, f
->width
, f
->height
);
1899 SET_FRAME_GARBAGED (f
);
1900 do_pending_window_change (0);
1905 x_set_visibility (f
, value
, oldval
)
1907 Lisp_Object value
, oldval
;
1910 XSETFRAME (frame
, f
);
1913 Fmake_frame_invisible (frame
, Qt
);
1914 else if (EQ (value
, Qicon
))
1915 Ficonify_frame (frame
);
1917 Fmake_frame_visible (frame
);
1921 /* Change window heights in windows rooted in WINDOW by N lines. */
1924 x_change_window_heights (window
, n
)
1928 struct window
*w
= XWINDOW (window
);
1930 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1931 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1933 if (INTEGERP (w
->orig_top
))
1934 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
1935 if (INTEGERP (w
->orig_height
))
1936 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
1938 /* Handle just the top child in a vertical split. */
1939 if (!NILP (w
->vchild
))
1940 x_change_window_heights (w
->vchild
, n
);
1942 /* Adjust all children in a horizontal split. */
1943 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1945 w
= XWINDOW (window
);
1946 x_change_window_heights (window
, n
);
1951 x_set_menu_bar_lines (f
, value
, oldval
)
1953 Lisp_Object value
, oldval
;
1956 #ifndef USE_X_TOOLKIT
1957 int olines
= FRAME_MENU_BAR_LINES (f
);
1960 /* Right now, menu bars don't work properly in minibuf-only frames;
1961 most of the commands try to apply themselves to the minibuffer
1962 frame itself, and get an error because you can't switch buffers
1963 in or split the minibuffer window. */
1964 if (FRAME_MINIBUF_ONLY_P (f
))
1967 if (INTEGERP (value
))
1968 nlines
= XINT (value
);
1972 /* Make sure we redisplay all windows in this frame. */
1973 windows_or_buffers_changed
++;
1975 #ifdef USE_X_TOOLKIT
1976 FRAME_MENU_BAR_LINES (f
) = 0;
1979 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1980 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1981 /* Make sure next redisplay shows the menu bar. */
1982 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1986 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1987 free_frame_menubar (f
);
1988 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1990 f
->output_data
.x
->menubar_widget
= 0;
1992 #else /* not USE_X_TOOLKIT */
1993 FRAME_MENU_BAR_LINES (f
) = nlines
;
1994 x_change_window_heights (f
->root_window
, nlines
- olines
);
1995 #endif /* not USE_X_TOOLKIT */
2000 /* Set the number of lines used for the tool bar of frame F to VALUE.
2001 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2002 is the old number of tool bar lines. This function changes the
2003 height of all windows on frame F to match the new tool bar height.
2004 The frame's height doesn't change. */
2007 x_set_tool_bar_lines (f
, value
, oldval
)
2009 Lisp_Object value
, oldval
;
2011 int delta
, nlines
, root_height
;
2012 Lisp_Object root_window
;
2014 /* Use VALUE only if an integer >= 0. */
2015 if (INTEGERP (value
) && XINT (value
) >= 0)
2016 nlines
= XFASTINT (value
);
2020 /* Make sure we redisplay all windows in this frame. */
2021 ++windows_or_buffers_changed
;
2023 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2025 /* Don't resize the tool-bar to more than we have room for. */
2026 root_window
= FRAME_ROOT_WINDOW (f
);
2027 root_height
= XINT (XWINDOW (root_window
)->height
);
2028 if (root_height
- delta
< 1)
2030 delta
= root_height
- 1;
2031 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2034 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2035 x_change_window_heights (root_window
, delta
);
2038 /* We also have to make sure that the internal border at the top of
2039 the frame, below the menu bar or tool bar, is redrawn when the
2040 tool bar disappears. This is so because the internal border is
2041 below the tool bar if one is displayed, but is below the menu bar
2042 if there isn't a tool bar. The tool bar draws into the area
2043 below the menu bar. */
2044 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2048 updating_frame
= NULL
;
2053 /* Set the foreground color for scroll bars on frame F to VALUE.
2054 VALUE should be a string, a color name. If it isn't a string or
2055 isn't a valid color name, do nothing. OLDVAL is the old value of
2056 the frame parameter. */
2059 x_set_scroll_bar_foreground (f
, value
, oldval
)
2061 Lisp_Object value
, oldval
;
2063 unsigned long pixel
;
2065 if (STRINGP (value
))
2066 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2070 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2071 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2073 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2074 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2076 /* Remove all scroll bars because they have wrong colors. */
2077 if (condemn_scroll_bars_hook
)
2078 (*condemn_scroll_bars_hook
) (f
);
2079 if (judge_scroll_bars_hook
)
2080 (*judge_scroll_bars_hook
) (f
);
2082 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2088 /* Set the background color for scroll bars on frame F to VALUE VALUE
2089 should be a string, a color name. If it isn't a string or isn't a
2090 valid color name, do nothing. OLDVAL is the old value of the frame
2094 x_set_scroll_bar_background (f
, value
, oldval
)
2096 Lisp_Object value
, oldval
;
2098 unsigned long pixel
;
2100 if (STRINGP (value
))
2101 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2105 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2106 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2108 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2109 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2111 /* Remove all scroll bars because they have wrong colors. */
2112 if (condemn_scroll_bars_hook
)
2113 (*condemn_scroll_bars_hook
) (f
);
2114 if (judge_scroll_bars_hook
)
2115 (*judge_scroll_bars_hook
) (f
);
2117 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2123 /* Encode Lisp string STRING as a text in a format appropriate for
2124 XICCC (X Inter Client Communication Conventions).
2126 If STRING contains only ASCII characters, do no conversion and
2127 return the string data of STRING. Otherwise, encode the text by
2128 CODING_SYSTEM, and return a newly allocated memory area which
2129 should be freed by `xfree' by a caller.
2131 Store the byte length of resulting text in *TEXT_BYTES.
2133 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2134 which means that the `encoding' of the result can be `STRING'.
2135 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2136 the result should be `COMPOUND_TEXT'. */
2139 x_encode_text (string
, coding_system
, text_bytes
, stringp
)
2140 Lisp_Object string
, coding_system
;
2141 int *text_bytes
, *stringp
;
2143 unsigned char *str
= XSTRING (string
)->data
;
2144 int chars
= XSTRING (string
)->size
;
2145 int bytes
= STRING_BYTES (XSTRING (string
));
2149 struct coding_system coding
;
2151 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2152 if (charset_info
== 0)
2154 /* No multibyte character in OBJ. We need not encode it. */
2155 *text_bytes
= bytes
;
2160 setup_coding_system (coding_system
, &coding
);
2161 coding
.src_multibyte
= 1;
2162 coding
.dst_multibyte
= 0;
2163 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2164 if (coding
.type
== coding_type_iso2022
)
2165 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2166 bufsize
= encoding_buffer_size (&coding
, bytes
);
2167 buf
= (unsigned char *) xmalloc (bufsize
);
2168 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2169 *text_bytes
= coding
.produced
;
2170 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2175 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2178 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2179 name; if NAME is a string, set F's name to NAME and set
2180 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2182 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2183 suggesting a new name, which lisp code should override; if
2184 F->explicit_name is set, ignore the new name; otherwise, set it. */
2187 x_set_name (f
, name
, explicit)
2192 /* Make sure that requests from lisp code override requests from
2193 Emacs redisplay code. */
2196 /* If we're switching from explicit to implicit, we had better
2197 update the mode lines and thereby update the title. */
2198 if (f
->explicit_name
&& NILP (name
))
2199 update_mode_lines
= 1;
2201 f
->explicit_name
= ! NILP (name
);
2203 else if (f
->explicit_name
)
2206 /* If NAME is nil, set the name to the x_id_name. */
2209 /* Check for no change needed in this very common case
2210 before we do any consing. */
2211 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2212 XSTRING (f
->name
)->data
))
2214 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2217 CHECK_STRING (name
, 0);
2219 /* Don't change the name if it's already NAME. */
2220 if (! NILP (Fstring_equal (name
, f
->name
)))
2225 /* For setting the frame title, the title parameter should override
2226 the name parameter. */
2227 if (! NILP (f
->title
))
2230 if (FRAME_X_WINDOW (f
))
2235 XTextProperty text
, icon
;
2237 Lisp_Object coding_system
;
2239 coding_system
= Vlocale_coding_system
;
2240 if (NILP (coding_system
))
2241 coding_system
= Qcompound_text
;
2242 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2243 text
.encoding
= (stringp
? XA_STRING
2244 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2246 text
.nitems
= bytes
;
2248 if (NILP (f
->icon_name
))
2254 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2256 icon
.encoding
= (stringp
? XA_STRING
2257 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2259 icon
.nitems
= bytes
;
2261 #ifdef USE_X_TOOLKIT
2262 XSetWMName (FRAME_X_DISPLAY (f
),
2263 XtWindow (f
->output_data
.x
->widget
), &text
);
2264 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2266 #else /* not USE_X_TOOLKIT */
2267 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2268 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2269 #endif /* not USE_X_TOOLKIT */
2270 if (!NILP (f
->icon_name
)
2271 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2273 if (text
.value
!= XSTRING (name
)->data
)
2276 #else /* not HAVE_X11R4 */
2277 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2278 XSTRING (name
)->data
);
2279 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2280 XSTRING (name
)->data
);
2281 #endif /* not HAVE_X11R4 */
2286 /* This function should be called when the user's lisp code has
2287 specified a name for the frame; the name will override any set by the
2290 x_explicitly_set_name (f
, arg
, oldval
)
2292 Lisp_Object arg
, oldval
;
2294 x_set_name (f
, arg
, 1);
2297 /* This function should be called by Emacs redisplay code to set the
2298 name; names set this way will never override names set by the user's
2301 x_implicitly_set_name (f
, arg
, oldval
)
2303 Lisp_Object arg
, oldval
;
2305 x_set_name (f
, arg
, 0);
2308 /* Change the title of frame F to NAME.
2309 If NAME is nil, use the frame name as the title.
2311 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2312 name; if NAME is a string, set F's name to NAME and set
2313 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2315 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2316 suggesting a new name, which lisp code should override; if
2317 F->explicit_name is set, ignore the new name; otherwise, set it. */
2320 x_set_title (f
, name
, old_name
)
2322 Lisp_Object name
, old_name
;
2324 /* Don't change the title if it's already NAME. */
2325 if (EQ (name
, f
->title
))
2328 update_mode_lines
= 1;
2335 CHECK_STRING (name
, 0);
2337 if (FRAME_X_WINDOW (f
))
2342 XTextProperty text
, icon
;
2344 Lisp_Object coding_system
;
2346 coding_system
= Vlocale_coding_system
;
2347 if (NILP (coding_system
))
2348 coding_system
= Qcompound_text
;
2349 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2350 text
.encoding
= (stringp
? XA_STRING
2351 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2353 text
.nitems
= bytes
;
2355 if (NILP (f
->icon_name
))
2361 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2363 icon
.encoding
= (stringp
? XA_STRING
2364 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2366 icon
.nitems
= bytes
;
2368 #ifdef USE_X_TOOLKIT
2369 XSetWMName (FRAME_X_DISPLAY (f
),
2370 XtWindow (f
->output_data
.x
->widget
), &text
);
2371 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2373 #else /* not USE_X_TOOLKIT */
2374 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2375 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2376 #endif /* not USE_X_TOOLKIT */
2377 if (!NILP (f
->icon_name
)
2378 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2380 if (text
.value
!= XSTRING (name
)->data
)
2383 #else /* not HAVE_X11R4 */
2384 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2385 XSTRING (name
)->data
);
2386 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2387 XSTRING (name
)->data
);
2388 #endif /* not HAVE_X11R4 */
2394 x_set_autoraise (f
, arg
, oldval
)
2396 Lisp_Object arg
, oldval
;
2398 f
->auto_raise
= !EQ (Qnil
, arg
);
2402 x_set_autolower (f
, arg
, oldval
)
2404 Lisp_Object arg
, oldval
;
2406 f
->auto_lower
= !EQ (Qnil
, arg
);
2410 x_set_unsplittable (f
, arg
, oldval
)
2412 Lisp_Object arg
, oldval
;
2414 f
->no_split
= !NILP (arg
);
2418 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2420 Lisp_Object arg
, oldval
;
2422 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2423 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2424 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2425 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2427 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2429 ? vertical_scroll_bar_none
2431 ? vertical_scroll_bar_right
2432 : vertical_scroll_bar_left
);
2434 /* We set this parameter before creating the X window for the
2435 frame, so we can get the geometry right from the start.
2436 However, if the window hasn't been created yet, we shouldn't
2437 call x_set_window_size. */
2438 if (FRAME_X_WINDOW (f
))
2439 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2440 do_pending_window_change (0);
2445 x_set_scroll_bar_width (f
, arg
, oldval
)
2447 Lisp_Object arg
, oldval
;
2449 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2453 #ifdef USE_TOOLKIT_SCROLL_BARS
2454 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2455 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2456 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2457 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2459 /* Make the actual width at least 14 pixels and a multiple of a
2461 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2463 /* Use all of that space (aside from required margins) for the
2465 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2468 if (FRAME_X_WINDOW (f
))
2469 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2470 do_pending_window_change (0);
2472 else if (INTEGERP (arg
) && XINT (arg
) > 0
2473 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2475 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2476 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2478 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2479 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2480 if (FRAME_X_WINDOW (f
))
2481 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2484 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2485 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2486 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2491 /* Subroutines of creating an X frame. */
2493 /* Make sure that Vx_resource_name is set to a reasonable value.
2494 Fix it up, or set it to `emacs' if it is too hopeless. */
2497 validate_x_resource_name ()
2500 /* Number of valid characters in the resource name. */
2502 /* Number of invalid characters in the resource name. */
2507 if (!STRINGP (Vx_resource_class
))
2508 Vx_resource_class
= build_string (EMACS_CLASS
);
2510 if (STRINGP (Vx_resource_name
))
2512 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2515 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2517 /* Only letters, digits, - and _ are valid in resource names.
2518 Count the valid characters and count the invalid ones. */
2519 for (i
= 0; i
< len
; i
++)
2522 if (! ((c
>= 'a' && c
<= 'z')
2523 || (c
>= 'A' && c
<= 'Z')
2524 || (c
>= '0' && c
<= '9')
2525 || c
== '-' || c
== '_'))
2532 /* Not a string => completely invalid. */
2533 bad_count
= 5, good_count
= 0;
2535 /* If name is valid already, return. */
2539 /* If name is entirely invalid, or nearly so, use `emacs'. */
2541 || (good_count
== 1 && bad_count
> 0))
2543 Vx_resource_name
= build_string ("emacs");
2547 /* Name is partly valid. Copy it and replace the invalid characters
2548 with underscores. */
2550 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2552 for (i
= 0; i
< len
; i
++)
2554 int c
= XSTRING (new)->data
[i
];
2555 if (! ((c
>= 'a' && c
<= 'z')
2556 || (c
>= 'A' && c
<= 'Z')
2557 || (c
>= '0' && c
<= '9')
2558 || c
== '-' || c
== '_'))
2559 XSTRING (new)->data
[i
] = '_';
2564 extern char *x_get_string_resource ();
2566 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2567 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2568 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2569 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2570 the name specified by the `-name' or `-rn' command-line arguments.\n\
2572 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2573 class, respectively. You must specify both of them or neither.\n\
2574 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2575 and the class is `Emacs.CLASS.SUBCLASS'.")
2576 (attribute
, class, component
, subclass
)
2577 Lisp_Object attribute
, class, component
, subclass
;
2579 register char *value
;
2585 CHECK_STRING (attribute
, 0);
2586 CHECK_STRING (class, 0);
2588 if (!NILP (component
))
2589 CHECK_STRING (component
, 1);
2590 if (!NILP (subclass
))
2591 CHECK_STRING (subclass
, 2);
2592 if (NILP (component
) != NILP (subclass
))
2593 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2595 validate_x_resource_name ();
2597 /* Allocate space for the components, the dots which separate them,
2598 and the final '\0'. Make them big enough for the worst case. */
2599 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2600 + (STRINGP (component
)
2601 ? STRING_BYTES (XSTRING (component
)) : 0)
2602 + STRING_BYTES (XSTRING (attribute
))
2605 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2606 + STRING_BYTES (XSTRING (class))
2607 + (STRINGP (subclass
)
2608 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2611 /* Start with emacs.FRAMENAME for the name (the specific one)
2612 and with `Emacs' for the class key (the general one). */
2613 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2614 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2616 strcat (class_key
, ".");
2617 strcat (class_key
, XSTRING (class)->data
);
2619 if (!NILP (component
))
2621 strcat (class_key
, ".");
2622 strcat (class_key
, XSTRING (subclass
)->data
);
2624 strcat (name_key
, ".");
2625 strcat (name_key
, XSTRING (component
)->data
);
2628 strcat (name_key
, ".");
2629 strcat (name_key
, XSTRING (attribute
)->data
);
2631 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2632 name_key
, class_key
);
2634 if (value
!= (char *) 0)
2635 return build_string (value
);
2640 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2643 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2644 struct x_display_info
*dpyinfo
;
2645 Lisp_Object attribute
, class, component
, subclass
;
2647 register char *value
;
2651 CHECK_STRING (attribute
, 0);
2652 CHECK_STRING (class, 0);
2654 if (!NILP (component
))
2655 CHECK_STRING (component
, 1);
2656 if (!NILP (subclass
))
2657 CHECK_STRING (subclass
, 2);
2658 if (NILP (component
) != NILP (subclass
))
2659 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2661 validate_x_resource_name ();
2663 /* Allocate space for the components, the dots which separate them,
2664 and the final '\0'. Make them big enough for the worst case. */
2665 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2666 + (STRINGP (component
)
2667 ? STRING_BYTES (XSTRING (component
)) : 0)
2668 + STRING_BYTES (XSTRING (attribute
))
2671 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2672 + STRING_BYTES (XSTRING (class))
2673 + (STRINGP (subclass
)
2674 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2677 /* Start with emacs.FRAMENAME for the name (the specific one)
2678 and with `Emacs' for the class key (the general one). */
2679 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2680 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2682 strcat (class_key
, ".");
2683 strcat (class_key
, XSTRING (class)->data
);
2685 if (!NILP (component
))
2687 strcat (class_key
, ".");
2688 strcat (class_key
, XSTRING (subclass
)->data
);
2690 strcat (name_key
, ".");
2691 strcat (name_key
, XSTRING (component
)->data
);
2694 strcat (name_key
, ".");
2695 strcat (name_key
, XSTRING (attribute
)->data
);
2697 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2699 if (value
!= (char *) 0)
2700 return build_string (value
);
2705 /* Used when C code wants a resource value. */
2708 x_get_resource_string (attribute
, class)
2709 char *attribute
, *class;
2713 struct frame
*sf
= SELECTED_FRAME ();
2715 /* Allocate space for the components, the dots which separate them,
2716 and the final '\0'. */
2717 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2718 + strlen (attribute
) + 2);
2719 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2720 + strlen (class) + 2);
2722 sprintf (name_key
, "%s.%s",
2723 XSTRING (Vinvocation_name
)->data
,
2725 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2727 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2728 name_key
, class_key
);
2731 /* Types we might convert a resource string into. */
2741 /* Return the value of parameter PARAM.
2743 First search ALIST, then Vdefault_frame_alist, then the X defaults
2744 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2746 Convert the resource to the type specified by desired_type.
2748 If no default is specified, return Qunbound. If you call
2749 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2750 and don't let it get stored in any Lisp-visible variables! */
2753 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2754 struct x_display_info
*dpyinfo
;
2755 Lisp_Object alist
, param
;
2758 enum resource_types type
;
2760 register Lisp_Object tem
;
2762 tem
= Fassq (param
, alist
);
2764 tem
= Fassq (param
, Vdefault_frame_alist
);
2770 tem
= display_x_get_resource (dpyinfo
,
2771 build_string (attribute
),
2772 build_string (class),
2780 case RES_TYPE_NUMBER
:
2781 return make_number (atoi (XSTRING (tem
)->data
));
2783 case RES_TYPE_FLOAT
:
2784 return make_float (atof (XSTRING (tem
)->data
));
2786 case RES_TYPE_BOOLEAN
:
2787 tem
= Fdowncase (tem
);
2788 if (!strcmp (XSTRING (tem
)->data
, "on")
2789 || !strcmp (XSTRING (tem
)->data
, "true"))
2794 case RES_TYPE_STRING
:
2797 case RES_TYPE_SYMBOL
:
2798 /* As a special case, we map the values `true' and `on'
2799 to Qt, and `false' and `off' to Qnil. */
2802 lower
= Fdowncase (tem
);
2803 if (!strcmp (XSTRING (lower
)->data
, "on")
2804 || !strcmp (XSTRING (lower
)->data
, "true"))
2806 else if (!strcmp (XSTRING (lower
)->data
, "off")
2807 || !strcmp (XSTRING (lower
)->data
, "false"))
2810 return Fintern (tem
, Qnil
);
2823 /* Like x_get_arg, but also record the value in f->param_alist. */
2826 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2828 Lisp_Object alist
, param
;
2831 enum resource_types type
;
2835 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2836 attribute
, class, type
);
2838 store_frame_param (f
, param
, value
);
2843 /* Record in frame F the specified or default value according to ALIST
2844 of the parameter named PROP (a Lisp symbol).
2845 If no value is specified for PROP, look for an X default for XPROP
2846 on the frame named NAME.
2847 If that is not found either, use the value DEFLT. */
2850 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2857 enum resource_types type
;
2861 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2862 if (EQ (tem
, Qunbound
))
2864 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2869 /* Record in frame F the specified or default value according to ALIST
2870 of the parameter named PROP (a Lisp symbol). If no value is
2871 specified for PROP, look for an X default for XPROP on the frame
2872 named NAME. If that is not found either, use the value DEFLT. */
2875 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2884 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2887 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2888 if (EQ (tem
, Qunbound
))
2890 #ifdef USE_TOOLKIT_SCROLL_BARS
2892 /* See if an X resource for the scroll bar color has been
2894 tem
= display_x_get_resource (dpyinfo
,
2895 build_string (foreground_p
2899 build_string ("verticalScrollBar"),
2903 /* If nothing has been specified, scroll bars will use a
2904 toolkit-dependent default. Because these defaults are
2905 difficult to get at without actually creating a scroll
2906 bar, use nil to indicate that no color has been
2911 #else /* not USE_TOOLKIT_SCROLL_BARS */
2915 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2918 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2924 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2925 "Parse an X-style geometry string STRING.\n\
2926 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2927 The properties returned may include `top', `left', `height', and `width'.\n\
2928 The value of `left' or `top' may be an integer,\n\
2929 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2930 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2935 unsigned int width
, height
;
2938 CHECK_STRING (string
, 0);
2940 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2941 &x
, &y
, &width
, &height
);
2944 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2945 error ("Must specify both x and y position, or neither");
2949 if (geometry
& XValue
)
2951 Lisp_Object element
;
2953 if (x
>= 0 && (geometry
& XNegative
))
2954 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2955 else if (x
< 0 && ! (geometry
& XNegative
))
2956 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2958 element
= Fcons (Qleft
, make_number (x
));
2959 result
= Fcons (element
, result
);
2962 if (geometry
& YValue
)
2964 Lisp_Object element
;
2966 if (y
>= 0 && (geometry
& YNegative
))
2967 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2968 else if (y
< 0 && ! (geometry
& YNegative
))
2969 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2971 element
= Fcons (Qtop
, make_number (y
));
2972 result
= Fcons (element
, result
);
2975 if (geometry
& WidthValue
)
2976 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2977 if (geometry
& HeightValue
)
2978 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2983 /* Calculate the desired size and position of this window,
2984 and return the flags saying which aspects were specified.
2986 This function does not make the coordinates positive. */
2988 #define DEFAULT_ROWS 40
2989 #define DEFAULT_COLS 80
2992 x_figure_window_size (f
, parms
)
2996 register Lisp_Object tem0
, tem1
, tem2
;
2997 long window_prompting
= 0;
2998 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3000 /* Default values if we fall through.
3001 Actually, if that happens we should get
3002 window manager prompting. */
3003 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3004 f
->height
= DEFAULT_ROWS
;
3005 /* Window managers expect that if program-specified
3006 positions are not (0,0), they're intentional, not defaults. */
3007 f
->output_data
.x
->top_pos
= 0;
3008 f
->output_data
.x
->left_pos
= 0;
3010 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3011 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3012 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3013 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3015 if (!EQ (tem0
, Qunbound
))
3017 CHECK_NUMBER (tem0
, 0);
3018 f
->height
= XINT (tem0
);
3020 if (!EQ (tem1
, Qunbound
))
3022 CHECK_NUMBER (tem1
, 0);
3023 SET_FRAME_WIDTH (f
, XINT (tem1
));
3025 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3026 window_prompting
|= USSize
;
3028 window_prompting
|= PSize
;
3031 f
->output_data
.x
->vertical_scroll_bar_extra
3032 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3034 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3035 f
->output_data
.x
->flags_areas_extra
3036 = FRAME_FLAGS_AREA_WIDTH (f
);
3037 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3038 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3040 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3041 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3042 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3043 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3045 if (EQ (tem0
, Qminus
))
3047 f
->output_data
.x
->top_pos
= 0;
3048 window_prompting
|= YNegative
;
3050 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3051 && CONSP (XCDR (tem0
))
3052 && INTEGERP (XCAR (XCDR (tem0
))))
3054 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3055 window_prompting
|= YNegative
;
3057 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3058 && CONSP (XCDR (tem0
))
3059 && INTEGERP (XCAR (XCDR (tem0
))))
3061 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3063 else if (EQ (tem0
, Qunbound
))
3064 f
->output_data
.x
->top_pos
= 0;
3067 CHECK_NUMBER (tem0
, 0);
3068 f
->output_data
.x
->top_pos
= XINT (tem0
);
3069 if (f
->output_data
.x
->top_pos
< 0)
3070 window_prompting
|= YNegative
;
3073 if (EQ (tem1
, Qminus
))
3075 f
->output_data
.x
->left_pos
= 0;
3076 window_prompting
|= XNegative
;
3078 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3079 && CONSP (XCDR (tem1
))
3080 && INTEGERP (XCAR (XCDR (tem1
))))
3082 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3083 window_prompting
|= XNegative
;
3085 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3086 && CONSP (XCDR (tem1
))
3087 && INTEGERP (XCAR (XCDR (tem1
))))
3089 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3091 else if (EQ (tem1
, Qunbound
))
3092 f
->output_data
.x
->left_pos
= 0;
3095 CHECK_NUMBER (tem1
, 0);
3096 f
->output_data
.x
->left_pos
= XINT (tem1
);
3097 if (f
->output_data
.x
->left_pos
< 0)
3098 window_prompting
|= XNegative
;
3101 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3102 window_prompting
|= USPosition
;
3104 window_prompting
|= PPosition
;
3107 return window_prompting
;
3110 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3113 XSetWMProtocols (dpy
, w
, protocols
, count
)
3120 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3121 if (prop
== None
) return False
;
3122 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3123 (unsigned char *) protocols
, count
);
3126 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3128 #ifdef USE_X_TOOLKIT
3130 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3131 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3132 already be present because of the toolkit (Motif adds some of them,
3133 for example, but Xt doesn't). */
3136 hack_wm_protocols (f
, widget
)
3140 Display
*dpy
= XtDisplay (widget
);
3141 Window w
= XtWindow (widget
);
3142 int need_delete
= 1;
3148 Atom type
, *atoms
= 0;
3150 unsigned long nitems
= 0;
3151 unsigned long bytes_after
;
3153 if ((XGetWindowProperty (dpy
, w
,
3154 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3155 (long)0, (long)100, False
, XA_ATOM
,
3156 &type
, &format
, &nitems
, &bytes_after
,
3157 (unsigned char **) &atoms
)
3159 && format
== 32 && type
== XA_ATOM
)
3163 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3165 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3167 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3170 if (atoms
) XFree ((char *) atoms
);
3176 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3178 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3180 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3182 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3183 XA_ATOM
, 32, PropModeAppend
,
3184 (unsigned char *) props
, count
);
3192 /* Support routines for XIC (X Input Context). */
3196 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3197 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3200 /* Supported XIM styles, ordered by preferenc. */
3202 static XIMStyle supported_xim_styles
[] =
3204 XIMPreeditPosition
| XIMStatusArea
,
3205 XIMPreeditPosition
| XIMStatusNothing
,
3206 XIMPreeditPosition
| XIMStatusNone
,
3207 XIMPreeditNothing
| XIMStatusArea
,
3208 XIMPreeditNothing
| XIMStatusNothing
,
3209 XIMPreeditNothing
| XIMStatusNone
,
3210 XIMPreeditNone
| XIMStatusArea
,
3211 XIMPreeditNone
| XIMStatusNothing
,
3212 XIMPreeditNone
| XIMStatusNone
,
3217 /* Create an X fontset on frame F with base font name
3221 xic_create_xfontset (f
, base_fontname
)
3223 char *base_fontname
;
3226 char **missing_list
;
3230 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3231 base_fontname
, &missing_list
,
3232 &missing_count
, &def_string
);
3234 XFreeStringList (missing_list
);
3236 /* No need to free def_string. */
3241 /* Value is the best input style, given user preferences USER (already
3242 checked to be supported by Emacs), and styles supported by the
3243 input method XIM. */
3246 best_xim_style (user
, xim
)
3252 for (i
= 0; i
< user
->count_styles
; ++i
)
3253 for (j
= 0; j
< xim
->count_styles
; ++j
)
3254 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3255 return user
->supported_styles
[i
];
3257 /* Return the default style. */
3258 return XIMPreeditNothing
| XIMStatusNothing
;
3261 /* Create XIC for frame F. */
3264 create_frame_xic (f
)
3269 XFontSet xfs
= NULL
;
3270 static XIMStyle xic_style
;
3275 xim
= FRAME_X_XIM (f
);
3280 XVaNestedList preedit_attr
;
3281 XVaNestedList status_attr
;
3282 char *base_fontname
;
3285 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3286 spot
.x
= 0; spot
.y
= 1;
3287 /* Create X fontset. */
3288 fontset
= FRAME_FONTSET (f
);
3290 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3293 /* Determine the base fontname from the ASCII font name of
3295 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3296 char *p
= ascii_font
;
3299 for (i
= 0; *p
; p
++)
3302 /* As the font name doesn't conform to XLFD, we can't
3303 modify it to get a suitable base fontname for the
3305 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3308 int len
= strlen (ascii_font
) + 1;
3311 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3320 base_fontname
= (char *) alloca (len
);
3321 bzero (base_fontname
, len
);
3322 strcpy (base_fontname
, "-*-*-");
3323 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3324 strcat (base_fontname
, "*-*-*-*-*-*-*");
3327 xfs
= xic_create_xfontset (f
, base_fontname
);
3329 /* Determine XIC style. */
3332 XIMStyles supported_list
;
3333 supported_list
.count_styles
= (sizeof supported_xim_styles
3334 / sizeof supported_xim_styles
[0]);
3335 supported_list
.supported_styles
= supported_xim_styles
;
3336 xic_style
= best_xim_style (&supported_list
,
3337 FRAME_X_XIM_STYLES (f
));
3340 preedit_attr
= XVaCreateNestedList (0,
3343 FRAME_FOREGROUND_PIXEL (f
),
3345 FRAME_BACKGROUND_PIXEL (f
),
3346 (xic_style
& XIMPreeditPosition
3351 status_attr
= XVaCreateNestedList (0,
3357 FRAME_FOREGROUND_PIXEL (f
),
3359 FRAME_BACKGROUND_PIXEL (f
),
3362 xic
= XCreateIC (xim
,
3363 XNInputStyle
, xic_style
,
3364 XNClientWindow
, FRAME_X_WINDOW(f
),
3365 XNFocusWindow
, FRAME_X_WINDOW(f
),
3366 XNStatusAttributes
, status_attr
,
3367 XNPreeditAttributes
, preedit_attr
,
3369 XFree (preedit_attr
);
3370 XFree (status_attr
);
3373 FRAME_XIC (f
) = xic
;
3374 FRAME_XIC_STYLE (f
) = xic_style
;
3375 FRAME_XIC_FONTSET (f
) = xfs
;
3379 /* Destroy XIC and free XIC fontset of frame F, if any. */
3385 if (FRAME_XIC (f
) == NULL
)
3388 XDestroyIC (FRAME_XIC (f
));
3389 if (FRAME_XIC_FONTSET (f
))
3390 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3392 FRAME_XIC (f
) = NULL
;
3393 FRAME_XIC_FONTSET (f
) = NULL
;
3397 /* Place preedit area for XIC of window W's frame to specified
3398 pixel position X/Y. X and Y are relative to window W. */
3401 xic_set_preeditarea (w
, x
, y
)
3405 struct frame
*f
= XFRAME (w
->frame
);
3409 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3410 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3411 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3412 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3417 /* Place status area for XIC in bottom right corner of frame F.. */
3420 xic_set_statusarea (f
)
3423 XIC xic
= FRAME_XIC (f
);
3428 /* Negotiate geometry of status area. If input method has existing
3429 status area, use its current size. */
3430 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3431 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3432 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3435 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3436 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3439 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3441 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3442 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3446 area
.width
= needed
->width
;
3447 area
.height
= needed
->height
;
3448 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3449 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3450 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3453 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3454 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3459 /* Set X fontset for XIC of frame F, using base font name
3460 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3463 xic_set_xfontset (f
, base_fontname
)
3465 char *base_fontname
;
3470 xfs
= xic_create_xfontset (f
, base_fontname
);
3472 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3473 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3474 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3475 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3476 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3479 if (FRAME_XIC_FONTSET (f
))
3480 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3481 FRAME_XIC_FONTSET (f
) = xfs
;
3484 #endif /* HAVE_X_I18N */
3488 #ifdef USE_X_TOOLKIT
3490 /* Create and set up the X widget for frame F. */
3493 x_window (f
, window_prompting
, minibuffer_only
)
3495 long window_prompting
;
3496 int minibuffer_only
;
3498 XClassHint class_hints
;
3499 XSetWindowAttributes attributes
;
3500 unsigned long attribute_mask
;
3501 Widget shell_widget
;
3503 Widget frame_widget
;
3509 /* Use the resource name as the top-level widget name
3510 for looking up resources. Make a non-Lisp copy
3511 for the window manager, so GC relocation won't bother it.
3513 Elsewhere we specify the window name for the window manager. */
3516 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3517 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3518 strcpy (f
->namebuf
, str
);
3522 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3523 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3524 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3525 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3526 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3527 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3528 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3529 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3530 applicationShellWidgetClass
,
3531 FRAME_X_DISPLAY (f
), al
, ac
);
3533 f
->output_data
.x
->widget
= shell_widget
;
3534 /* maybe_set_screen_title_format (shell_widget); */
3536 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3537 (widget_value
*) NULL
,
3538 shell_widget
, False
,
3542 (lw_callback
) NULL
);
3545 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3546 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3547 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3548 XtSetValues (pane_widget
, al
, ac
);
3549 f
->output_data
.x
->column_widget
= pane_widget
;
3551 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3552 the emacs screen when changing menubar. This reduces flickering. */
3555 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3556 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3557 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3558 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3559 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3560 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3561 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3562 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3563 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3566 f
->output_data
.x
->edit_widget
= frame_widget
;
3568 XtManageChild (frame_widget
);
3570 /* Do some needed geometry management. */
3573 char *tem
, shell_position
[32];
3576 int extra_borders
= 0;
3578 = (f
->output_data
.x
->menubar_widget
3579 ? (f
->output_data
.x
->menubar_widget
->core
.height
3580 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3583 #if 0 /* Experimentally, we now get the right results
3584 for -geometry -0-0 without this. 24 Aug 96, rms. */
3585 if (FRAME_EXTERNAL_MENU_BAR (f
))
3588 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3589 menubar_size
+= ibw
;
3593 f
->output_data
.x
->menubar_height
= menubar_size
;
3596 /* Motif seems to need this amount added to the sizes
3597 specified for the shell widget. The Athena/Lucid widgets don't.
3598 Both conclusions reached experimentally. -- rms. */
3599 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3600 &extra_borders
, NULL
);
3604 /* Convert our geometry parameters into a geometry string
3606 Note that we do not specify here whether the position
3607 is a user-specified or program-specified one.
3608 We pass that information later, in x_wm_set_size_hints. */
3610 int left
= f
->output_data
.x
->left_pos
;
3611 int xneg
= window_prompting
& XNegative
;
3612 int top
= f
->output_data
.x
->top_pos
;
3613 int yneg
= window_prompting
& YNegative
;
3619 if (window_prompting
& USPosition
)
3620 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3621 PIXEL_WIDTH (f
) + extra_borders
,
3622 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3623 (xneg
? '-' : '+'), left
,
3624 (yneg
? '-' : '+'), top
);
3626 sprintf (shell_position
, "=%dx%d",
3627 PIXEL_WIDTH (f
) + extra_borders
,
3628 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3631 len
= strlen (shell_position
) + 1;
3632 /* We don't free this because we don't know whether
3633 it is safe to free it while the frame exists.
3634 It isn't worth the trouble of arranging to free it
3635 when the frame is deleted. */
3636 tem
= (char *) xmalloc (len
);
3637 strncpy (tem
, shell_position
, len
);
3638 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3639 XtSetValues (shell_widget
, al
, ac
);
3642 XtManageChild (pane_widget
);
3643 XtRealizeWidget (shell_widget
);
3645 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3647 validate_x_resource_name ();
3649 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3650 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3651 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3654 FRAME_XIC (f
) = NULL
;
3656 create_frame_xic (f
);
3660 f
->output_data
.x
->wm_hints
.input
= True
;
3661 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3662 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3663 &f
->output_data
.x
->wm_hints
);
3665 hack_wm_protocols (f
, shell_widget
);
3668 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3671 /* Do a stupid property change to force the server to generate a
3672 PropertyNotify event so that the event_stream server timestamp will
3673 be initialized to something relevant to the time we created the window.
3675 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3676 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3677 XA_ATOM
, 32, PropModeAppend
,
3678 (unsigned char*) NULL
, 0);
3680 /* Make all the standard events reach the Emacs frame. */
3681 attributes
.event_mask
= STANDARD_EVENT_SET
;
3686 /* XIM server might require some X events. */
3687 unsigned long fevent
= NoEventMask
;
3688 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3689 attributes
.event_mask
|= fevent
;
3691 #endif /* HAVE_X_I18N */
3693 attribute_mask
= CWEventMask
;
3694 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3695 attribute_mask
, &attributes
);
3697 XtMapWidget (frame_widget
);
3699 /* x_set_name normally ignores requests to set the name if the
3700 requested name is the same as the current name. This is the one
3701 place where that assumption isn't correct; f->name is set, but
3702 the X server hasn't been told. */
3705 int explicit = f
->explicit_name
;
3707 f
->explicit_name
= 0;
3710 x_set_name (f
, name
, explicit);
3713 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3714 f
->output_data
.x
->text_cursor
);
3718 /* This is a no-op, except under Motif. Make sure main areas are
3719 set to something reasonable, in case we get an error later. */
3720 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3723 #else /* not USE_X_TOOLKIT */
3725 /* Create and set up the X window for frame F. */
3732 XClassHint class_hints
;
3733 XSetWindowAttributes attributes
;
3734 unsigned long attribute_mask
;
3736 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3737 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3738 attributes
.bit_gravity
= StaticGravity
;
3739 attributes
.backing_store
= NotUseful
;
3740 attributes
.save_under
= True
;
3741 attributes
.event_mask
= STANDARD_EVENT_SET
;
3742 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3743 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3748 = XCreateWindow (FRAME_X_DISPLAY (f
),
3749 f
->output_data
.x
->parent_desc
,
3750 f
->output_data
.x
->left_pos
,
3751 f
->output_data
.x
->top_pos
,
3752 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3753 f
->output_data
.x
->border_width
,
3754 CopyFromParent
, /* depth */
3755 InputOutput
, /* class */
3757 attribute_mask
, &attributes
);
3761 create_frame_xic (f
);
3764 /* XIM server might require some X events. */
3765 unsigned long fevent
= NoEventMask
;
3766 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3767 attributes
.event_mask
|= fevent
;
3768 attribute_mask
= CWEventMask
;
3769 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3770 attribute_mask
, &attributes
);
3773 #endif /* HAVE_X_I18N */
3775 validate_x_resource_name ();
3777 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3778 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3779 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3781 /* The menubar is part of the ordinary display;
3782 it does not count in addition to the height of the window. */
3783 f
->output_data
.x
->menubar_height
= 0;
3785 /* This indicates that we use the "Passive Input" input model.
3786 Unless we do this, we don't get the Focus{In,Out} events that we
3787 need to draw the cursor correctly. Accursed bureaucrats.
3788 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3790 f
->output_data
.x
->wm_hints
.input
= True
;
3791 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3792 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3793 &f
->output_data
.x
->wm_hints
);
3794 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3796 /* Request "save yourself" and "delete window" commands from wm. */
3799 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3800 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3801 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3804 /* x_set_name normally ignores requests to set the name if the
3805 requested name is the same as the current name. This is the one
3806 place where that assumption isn't correct; f->name is set, but
3807 the X server hasn't been told. */
3810 int explicit = f
->explicit_name
;
3812 f
->explicit_name
= 0;
3815 x_set_name (f
, name
, explicit);
3818 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3819 f
->output_data
.x
->text_cursor
);
3823 if (FRAME_X_WINDOW (f
) == 0)
3824 error ("Unable to create window");
3827 #endif /* not USE_X_TOOLKIT */
3829 /* Handle the icon stuff for this window. Perhaps later we might
3830 want an x_set_icon_position which can be called interactively as
3838 Lisp_Object icon_x
, icon_y
;
3839 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3841 /* Set the position of the icon. Note that twm groups all
3842 icons in an icon window. */
3843 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3844 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3845 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3847 CHECK_NUMBER (icon_x
, 0);
3848 CHECK_NUMBER (icon_y
, 0);
3850 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3851 error ("Both left and top icon corners of icon must be specified");
3855 if (! EQ (icon_x
, Qunbound
))
3856 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3858 /* Start up iconic or window? */
3859 x_wm_set_window_state
3860 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3865 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3872 /* Make the GCs needed for this window, setting the
3873 background, border and mouse colors; also create the
3874 mouse cursor and the gray border tile. */
3876 static char cursor_bits
[] =
3878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3888 XGCValues gc_values
;
3892 /* Create the GCs of this frame.
3893 Note that many default values are used. */
3896 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3897 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3898 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3899 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3900 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3902 GCLineWidth
| GCFont
3903 | GCForeground
| GCBackground
,
3906 /* Reverse video style. */
3907 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3908 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3909 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3911 GCFont
| GCForeground
| GCBackground
3915 /* Cursor has cursor-color background, background-color foreground. */
3916 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3917 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3918 gc_values
.fill_style
= FillOpaqueStippled
;
3920 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3921 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3922 cursor_bits
, 16, 16);
3923 f
->output_data
.x
->cursor_gc
3924 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3925 (GCFont
| GCForeground
| GCBackground
3926 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3930 f
->output_data
.x
->white_relief
.gc
= 0;
3931 f
->output_data
.x
->black_relief
.gc
= 0;
3933 /* Create the gray border tile used when the pointer is not in
3934 the frame. Since this depends on the frame's pixel values,
3935 this must be done on a per-frame basis. */
3936 f
->output_data
.x
->border_tile
3937 = (XCreatePixmapFromBitmapData
3938 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3939 gray_bits
, gray_width
, gray_height
,
3940 f
->output_data
.x
->foreground_pixel
,
3941 f
->output_data
.x
->background_pixel
,
3942 DefaultDepth (FRAME_X_DISPLAY (f
),
3943 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3948 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3950 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3951 Returns an Emacs frame object.\n\
3952 ALIST is an alist of frame parameters.\n\
3953 If the parameters specify that the frame should not have a minibuffer,\n\
3954 and do not specify a specific minibuffer window to use,\n\
3955 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3956 be shared by the new frame.\n\
3958 This function is an internal primitive--use `make-frame' instead.")
3963 Lisp_Object frame
, tem
;
3965 int minibuffer_only
= 0;
3966 long window_prompting
= 0;
3968 int count
= specpdl_ptr
- specpdl
;
3969 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3970 Lisp_Object display
;
3971 struct x_display_info
*dpyinfo
= NULL
;
3977 /* Use this general default value to start with
3978 until we know if this frame has a specified name. */
3979 Vx_resource_name
= Vinvocation_name
;
3981 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3982 if (EQ (display
, Qunbound
))
3984 dpyinfo
= check_x_display_info (display
);
3986 kb
= dpyinfo
->kboard
;
3988 kb
= &the_only_kboard
;
3991 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3993 && ! EQ (name
, Qunbound
)
3995 error ("Invalid frame name--not a string or nil");
3998 Vx_resource_name
= name
;
4000 /* See if parent window is specified. */
4001 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4002 if (EQ (parent
, Qunbound
))
4004 if (! NILP (parent
))
4005 CHECK_NUMBER (parent
, 0);
4007 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4008 /* No need to protect DISPLAY because that's not used after passing
4009 it to make_frame_without_minibuffer. */
4011 GCPRO4 (parms
, parent
, name
, frame
);
4012 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4014 if (EQ (tem
, Qnone
) || NILP (tem
))
4015 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4016 else if (EQ (tem
, Qonly
))
4018 f
= make_minibuffer_frame ();
4019 minibuffer_only
= 1;
4021 else if (WINDOWP (tem
))
4022 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4026 XSETFRAME (frame
, f
);
4028 /* Note that X Windows does support scroll bars. */
4029 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4031 f
->output_method
= output_x_window
;
4032 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4033 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4034 f
->output_data
.x
->icon_bitmap
= -1;
4035 f
->output_data
.x
->fontset
= -1;
4036 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4037 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4040 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4042 if (! STRINGP (f
->icon_name
))
4043 f
->icon_name
= Qnil
;
4045 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4047 FRAME_KBOARD (f
) = kb
;
4050 /* These colors will be set anyway later, but it's important
4051 to get the color reference counts right, so initialize them! */
4054 struct gcpro gcpro1
;
4056 black
= build_string ("black");
4058 f
->output_data
.x
->foreground_pixel
4059 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4060 f
->output_data
.x
->background_pixel
4061 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4062 f
->output_data
.x
->cursor_pixel
4063 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4064 f
->output_data
.x
->cursor_foreground_pixel
4065 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4066 f
->output_data
.x
->border_pixel
4067 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4068 f
->output_data
.x
->mouse_pixel
4069 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4073 /* Specify the parent under which to make this X window. */
4077 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4078 f
->output_data
.x
->explicit_parent
= 1;
4082 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4083 f
->output_data
.x
->explicit_parent
= 0;
4086 /* Set the name; the functions to which we pass f expect the name to
4088 if (EQ (name
, Qunbound
) || NILP (name
))
4090 f
->name
= build_string (dpyinfo
->x_id_name
);
4091 f
->explicit_name
= 0;
4096 f
->explicit_name
= 1;
4097 /* use the frame's title when getting resources for this frame. */
4098 specbind (Qx_resource_name
, name
);
4101 /* Extract the window parameters from the supplied values
4102 that are needed to determine window geometry. */
4106 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4109 /* First, try whatever font the caller has specified. */
4112 tem
= Fquery_fontset (font
, Qnil
);
4114 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4116 font
= x_new_font (f
, XSTRING (font
)->data
);
4119 /* Try out a font which we hope has bold and italic variations. */
4120 if (!STRINGP (font
))
4121 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4122 if (!STRINGP (font
))
4123 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4124 if (! STRINGP (font
))
4125 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4126 if (! STRINGP (font
))
4127 /* This was formerly the first thing tried, but it finds too many fonts
4128 and takes too long. */
4129 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4130 /* If those didn't work, look for something which will at least work. */
4131 if (! STRINGP (font
))
4132 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4134 if (! STRINGP (font
))
4135 font
= build_string ("fixed");
4137 x_default_parameter (f
, parms
, Qfont
, font
,
4138 "font", "Font", RES_TYPE_STRING
);
4142 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4143 whereby it fails to get any font. */
4144 xlwmenu_default_font
= f
->output_data
.x
->font
;
4147 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4148 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4150 /* This defaults to 2 in order to match xterm. We recognize either
4151 internalBorderWidth or internalBorder (which is what xterm calls
4153 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4157 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4158 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4159 if (! EQ (value
, Qunbound
))
4160 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4163 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4164 "internalBorderWidth", "internalBorderWidth",
4166 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4167 "verticalScrollBars", "ScrollBars",
4170 /* Also do the stuff which must be set before the window exists. */
4171 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4172 "foreground", "Foreground", RES_TYPE_STRING
);
4173 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4174 "background", "Background", RES_TYPE_STRING
);
4175 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4176 "pointerColor", "Foreground", RES_TYPE_STRING
);
4177 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4178 "cursorColor", "Foreground", RES_TYPE_STRING
);
4179 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4180 "borderColor", "BorderColor", RES_TYPE_STRING
);
4181 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4182 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4183 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4184 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4186 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4187 "scrollBarForeground",
4188 "ScrollBarForeground", 1);
4189 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4190 "scrollBarBackground",
4191 "ScrollBarBackground", 0);
4193 /* Init faces before x_default_parameter is called for scroll-bar
4194 parameters because that function calls x_set_scroll_bar_width,
4195 which calls change_frame_size, which calls Fset_window_buffer,
4196 which runs hooks, which call Fvertical_motion. At the end, we
4197 end up in init_iterator with a null face cache, which should not
4199 init_frame_faces (f
);
4201 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4202 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4203 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4204 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4205 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4206 "bufferPredicate", "BufferPredicate",
4208 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4209 "title", "Title", RES_TYPE_STRING
);
4211 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4212 window_prompting
= x_figure_window_size (f
, parms
);
4214 if (window_prompting
& XNegative
)
4216 if (window_prompting
& YNegative
)
4217 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4219 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4223 if (window_prompting
& YNegative
)
4224 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4226 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4229 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4231 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4232 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4234 /* Create the X widget or window. Add the tool-bar height to the
4235 initial frame height so that the user gets a text display area of
4236 the size he specified with -g or via .Xdefaults. Later changes
4237 of the tool-bar height don't change the frame size. This is done
4238 so that users can create tall Emacs frames without having to
4239 guess how tall the tool-bar will get. */
4240 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
4242 #ifdef USE_X_TOOLKIT
4243 x_window (f
, window_prompting
, minibuffer_only
);
4251 /* Now consider the frame official. */
4252 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4253 Vframe_list
= Fcons (frame
, Vframe_list
);
4255 /* We need to do this after creating the X window, so that the
4256 icon-creation functions can say whose icon they're describing. */
4257 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4258 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4260 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4261 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4262 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4263 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4264 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4265 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4266 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4267 "scrollBarWidth", "ScrollBarWidth",
4270 /* Dimensions, especially f->height, must be done via change_frame_size.
4271 Change will not be effected unless different from the current
4276 SET_FRAME_WIDTH (f
, 0);
4277 change_frame_size (f
, height
, width
, 1, 0, 0);
4279 #ifdef USE_X_TOOLKIT
4280 /* Create the menu bar. */
4281 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4283 /* If this signals an error, we haven't set size hints for the
4284 frame and we didn't make it visible. */
4285 initialize_frame_menubar (f
);
4287 /* This is a no-op, except under Motif where it arranges the
4288 main window for the widgets on it. */
4289 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4290 f
->output_data
.x
->menubar_widget
,
4291 f
->output_data
.x
->edit_widget
);
4293 #endif /* USE_X_TOOLKIT */
4295 /* Tell the server what size and position, etc, we want, and how
4296 badly we want them. This should be done after we have the menu
4297 bar so that its size can be taken into account. */
4299 x_wm_set_size_hint (f
, window_prompting
, 0);
4302 /* Make the window appear on the frame and enable display, unless
4303 the caller says not to. However, with explicit parent, Emacs
4304 cannot control visibility, so don't try. */
4305 if (! f
->output_data
.x
->explicit_parent
)
4307 Lisp_Object visibility
;
4309 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4311 if (EQ (visibility
, Qunbound
))
4314 if (EQ (visibility
, Qicon
))
4315 x_iconify_frame (f
);
4316 else if (! NILP (visibility
))
4317 x_make_frame_visible (f
);
4319 /* Must have been Qnil. */
4324 return unbind_to (count
, frame
);
4327 /* FRAME is used only to get a handle on the X display. We don't pass the
4328 display info directly because we're called from frame.c, which doesn't
4329 know about that structure. */
4332 x_get_focus_frame (frame
)
4333 struct frame
*frame
;
4335 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4337 if (! dpyinfo
->x_focus_frame
)
4340 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4345 /* In certain situations, when the window manager follows a
4346 click-to-focus policy, there seems to be no way around calling
4347 XSetInputFocus to give another frame the input focus .
4349 In an ideal world, XSetInputFocus should generally be avoided so
4350 that applications don't interfere with the window manager's focus
4351 policy. But I think it's okay to use when it's clearly done
4352 following a user-command. */
4354 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4355 "Set the input focus to FRAME.\n\
4356 FRAME nil means use the selected frame.")
4360 struct frame
*f
= check_x_frame (frame
);
4361 Display
*dpy
= FRAME_X_DISPLAY (f
);
4365 count
= x_catch_errors (dpy
);
4366 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4367 RevertToParent
, CurrentTime
);
4368 x_uncatch_errors (dpy
, count
);
4375 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4376 "Internal function called by `color-defined-p', which see.")
4378 Lisp_Object color
, frame
;
4381 FRAME_PTR f
= check_x_frame (frame
);
4383 CHECK_STRING (color
, 1);
4385 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4391 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4392 "Internal function called by `color-values', which see.")
4394 Lisp_Object color
, frame
;
4397 FRAME_PTR f
= check_x_frame (frame
);
4399 CHECK_STRING (color
, 1);
4401 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4405 rgb
[0] = make_number (foo
.red
);
4406 rgb
[1] = make_number (foo
.green
);
4407 rgb
[2] = make_number (foo
.blue
);
4408 return Flist (3, rgb
);
4414 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4415 "Internal function called by `display-color-p', which see.")
4417 Lisp_Object display
;
4419 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4421 if (dpyinfo
->n_planes
<= 2)
4424 switch (dpyinfo
->visual
->class)
4437 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4439 "Return t if the X display supports shades of gray.\n\
4440 Note that color displays do support shades of gray.\n\
4441 The optional argument DISPLAY specifies which display to ask about.\n\
4442 DISPLAY should be either a frame or a display name (a string).\n\
4443 If omitted or nil, that stands for the selected frame's display.")
4445 Lisp_Object display
;
4447 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4449 if (dpyinfo
->n_planes
<= 1)
4452 switch (dpyinfo
->visual
->class)
4467 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4469 "Returns the width in pixels of the X display DISPLAY.\n\
4470 The optional argument DISPLAY specifies which display to ask about.\n\
4471 DISPLAY should be either a frame or a display name (a string).\n\
4472 If omitted or nil, that stands for the selected frame's display.")
4474 Lisp_Object display
;
4476 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4478 return make_number (dpyinfo
->width
);
4481 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4482 Sx_display_pixel_height
, 0, 1, 0,
4483 "Returns the height in pixels of the X display DISPLAY.\n\
4484 The optional argument DISPLAY specifies which display to ask about.\n\
4485 DISPLAY should be either a frame or a display name (a string).\n\
4486 If omitted or nil, that stands for the selected frame's display.")
4488 Lisp_Object display
;
4490 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4492 return make_number (dpyinfo
->height
);
4495 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4497 "Returns the number of bitplanes of the X display DISPLAY.\n\
4498 The optional argument DISPLAY specifies which display to ask about.\n\
4499 DISPLAY should be either a frame or a display name (a string).\n\
4500 If omitted or nil, that stands for the selected frame's display.")
4502 Lisp_Object display
;
4504 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4506 return make_number (dpyinfo
->n_planes
);
4509 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4511 "Returns the number of color cells of the X display DISPLAY.\n\
4512 The optional argument DISPLAY specifies which display to ask about.\n\
4513 DISPLAY should be either a frame or a display name (a string).\n\
4514 If omitted or nil, that stands for the selected frame's display.")
4516 Lisp_Object display
;
4518 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4520 return make_number (DisplayCells (dpyinfo
->display
,
4521 XScreenNumberOfScreen (dpyinfo
->screen
)));
4524 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4525 Sx_server_max_request_size
,
4527 "Returns the maximum request size of the X server of display DISPLAY.\n\
4528 The optional argument DISPLAY specifies which display to ask about.\n\
4529 DISPLAY should be either a frame or a display name (a string).\n\
4530 If omitted or nil, that stands for the selected frame's display.")
4532 Lisp_Object display
;
4534 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4536 return make_number (MAXREQUEST (dpyinfo
->display
));
4539 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4540 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4541 The optional argument DISPLAY specifies which display to ask about.\n\
4542 DISPLAY should be either a frame or a display name (a string).\n\
4543 If omitted or nil, that stands for the selected frame's display.")
4545 Lisp_Object display
;
4547 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4548 char *vendor
= ServerVendor (dpyinfo
->display
);
4550 if (! vendor
) vendor
= "";
4551 return build_string (vendor
);
4554 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4555 "Returns the version numbers of the X server of display DISPLAY.\n\
4556 The value is a list of three integers: the major and minor\n\
4557 version numbers of the X Protocol in use, and the vendor-specific release\n\
4558 number. See also the function `x-server-vendor'.\n\n\
4559 The optional argument DISPLAY specifies which display to ask about.\n\
4560 DISPLAY should be either a frame or a display name (a string).\n\
4561 If omitted or nil, that stands for the selected frame's display.")
4563 Lisp_Object display
;
4565 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4566 Display
*dpy
= dpyinfo
->display
;
4568 return Fcons (make_number (ProtocolVersion (dpy
)),
4569 Fcons (make_number (ProtocolRevision (dpy
)),
4570 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4573 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4574 "Returns the number of screens on the X server of display DISPLAY.\n\
4575 The optional argument DISPLAY specifies which display to ask about.\n\
4576 DISPLAY should be either a frame or a display name (a string).\n\
4577 If omitted or nil, that stands for the selected frame's display.")
4579 Lisp_Object display
;
4581 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4583 return make_number (ScreenCount (dpyinfo
->display
));
4586 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4587 "Returns the height in millimeters of the X display DISPLAY.\n\
4588 The optional argument DISPLAY specifies which display to ask about.\n\
4589 DISPLAY should be either a frame or a display name (a string).\n\
4590 If omitted or nil, that stands for the selected frame's display.")
4592 Lisp_Object display
;
4594 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4596 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4599 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4600 "Returns the width in millimeters of the X display DISPLAY.\n\
4601 The optional argument DISPLAY specifies which display to ask about.\n\
4602 DISPLAY should be either a frame or a display name (a string).\n\
4603 If omitted or nil, that stands for the selected frame's display.")
4605 Lisp_Object display
;
4607 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4609 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4612 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4613 Sx_display_backing_store
, 0, 1, 0,
4614 "Returns an indication of whether X display DISPLAY does backing store.\n\
4615 The value may be `always', `when-mapped', or `not-useful'.\n\
4616 The optional argument DISPLAY specifies which display to ask about.\n\
4617 DISPLAY should be either a frame or a display name (a string).\n\
4618 If omitted or nil, that stands for the selected frame's display.")
4620 Lisp_Object display
;
4622 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4625 switch (DoesBackingStore (dpyinfo
->screen
))
4628 result
= intern ("always");
4632 result
= intern ("when-mapped");
4636 result
= intern ("not-useful");
4640 error ("Strange value for BackingStore parameter of screen");
4647 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4648 Sx_display_visual_class
, 0, 1, 0,
4649 "Returns the visual class of the X display DISPLAY.\n\
4650 The value is one of the symbols `static-gray', `gray-scale',\n\
4651 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4652 The optional argument DISPLAY specifies which display to ask about.\n\
4653 DISPLAY should be either a frame or a display name (a string).\n\
4654 If omitted or nil, that stands for the selected frame's display.")
4656 Lisp_Object display
;
4658 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4661 switch (dpyinfo
->visual
->class)
4664 result
= intern ("static-gray");
4667 result
= intern ("gray-scale");
4670 result
= intern ("static-color");
4673 result
= intern ("pseudo-color");
4676 result
= intern ("true-color");
4679 result
= intern ("direct-color");
4682 error ("Display has an unknown visual class");
4689 DEFUN ("x-display-save-under", Fx_display_save_under
,
4690 Sx_display_save_under
, 0, 1, 0,
4691 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4692 The optional argument DISPLAY specifies which display to ask about.\n\
4693 DISPLAY should be either a frame or a display name (a string).\n\
4694 If omitted or nil, that stands for the selected frame's display.")
4696 Lisp_Object display
;
4698 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4700 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4708 register struct frame
*f
;
4710 return PIXEL_WIDTH (f
);
4715 register struct frame
*f
;
4717 return PIXEL_HEIGHT (f
);
4722 register struct frame
*f
;
4724 return FONT_WIDTH (f
->output_data
.x
->font
);
4729 register struct frame
*f
;
4731 return f
->output_data
.x
->line_height
;
4736 register struct frame
*f
;
4738 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4743 /************************************************************************
4745 ************************************************************************/
4748 /* Mapping visual names to visuals. */
4750 static struct visual_class
4757 {"StaticGray", StaticGray
},
4758 {"GrayScale", GrayScale
},
4759 {"StaticColor", StaticColor
},
4760 {"PseudoColor", PseudoColor
},
4761 {"TrueColor", TrueColor
},
4762 {"DirectColor", DirectColor
},
4767 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4769 /* Value is the screen number of screen SCR. This is a substitute for
4770 the X function with the same name when that doesn't exist. */
4773 XScreenNumberOfScreen (scr
)
4774 register Screen
*scr
;
4776 Display
*dpy
= scr
->display
;
4779 for (i
= 0; i
< dpy
->nscreens
; ++i
)
4780 if (scr
== dpy
->screens
[i
])
4786 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4789 /* Select the visual that should be used on display DPYINFO. Set
4790 members of DPYINFO appropriately. Called from x_term_init. */
4793 select_visual (dpyinfo
)
4794 struct x_display_info
*dpyinfo
;
4796 Display
*dpy
= dpyinfo
->display
;
4797 Screen
*screen
= dpyinfo
->screen
;
4800 /* See if a visual is specified. */
4801 value
= display_x_get_resource (dpyinfo
,
4802 build_string ("visualClass"),
4803 build_string ("VisualClass"),
4805 if (STRINGP (value
))
4807 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4808 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4809 depth, a decimal number. NAME is compared with case ignored. */
4810 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
4815 strcpy (s
, XSTRING (value
)->data
);
4816 dash
= index (s
, '-');
4819 dpyinfo
->n_planes
= atoi (dash
+ 1);
4823 /* We won't find a matching visual with depth 0, so that
4824 an error will be printed below. */
4825 dpyinfo
->n_planes
= 0;
4827 /* Determine the visual class. */
4828 for (i
= 0; visual_classes
[i
].name
; ++i
)
4829 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
4831 class = visual_classes
[i
].class;
4835 /* Look up a matching visual for the specified class. */
4837 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
4838 dpyinfo
->n_planes
, class, &vinfo
))
4839 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
4841 dpyinfo
->visual
= vinfo
.visual
;
4846 XVisualInfo
*vinfo
, vinfo_template
;
4848 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
4851 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
4853 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
4855 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
4856 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
4857 &vinfo_template
, &n_visuals
);
4859 fatal ("Can't get proper X visual info");
4861 dpyinfo
->n_planes
= vinfo
->depth
;
4862 XFree ((char *) vinfo
);
4867 /* Return the X display structure for the display named NAME.
4868 Open a new connection if necessary. */
4870 struct x_display_info
*
4871 x_display_info_for_name (name
)
4875 struct x_display_info
*dpyinfo
;
4877 CHECK_STRING (name
, 0);
4879 if (! EQ (Vwindow_system
, intern ("x")))
4880 error ("Not using X Windows");
4882 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
4884 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4887 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4892 /* Use this general default value to start with. */
4893 Vx_resource_name
= Vinvocation_name
;
4895 validate_x_resource_name ();
4897 dpyinfo
= x_term_init (name
, (unsigned char *)0,
4898 (char *) XSTRING (Vx_resource_name
)->data
);
4901 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
4904 XSETFASTINT (Vwindow_system_version
, 11);
4910 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4911 1, 3, 0, "Open a connection to an X server.\n\
4912 DISPLAY is the name of the display to connect to.\n\
4913 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4914 If the optional third arg MUST-SUCCEED is non-nil,\n\
4915 terminate Emacs if we can't open the connection.")
4916 (display
, xrm_string
, must_succeed
)
4917 Lisp_Object display
, xrm_string
, must_succeed
;
4919 unsigned char *xrm_option
;
4920 struct x_display_info
*dpyinfo
;
4922 CHECK_STRING (display
, 0);
4923 if (! NILP (xrm_string
))
4924 CHECK_STRING (xrm_string
, 1);
4926 if (! EQ (Vwindow_system
, intern ("x")))
4927 error ("Not using X Windows");
4929 if (! NILP (xrm_string
))
4930 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
4932 xrm_option
= (unsigned char *) 0;
4934 validate_x_resource_name ();
4936 /* This is what opens the connection and sets x_current_display.
4937 This also initializes many symbols, such as those used for input. */
4938 dpyinfo
= x_term_init (display
, xrm_option
,
4939 (char *) XSTRING (Vx_resource_name
)->data
);
4943 if (!NILP (must_succeed
))
4944 fatal ("Cannot connect to X server %s.\n\
4945 Check the DISPLAY environment variable or use `-d'.\n\
4946 Also use the `xhost' program to verify that it is set to permit\n\
4947 connections from your machine.\n",
4948 XSTRING (display
)->data
);
4950 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
4955 XSETFASTINT (Vwindow_system_version
, 11);
4959 DEFUN ("x-close-connection", Fx_close_connection
,
4960 Sx_close_connection
, 1, 1, 0,
4961 "Close the connection to DISPLAY's X server.\n\
4962 For DISPLAY, specify either a frame or a display name (a string).\n\
4963 If DISPLAY is nil, that stands for the selected frame's display.")
4965 Lisp_Object display
;
4967 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4970 if (dpyinfo
->reference_count
> 0)
4971 error ("Display still has frames on it");
4974 /* Free the fonts in the font table. */
4975 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4976 if (dpyinfo
->font_table
[i
].name
)
4978 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
4979 xfree (dpyinfo
->font_table
[i
].full_name
);
4980 xfree (dpyinfo
->font_table
[i
].name
);
4981 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
4984 x_destroy_all_bitmaps (dpyinfo
);
4985 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
4987 #ifdef USE_X_TOOLKIT
4988 XtCloseDisplay (dpyinfo
->display
);
4990 XCloseDisplay (dpyinfo
->display
);
4993 x_delete_display (dpyinfo
);
4999 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5000 "Return the list of display names that Emacs has connections to.")
5003 Lisp_Object tail
, result
;
5006 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5007 result
= Fcons (XCAR (XCAR (tail
)), result
);
5012 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5013 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5014 If ON is nil, allow buffering of requests.\n\
5015 Turning on synchronization prohibits the Xlib routines from buffering\n\
5016 requests and seriously degrades performance, but makes debugging much\n\
5018 The optional second argument DISPLAY specifies which display to act on.\n\
5019 DISPLAY should be either a frame or a display name (a string).\n\
5020 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5022 Lisp_Object display
, on
;
5024 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5026 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5031 /* Wait for responses to all X commands issued so far for frame F. */
5038 XSync (FRAME_X_DISPLAY (f
), False
);
5043 /***********************************************************************
5045 ***********************************************************************/
5047 /* Value is the number of elements of vector VECTOR. */
5049 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5051 /* List of supported image types. Use define_image_type to add new
5052 types. Use lookup_image_type to find a type for a given symbol. */
5054 static struct image_type
*image_types
;
5056 /* The symbol `image' which is the car of the lists used to represent
5059 extern Lisp_Object Qimage
;
5061 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5067 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5068 extern Lisp_Object QCdata
;
5069 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5070 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5071 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5073 /* Other symbols. */
5075 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5077 /* Time in seconds after which images should be removed from the cache
5078 if not displayed. */
5080 Lisp_Object Vimage_cache_eviction_delay
;
5082 /* Function prototypes. */
5084 static void define_image_type
P_ ((struct image_type
*type
));
5085 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5086 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5087 static void x_laplace
P_ ((struct frame
*, struct image
*));
5088 static void x_emboss
P_ ((struct frame
*, struct image
*));
5089 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5093 /* Define a new image type from TYPE. This adds a copy of TYPE to
5094 image_types and adds the symbol *TYPE->type to Vimage_types. */
5097 define_image_type (type
)
5098 struct image_type
*type
;
5100 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5101 The initialized data segment is read-only. */
5102 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5103 bcopy (type
, p
, sizeof *p
);
5104 p
->next
= image_types
;
5106 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5110 /* Look up image type SYMBOL, and return a pointer to its image_type
5111 structure. Value is null if SYMBOL is not a known image type. */
5113 static INLINE
struct image_type
*
5114 lookup_image_type (symbol
)
5117 struct image_type
*type
;
5119 for (type
= image_types
; type
; type
= type
->next
)
5120 if (EQ (symbol
, *type
->type
))
5127 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5128 valid image specification is a list whose car is the symbol
5129 `image', and whose rest is a property list. The property list must
5130 contain a value for key `:type'. That value must be the name of a
5131 supported image type. The rest of the property list depends on the
5135 valid_image_p (object
)
5140 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5142 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5143 struct image_type
*type
= lookup_image_type (symbol
);
5146 valid_p
= type
->valid_p (object
);
5153 /* Log error message with format string FORMAT and argument ARG.
5154 Signaling an error, e.g. when an image cannot be loaded, is not a
5155 good idea because this would interrupt redisplay, and the error
5156 message display would lead to another redisplay. This function
5157 therefore simply displays a message. */
5160 image_error (format
, arg1
, arg2
)
5162 Lisp_Object arg1
, arg2
;
5164 add_to_log (format
, arg1
, arg2
);
5169 /***********************************************************************
5170 Image specifications
5171 ***********************************************************************/
5173 enum image_value_type
5175 IMAGE_DONT_CHECK_VALUE_TYPE
,
5178 IMAGE_POSITIVE_INTEGER_VALUE
,
5179 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5181 IMAGE_INTEGER_VALUE
,
5182 IMAGE_FUNCTION_VALUE
,
5187 /* Structure used when parsing image specifications. */
5189 struct image_keyword
5191 /* Name of keyword. */
5194 /* The type of value allowed. */
5195 enum image_value_type type
;
5197 /* Non-zero means key must be present. */
5200 /* Used to recognize duplicate keywords in a property list. */
5203 /* The value that was found. */
5208 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5210 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5213 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5214 has the format (image KEYWORD VALUE ...). One of the keyword/
5215 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5216 image_keywords structures of size NKEYWORDS describing other
5217 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5220 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5222 struct image_keyword
*keywords
;
5229 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5232 plist
= XCDR (spec
);
5233 while (CONSP (plist
))
5235 Lisp_Object key
, value
;
5237 /* First element of a pair must be a symbol. */
5239 plist
= XCDR (plist
);
5243 /* There must follow a value. */
5246 value
= XCAR (plist
);
5247 plist
= XCDR (plist
);
5249 /* Find key in KEYWORDS. Error if not found. */
5250 for (i
= 0; i
< nkeywords
; ++i
)
5251 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5257 /* Record that we recognized the keyword. If a keywords
5258 was found more than once, it's an error. */
5259 keywords
[i
].value
= value
;
5260 ++keywords
[i
].count
;
5262 if (keywords
[i
].count
> 1)
5265 /* Check type of value against allowed type. */
5266 switch (keywords
[i
].type
)
5268 case IMAGE_STRING_VALUE
:
5269 if (!STRINGP (value
))
5273 case IMAGE_SYMBOL_VALUE
:
5274 if (!SYMBOLP (value
))
5278 case IMAGE_POSITIVE_INTEGER_VALUE
:
5279 if (!INTEGERP (value
) || XINT (value
) <= 0)
5283 case IMAGE_ASCENT_VALUE
:
5284 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5286 else if (INTEGERP (value
)
5287 && XINT (value
) >= 0
5288 && XINT (value
) <= 100)
5292 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5293 if (!INTEGERP (value
) || XINT (value
) < 0)
5297 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5300 case IMAGE_FUNCTION_VALUE
:
5301 value
= indirect_function (value
);
5303 || COMPILEDP (value
)
5304 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5308 case IMAGE_NUMBER_VALUE
:
5309 if (!INTEGERP (value
) && !FLOATP (value
))
5313 case IMAGE_INTEGER_VALUE
:
5314 if (!INTEGERP (value
))
5318 case IMAGE_BOOL_VALUE
:
5319 if (!NILP (value
) && !EQ (value
, Qt
))
5328 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5332 /* Check that all mandatory fields are present. */
5333 for (i
= 0; i
< nkeywords
; ++i
)
5334 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5337 return NILP (plist
);
5341 /* Return the value of KEY in image specification SPEC. Value is nil
5342 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5343 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5346 image_spec_value (spec
, key
, found
)
5347 Lisp_Object spec
, key
;
5352 xassert (valid_image_p (spec
));
5354 for (tail
= XCDR (spec
);
5355 CONSP (tail
) && CONSP (XCDR (tail
));
5356 tail
= XCDR (XCDR (tail
)))
5358 if (EQ (XCAR (tail
), key
))
5362 return XCAR (XCDR (tail
));
5372 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5373 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5374 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5375 size in canonical character units.\n\
5376 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5377 or omitted means use the selected frame.")
5378 (spec
, pixels
, frame
)
5379 Lisp_Object spec
, pixels
, frame
;
5384 if (valid_image_p (spec
))
5386 struct frame
*f
= check_x_frame (frame
);
5387 int id
= lookup_image (f
, spec
);
5388 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5389 int width
= img
->width
+ 2 * img
->margin
;
5390 int height
= img
->height
+ 2 * img
->margin
;
5393 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5394 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5396 size
= Fcons (make_number (width
), make_number (height
));
5399 error ("Invalid image specification");
5405 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5406 "Return t if image SPEC has a mask bitmap.\n\
5407 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5408 or omitted means use the selected frame.")
5410 Lisp_Object spec
, frame
;
5415 if (valid_image_p (spec
))
5417 struct frame
*f
= check_x_frame (frame
);
5418 int id
= lookup_image (f
, spec
);
5419 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5424 error ("Invalid image specification");
5431 /***********************************************************************
5432 Image type independent image structures
5433 ***********************************************************************/
5435 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5436 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5439 /* Allocate and return a new image structure for image specification
5440 SPEC. SPEC has a hash value of HASH. */
5442 static struct image
*
5443 make_image (spec
, hash
)
5447 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5449 xassert (valid_image_p (spec
));
5450 bzero (img
, sizeof *img
);
5451 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5452 xassert (img
->type
!= NULL
);
5454 img
->data
.lisp_val
= Qnil
;
5455 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5461 /* Free image IMG which was used on frame F, including its resources. */
5470 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5472 /* Remove IMG from the hash table of its cache. */
5474 img
->prev
->next
= img
->next
;
5476 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5479 img
->next
->prev
= img
->prev
;
5481 c
->images
[img
->id
] = NULL
;
5483 /* Free resources, then free IMG. */
5484 img
->type
->free (f
, img
);
5490 /* Prepare image IMG for display on frame F. Must be called before
5491 drawing an image. */
5494 prepare_image_for_display (f
, img
)
5500 /* We're about to display IMG, so set its timestamp to `now'. */
5502 img
->timestamp
= EMACS_SECS (t
);
5504 /* If IMG doesn't have a pixmap yet, load it now, using the image
5505 type dependent loader function. */
5506 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5507 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5511 /* Value is the number of pixels for the ascent of image IMG when
5512 drawn in face FACE. */
5515 image_ascent (img
, face
)
5519 int height
= img
->height
+ img
->margin
;
5522 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5525 /* This expression is arranged so that if the image can't be
5526 exactly centered, it will be moved slightly up. This is
5527 because a typical font is `top-heavy' (due to the presence
5528 uppercase letters), so the image placement should err towards
5529 being top-heavy too. It also just generally looks better. */
5530 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5532 ascent
= height
/ 2;
5535 ascent
= height
* img
->ascent
/ 100.0;
5542 /***********************************************************************
5543 Helper functions for X image types
5544 ***********************************************************************/
5546 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
5548 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5549 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5551 Lisp_Object color_name
,
5552 unsigned long dflt
));
5555 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5556 free the pixmap if any. MASK_P non-zero means clear the mask
5557 pixmap if any. COLORS_P non-zero means free colors allocated for
5558 the image, if any. */
5561 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
5564 int pixmap_p
, mask_p
, colors_p
;
5566 if (pixmap_p
&& img
->pixmap
)
5568 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5572 if (mask_p
&& img
->mask
)
5574 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5578 if (colors_p
&& img
->ncolors
)
5580 x_free_colors (f
, img
->colors
, img
->ncolors
);
5581 xfree (img
->colors
);
5587 /* Free X resources of image IMG which is used on frame F. */
5590 x_clear_image (f
, img
)
5595 x_clear_image_1 (f
, img
, 1, 1, 1);
5600 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5601 cannot be allocated, use DFLT. Add a newly allocated color to
5602 IMG->colors, so that it can be freed again. Value is the pixel
5605 static unsigned long
5606 x_alloc_image_color (f
, img
, color_name
, dflt
)
5609 Lisp_Object color_name
;
5613 unsigned long result
;
5615 xassert (STRINGP (color_name
));
5617 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5619 /* This isn't called frequently so we get away with simply
5620 reallocating the color vector to the needed size, here. */
5623 (unsigned long *) xrealloc (img
->colors
,
5624 img
->ncolors
* sizeof *img
->colors
);
5625 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5626 result
= color
.pixel
;
5636 /***********************************************************************
5638 ***********************************************************************/
5640 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5643 /* Return a new, initialized image cache that is allocated from the
5644 heap. Call free_image_cache to free an image cache. */
5646 struct image_cache
*
5649 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5652 bzero (c
, sizeof *c
);
5654 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5655 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5656 c
->buckets
= (struct image
**) xmalloc (size
);
5657 bzero (c
->buckets
, size
);
5662 /* Free image cache of frame F. Be aware that X frames share images
5666 free_image_cache (f
)
5669 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5674 /* Cache should not be referenced by any frame when freed. */
5675 xassert (c
->refcount
== 0);
5677 for (i
= 0; i
< c
->used
; ++i
)
5678 free_image (f
, c
->images
[i
]);
5682 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5687 /* Clear image cache of frame F. FORCE_P non-zero means free all
5688 images. FORCE_P zero means clear only images that haven't been
5689 displayed for some time. Should be called from time to time to
5690 reduce the number of loaded images. If image-eviction-seconds is
5691 non-nil, this frees images in the cache which weren't displayed for
5692 at least that many seconds. */
5695 clear_image_cache (f
, force_p
)
5699 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5701 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5708 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5710 /* Block input so that we won't be interrupted by a SIGIO
5711 while being in an inconsistent state. */
5714 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
5716 struct image
*img
= c
->images
[i
];
5718 && (force_p
|| img
->timestamp
< old
))
5720 free_image (f
, img
);
5725 /* We may be clearing the image cache because, for example,
5726 Emacs was iconified for a longer period of time. In that
5727 case, current matrices may still contain references to
5728 images freed above. So, clear these matrices. */
5731 Lisp_Object tail
, frame
;
5733 FOR_EACH_FRAME (tail
, frame
)
5735 struct frame
*f
= XFRAME (frame
);
5737 && FRAME_X_IMAGE_CACHE (f
) == c
)
5738 clear_current_matrices (f
);
5741 ++windows_or_buffers_changed
;
5749 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5751 "Clear the image cache of FRAME.\n\
5752 FRAME nil or omitted means use the selected frame.\n\
5753 FRAME t means clear the image caches of all frames.")
5761 FOR_EACH_FRAME (tail
, frame
)
5762 if (FRAME_X_P (XFRAME (frame
)))
5763 clear_image_cache (XFRAME (frame
), 1);
5766 clear_image_cache (check_x_frame (frame
), 1);
5772 /* Return the id of image with Lisp specification SPEC on frame F.
5773 SPEC must be a valid Lisp image specification (see valid_image_p). */
5776 lookup_image (f
, spec
)
5780 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5784 struct gcpro gcpro1
;
5787 /* F must be a window-system frame, and SPEC must be a valid image
5789 xassert (FRAME_WINDOW_P (f
));
5790 xassert (valid_image_p (spec
));
5794 /* Look up SPEC in the hash table of the image cache. */
5795 hash
= sxhash (spec
, 0);
5796 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5798 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
5799 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
5802 /* If not found, create a new image and cache it. */
5806 img
= make_image (spec
, hash
);
5807 cache_image (f
, img
);
5808 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5810 /* If we can't load the image, and we don't have a width and
5811 height, use some arbitrary width and height so that we can
5812 draw a rectangle for it. */
5813 if (img
->load_failed_p
)
5817 value
= image_spec_value (spec
, QCwidth
, NULL
);
5818 img
->width
= (INTEGERP (value
)
5819 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
5820 value
= image_spec_value (spec
, QCheight
, NULL
);
5821 img
->height
= (INTEGERP (value
)
5822 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
5826 /* Handle image type independent image attributes
5827 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5828 Lisp_Object ascent
, margin
, relief
;
5831 ascent
= image_spec_value (spec
, QCascent
, NULL
);
5832 if (INTEGERP (ascent
))
5833 img
->ascent
= XFASTINT (ascent
);
5834 else if (EQ (ascent
, Qcenter
))
5835 img
->ascent
= CENTERED_IMAGE_ASCENT
;
5837 margin
= image_spec_value (spec
, QCmargin
, NULL
);
5838 if (INTEGERP (margin
) && XINT (margin
) >= 0)
5839 img
->margin
= XFASTINT (margin
);
5841 relief
= image_spec_value (spec
, QCrelief
, NULL
);
5842 if (INTEGERP (relief
))
5844 img
->relief
= XINT (relief
);
5845 img
->margin
+= abs (img
->relief
);
5848 /* Manipulation of the image's mask. */
5851 /* `:heuristic-mask t'
5853 means build a mask heuristically.
5854 `:heuristic-mask (R G B)'
5855 `:mask (heuristic (R G B))'
5856 means build a mask from color (R G B) in the
5859 means remove a mask, if any. */
5863 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
5865 x_build_heuristic_mask (f
, img
, mask
);
5870 mask
= image_spec_value (spec
, QCmask
, &found_p
);
5872 if (EQ (mask
, Qheuristic
))
5873 x_build_heuristic_mask (f
, img
, Qt
);
5874 else if (CONSP (mask
)
5875 && EQ (XCAR (mask
), Qheuristic
))
5877 if (CONSP (XCDR (mask
)))
5878 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
5880 x_build_heuristic_mask (f
, img
, XCDR (mask
));
5882 else if (NILP (mask
) && found_p
&& img
->mask
)
5884 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5890 /* Should we apply an image transformation algorithm? */
5893 Lisp_Object algorithm
;
5895 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
5896 if (EQ (algorithm
, Qdisabled
))
5897 x_disable_image (f
, img
);
5898 else if (EQ (algorithm
, Qlaplace
))
5900 else if (EQ (algorithm
, Qemboss
))
5902 else if (CONSP (algorithm
)
5903 && EQ (XCAR (algorithm
), Qedge_detection
))
5906 tem
= XCDR (algorithm
);
5908 x_edge_detection (f
, img
,
5909 Fplist_get (tem
, QCmatrix
),
5910 Fplist_get (tem
, QCcolor_adjustment
));
5916 xassert (!interrupt_input_blocked
);
5919 /* We're using IMG, so set its timestamp to `now'. */
5920 EMACS_GET_TIME (now
);
5921 img
->timestamp
= EMACS_SECS (now
);
5925 /* Value is the image id. */
5930 /* Cache image IMG in the image cache of frame F. */
5933 cache_image (f
, img
)
5937 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5940 /* Find a free slot in c->images. */
5941 for (i
= 0; i
< c
->used
; ++i
)
5942 if (c
->images
[i
] == NULL
)
5945 /* If no free slot found, maybe enlarge c->images. */
5946 if (i
== c
->used
&& c
->used
== c
->size
)
5949 c
->images
= (struct image
**) xrealloc (c
->images
,
5950 c
->size
* sizeof *c
->images
);
5953 /* Add IMG to c->images, and assign IMG an id. */
5959 /* Add IMG to the cache's hash table. */
5960 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5961 img
->next
= c
->buckets
[i
];
5963 img
->next
->prev
= img
;
5965 c
->buckets
[i
] = img
;
5969 /* Call FN on every image in the image cache of frame F. Used to mark
5970 Lisp Objects in the image cache. */
5973 forall_images_in_image_cache (f
, fn
)
5975 void (*fn
) P_ ((struct image
*img
));
5977 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
5979 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5983 for (i
= 0; i
< c
->used
; ++i
)
5992 /***********************************************************************
5994 ***********************************************************************/
5996 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
5997 XImage
**, Pixmap
*));
5998 static void x_destroy_x_image
P_ ((XImage
*));
5999 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6002 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6003 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6004 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6005 via xmalloc. Print error messages via image_error if an error
6006 occurs. Value is non-zero if successful. */
6009 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6011 int width
, height
, depth
;
6015 Display
*display
= FRAME_X_DISPLAY (f
);
6016 Screen
*screen
= FRAME_X_SCREEN (f
);
6017 Window window
= FRAME_X_WINDOW (f
);
6019 xassert (interrupt_input_blocked
);
6022 depth
= DefaultDepthOfScreen (screen
);
6023 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6024 depth
, ZPixmap
, 0, NULL
, width
, height
,
6025 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6028 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6032 /* Allocate image raster. */
6033 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6035 /* Allocate a pixmap of the same size. */
6036 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6037 if (*pixmap
== None
)
6039 x_destroy_x_image (*ximg
);
6041 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6049 /* Destroy XImage XIMG. Free XIMG->data. */
6052 x_destroy_x_image (ximg
)
6055 xassert (interrupt_input_blocked
);
6060 XDestroyImage (ximg
);
6065 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6066 are width and height of both the image and pixmap. */
6069 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6076 xassert (interrupt_input_blocked
);
6077 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6078 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6079 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6084 /***********************************************************************
6086 ***********************************************************************/
6088 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6089 static char *slurp_file
P_ ((char *, int *));
6092 /* Find image file FILE. Look in data-directory, then
6093 x-bitmap-file-path. Value is the full name of the file found, or
6094 nil if not found. */
6097 x_find_image_file (file
)
6100 Lisp_Object file_found
, search_path
;
6101 struct gcpro gcpro1
, gcpro2
;
6105 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6106 GCPRO2 (file_found
, search_path
);
6108 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6109 fd
= openp (search_path
, file
, "", &file_found
, 0);
6121 /* Read FILE into memory. Value is a pointer to a buffer allocated
6122 with xmalloc holding FILE's contents. Value is null if an error
6123 occurred. *SIZE is set to the size of the file. */
6126 slurp_file (file
, size
)
6134 if (stat (file
, &st
) == 0
6135 && (fp
= fopen (file
, "r")) != NULL
6136 && (buf
= (char *) xmalloc (st
.st_size
),
6137 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6158 /***********************************************************************
6160 ***********************************************************************/
6162 static int xbm_scan
P_ ((char **, char *, char *, int *));
6163 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6164 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6166 static int xbm_image_p
P_ ((Lisp_Object object
));
6167 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6169 static int xbm_file_p
P_ ((Lisp_Object
));
6172 /* Indices of image specification fields in xbm_format, below. */
6174 enum xbm_keyword_index
6192 /* Vector of image_keyword structures describing the format
6193 of valid XBM image specifications. */
6195 static struct image_keyword xbm_format
[XBM_LAST
] =
6197 {":type", IMAGE_SYMBOL_VALUE
, 1},
6198 {":file", IMAGE_STRING_VALUE
, 0},
6199 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6200 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6201 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6202 {":foreground", IMAGE_STRING_VALUE
, 0},
6203 {":background", IMAGE_STRING_VALUE
, 0},
6204 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6205 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6206 {":relief", IMAGE_INTEGER_VALUE
, 0},
6207 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6208 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6209 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6212 /* Structure describing the image type XBM. */
6214 static struct image_type xbm_type
=
6223 /* Tokens returned from xbm_scan. */
6232 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6233 A valid specification is a list starting with the symbol `image'
6234 The rest of the list is a property list which must contain an
6237 If the specification specifies a file to load, it must contain
6238 an entry `:file FILENAME' where FILENAME is a string.
6240 If the specification is for a bitmap loaded from memory it must
6241 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6242 WIDTH and HEIGHT are integers > 0. DATA may be:
6244 1. a string large enough to hold the bitmap data, i.e. it must
6245 have a size >= (WIDTH + 7) / 8 * HEIGHT
6247 2. a bool-vector of size >= WIDTH * HEIGHT
6249 3. a vector of strings or bool-vectors, one for each line of the
6252 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6253 may not be specified in this case because they are defined in the
6256 Both the file and data forms may contain the additional entries
6257 `:background COLOR' and `:foreground COLOR'. If not present,
6258 foreground and background of the frame on which the image is
6259 displayed is used. */
6262 xbm_image_p (object
)
6265 struct image_keyword kw
[XBM_LAST
];
6267 bcopy (xbm_format
, kw
, sizeof kw
);
6268 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6271 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6273 if (kw
[XBM_FILE
].count
)
6275 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6278 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6280 /* In-memory XBM file. */
6281 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6289 /* Entries for `:width', `:height' and `:data' must be present. */
6290 if (!kw
[XBM_WIDTH
].count
6291 || !kw
[XBM_HEIGHT
].count
6292 || !kw
[XBM_DATA
].count
)
6295 data
= kw
[XBM_DATA
].value
;
6296 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6297 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6299 /* Check type of data, and width and height against contents of
6305 /* Number of elements of the vector must be >= height. */
6306 if (XVECTOR (data
)->size
< height
)
6309 /* Each string or bool-vector in data must be large enough
6310 for one line of the image. */
6311 for (i
= 0; i
< height
; ++i
)
6313 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6317 if (XSTRING (elt
)->size
6318 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6321 else if (BOOL_VECTOR_P (elt
))
6323 if (XBOOL_VECTOR (elt
)->size
< width
)
6330 else if (STRINGP (data
))
6332 if (XSTRING (data
)->size
6333 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6336 else if (BOOL_VECTOR_P (data
))
6338 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6349 /* Scan a bitmap file. FP is the stream to read from. Value is
6350 either an enumerator from enum xbm_token, or a character for a
6351 single-character token, or 0 at end of file. If scanning an
6352 identifier, store the lexeme of the identifier in SVAL. If
6353 scanning a number, store its value in *IVAL. */
6356 xbm_scan (s
, end
, sval
, ival
)
6365 /* Skip white space. */
6366 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6371 else if (isdigit (c
))
6373 int value
= 0, digit
;
6375 if (c
== '0' && *s
< end
)
6378 if (c
== 'x' || c
== 'X')
6385 else if (c
>= 'a' && c
<= 'f')
6386 digit
= c
- 'a' + 10;
6387 else if (c
>= 'A' && c
<= 'F')
6388 digit
= c
- 'A' + 10;
6391 value
= 16 * value
+ digit
;
6394 else if (isdigit (c
))
6398 && (c
= *(*s
)++, isdigit (c
)))
6399 value
= 8 * value
+ c
- '0';
6406 && (c
= *(*s
)++, isdigit (c
)))
6407 value
= 10 * value
+ c
- '0';
6415 else if (isalpha (c
) || c
== '_')
6419 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6426 else if (c
== '/' && **s
== '*')
6428 /* C-style comment. */
6430 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6443 /* Replacement for XReadBitmapFileData which isn't available under old
6444 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6445 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6446 the image. Return in *DATA the bitmap data allocated with xmalloc.
6447 Value is non-zero if successful. DATA null means just test if
6448 CONTENTS looks like an in-memory XBM file. */
6451 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6452 char *contents
, *end
;
6453 int *width
, *height
;
6454 unsigned char **data
;
6457 char buffer
[BUFSIZ
];
6460 int bytes_per_line
, i
, nbytes
;
6466 LA1 = xbm_scan (&s, end, buffer, &value)
6468 #define expect(TOKEN) \
6469 if (LA1 != (TOKEN)) \
6474 #define expect_ident(IDENT) \
6475 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6480 *width
= *height
= -1;
6483 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6485 /* Parse defines for width, height and hot-spots. */
6489 expect_ident ("define");
6490 expect (XBM_TK_IDENT
);
6492 if (LA1
== XBM_TK_NUMBER
);
6494 char *p
= strrchr (buffer
, '_');
6495 p
= p
? p
+ 1 : buffer
;
6496 if (strcmp (p
, "width") == 0)
6498 else if (strcmp (p
, "height") == 0)
6501 expect (XBM_TK_NUMBER
);
6504 if (*width
< 0 || *height
< 0)
6506 else if (data
== NULL
)
6509 /* Parse bits. Must start with `static'. */
6510 expect_ident ("static");
6511 if (LA1
== XBM_TK_IDENT
)
6513 if (strcmp (buffer
, "unsigned") == 0)
6516 expect_ident ("char");
6518 else if (strcmp (buffer
, "short") == 0)
6522 if (*width
% 16 && *width
% 16 < 9)
6525 else if (strcmp (buffer
, "char") == 0)
6533 expect (XBM_TK_IDENT
);
6539 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6540 nbytes
= bytes_per_line
* *height
;
6541 p
= *data
= (char *) xmalloc (nbytes
);
6545 for (i
= 0; i
< nbytes
; i
+= 2)
6548 expect (XBM_TK_NUMBER
);
6551 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6554 if (LA1
== ',' || LA1
== '}')
6562 for (i
= 0; i
< nbytes
; ++i
)
6565 expect (XBM_TK_NUMBER
);
6569 if (LA1
== ',' || LA1
== '}')
6594 /* Load XBM image IMG which will be displayed on frame F from buffer
6595 CONTENTS. END is the end of the buffer. Value is non-zero if
6599 xbm_load_image (f
, img
, contents
, end
)
6602 char *contents
, *end
;
6605 unsigned char *data
;
6608 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
6611 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6612 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6613 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6616 xassert (img
->width
> 0 && img
->height
> 0);
6618 /* Get foreground and background colors, maybe allocate colors. */
6619 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6621 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6623 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6625 background
= x_alloc_image_color (f
, img
, value
, background
);
6628 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6631 img
->width
, img
->height
,
6632 foreground
, background
,
6636 if (img
->pixmap
== None
)
6638 x_clear_image (f
, img
);
6639 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
6645 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6651 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6658 return (STRINGP (data
)
6659 && xbm_read_bitmap_data (XSTRING (data
)->data
,
6660 (XSTRING (data
)->data
6661 + STRING_BYTES (XSTRING (data
))),
6666 /* Fill image IMG which is used on frame F with pixmap data. Value is
6667 non-zero if successful. */
6675 Lisp_Object file_name
;
6677 xassert (xbm_image_p (img
->spec
));
6679 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6680 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6681 if (STRINGP (file_name
))
6686 struct gcpro gcpro1
;
6688 file
= x_find_image_file (file_name
);
6690 if (!STRINGP (file
))
6692 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
6697 contents
= slurp_file (XSTRING (file
)->data
, &size
);
6698 if (contents
== NULL
)
6700 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6705 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
6710 struct image_keyword fmt
[XBM_LAST
];
6712 unsigned char *bitmap_data
;
6714 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6715 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6717 int parsed_p
, height
, width
;
6718 int in_memory_file_p
= 0;
6720 /* See if data looks like an in-memory XBM file. */
6721 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6722 in_memory_file_p
= xbm_file_p (data
);
6724 /* Parse the image specification. */
6725 bcopy (xbm_format
, fmt
, sizeof fmt
);
6726 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6729 /* Get specified width, and height. */
6730 if (!in_memory_file_p
)
6732 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6733 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6734 xassert (img
->width
> 0 && img
->height
> 0);
6737 /* Get foreground and background colors, maybe allocate colors. */
6738 if (fmt
[XBM_FOREGROUND
].count
)
6739 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6741 if (fmt
[XBM_BACKGROUND
].count
)
6742 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6745 if (in_memory_file_p
)
6746 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
6747 (XSTRING (data
)->data
6748 + STRING_BYTES (XSTRING (data
))));
6755 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6757 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6758 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6760 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6762 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6764 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6767 else if (STRINGP (data
))
6768 bits
= XSTRING (data
)->data
;
6770 bits
= XBOOL_VECTOR (data
)->data
;
6772 /* Create the pixmap. */
6773 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6775 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6778 img
->width
, img
->height
,
6779 foreground
, background
,
6785 image_error ("Unable to create pixmap for XBM image `%s'",
6787 x_clear_image (f
, img
);
6797 /***********************************************************************
6799 ***********************************************************************/
6803 static int xpm_image_p
P_ ((Lisp_Object object
));
6804 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6805 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6807 #include "X11/xpm.h"
6809 /* The symbol `xpm' identifying XPM-format images. */
6813 /* Indices of image specification fields in xpm_format, below. */
6815 enum xpm_keyword_index
6830 /* Vector of image_keyword structures describing the format
6831 of valid XPM image specifications. */
6833 static struct image_keyword xpm_format
[XPM_LAST
] =
6835 {":type", IMAGE_SYMBOL_VALUE
, 1},
6836 {":file", IMAGE_STRING_VALUE
, 0},
6837 {":data", IMAGE_STRING_VALUE
, 0},
6838 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6839 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6840 {":relief", IMAGE_INTEGER_VALUE
, 0},
6841 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6842 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6843 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6844 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6847 /* Structure describing the image type XBM. */
6849 static struct image_type xpm_type
=
6859 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6860 functions for allocating image colors. Our own functions handle
6861 color allocation failures more gracefully than the ones on the XPM
6864 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6865 #define ALLOC_XPM_COLORS
6868 #ifdef ALLOC_XPM_COLORS
6870 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
6871 static void xpm_free_color_cache
P_ ((void));
6872 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
6873 static int xpm_color_bucket
P_ ((char *));
6874 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
6877 /* An entry in a hash table used to cache color definitions of named
6878 colors. This cache is necessary to speed up XPM image loading in
6879 case we do color allocations ourselves. Without it, we would need
6880 a call to XParseColor per pixel in the image. */
6882 struct xpm_cached_color
6884 /* Next in collision chain. */
6885 struct xpm_cached_color
*next
;
6887 /* Color definition (RGB and pixel color). */
6894 /* The hash table used for the color cache, and its bucket vector
6897 #define XPM_COLOR_CACHE_BUCKETS 1001
6898 struct xpm_cached_color
**xpm_color_cache
;
6900 /* Initialize the color cache. */
6903 xpm_init_color_cache (f
, attrs
)
6905 XpmAttributes
*attrs
;
6907 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
6908 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
6909 memset (xpm_color_cache
, 0, nbytes
);
6910 init_color_table ();
6912 if (attrs
->valuemask
& XpmColorSymbols
)
6917 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
6918 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
6919 attrs
->colorsymbols
[i
].value
, &color
))
6921 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
6923 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
6929 /* Free the color cache. */
6932 xpm_free_color_cache ()
6934 struct xpm_cached_color
*p
, *next
;
6937 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
6938 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
6944 xfree (xpm_color_cache
);
6945 xpm_color_cache
= NULL
;
6946 free_color_table ();
6950 /* Return the bucket index for color named COLOR_NAME in the color
6954 xpm_color_bucket (color_name
)
6960 for (s
= color_name
; *s
; ++s
)
6962 return h
%= XPM_COLOR_CACHE_BUCKETS
;
6966 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6967 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6970 static struct xpm_cached_color
*
6971 xpm_cache_color (f
, color_name
, color
, bucket
)
6978 struct xpm_cached_color
*p
;
6981 bucket
= xpm_color_bucket (color_name
);
6983 nbytes
= sizeof *p
+ strlen (color_name
);
6984 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
6985 strcpy (p
->name
, color_name
);
6987 p
->next
= xpm_color_cache
[bucket
];
6988 xpm_color_cache
[bucket
] = p
;
6993 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6994 return the cached definition in *COLOR. Otherwise, make a new
6995 entry in the cache and allocate the color. Value is zero if color
6996 allocation failed. */
6999 xpm_lookup_color (f
, color_name
, color
)
7004 struct xpm_cached_color
*p
;
7005 int h
= xpm_color_bucket (color_name
);
7007 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7008 if (strcmp (p
->name
, color_name
) == 0)
7013 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7016 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7018 p
= xpm_cache_color (f
, color_name
, color
, h
);
7025 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7026 CLOSURE is a pointer to the frame on which we allocate the
7027 color. Return in *COLOR the allocated color. Value is non-zero
7031 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7038 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7042 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7043 is a pointer to the frame on which we allocate the color. Value is
7044 non-zero if successful. */
7047 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7057 #endif /* ALLOC_XPM_COLORS */
7060 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7061 for XPM images. Such a list must consist of conses whose car and
7065 xpm_valid_color_symbols_p (color_symbols
)
7066 Lisp_Object color_symbols
;
7068 while (CONSP (color_symbols
))
7070 Lisp_Object sym
= XCAR (color_symbols
);
7072 || !STRINGP (XCAR (sym
))
7073 || !STRINGP (XCDR (sym
)))
7075 color_symbols
= XCDR (color_symbols
);
7078 return NILP (color_symbols
);
7082 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7085 xpm_image_p (object
)
7088 struct image_keyword fmt
[XPM_LAST
];
7089 bcopy (xpm_format
, fmt
, sizeof fmt
);
7090 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7091 /* Either `:file' or `:data' must be present. */
7092 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7093 /* Either no `:color-symbols' or it's a list of conses
7094 whose car and cdr are strings. */
7095 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7096 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7100 /* Load image IMG which will be displayed on frame F. Value is
7101 non-zero if successful. */
7109 XpmAttributes attrs
;
7110 Lisp_Object specified_file
, color_symbols
;
7112 /* Configure the XPM lib. Use the visual of frame F. Allocate
7113 close colors. Return colors allocated. */
7114 bzero (&attrs
, sizeof attrs
);
7115 attrs
.visual
= FRAME_X_VISUAL (f
);
7116 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7117 attrs
.valuemask
|= XpmVisual
;
7118 attrs
.valuemask
|= XpmColormap
;
7120 #ifdef ALLOC_XPM_COLORS
7121 /* Allocate colors with our own functions which handle
7122 failing color allocation more gracefully. */
7123 attrs
.color_closure
= f
;
7124 attrs
.alloc_color
= xpm_alloc_color
;
7125 attrs
.free_colors
= xpm_free_colors
;
7126 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7127 #else /* not ALLOC_XPM_COLORS */
7128 /* Let the XPM lib allocate colors. */
7129 attrs
.valuemask
|= XpmReturnAllocPixels
;
7130 #ifdef XpmAllocCloseColors
7131 attrs
.alloc_close_colors
= 1;
7132 attrs
.valuemask
|= XpmAllocCloseColors
;
7133 #else /* not XpmAllocCloseColors */
7134 attrs
.closeness
= 600;
7135 attrs
.valuemask
|= XpmCloseness
;
7136 #endif /* not XpmAllocCloseColors */
7137 #endif /* ALLOC_XPM_COLORS */
7139 /* If image specification contains symbolic color definitions, add
7140 these to `attrs'. */
7141 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7142 if (CONSP (color_symbols
))
7145 XpmColorSymbol
*xpm_syms
;
7148 attrs
.valuemask
|= XpmColorSymbols
;
7150 /* Count number of symbols. */
7151 attrs
.numsymbols
= 0;
7152 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7155 /* Allocate an XpmColorSymbol array. */
7156 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7157 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7158 bzero (xpm_syms
, size
);
7159 attrs
.colorsymbols
= xpm_syms
;
7161 /* Fill the color symbol array. */
7162 for (tail
= color_symbols
, i
= 0;
7164 ++i
, tail
= XCDR (tail
))
7166 Lisp_Object name
= XCAR (XCAR (tail
));
7167 Lisp_Object color
= XCDR (XCAR (tail
));
7168 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7169 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7170 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7171 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7175 /* Create a pixmap for the image, either from a file, or from a
7176 string buffer containing data in the same format as an XPM file. */
7177 #ifdef ALLOC_XPM_COLORS
7178 xpm_init_color_cache (f
, &attrs
);
7181 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7182 if (STRINGP (specified_file
))
7184 Lisp_Object file
= x_find_image_file (specified_file
);
7185 if (!STRINGP (file
))
7187 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7191 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7192 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7197 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7198 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7199 XSTRING (buffer
)->data
,
7200 &img
->pixmap
, &img
->mask
,
7204 if (rc
== XpmSuccess
)
7206 #ifdef ALLOC_XPM_COLORS
7207 img
->colors
= colors_in_color_table (&img
->ncolors
);
7208 #else /* not ALLOC_XPM_COLORS */
7209 img
->ncolors
= attrs
.nalloc_pixels
;
7210 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7211 * sizeof *img
->colors
);
7212 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7214 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7215 #ifdef DEBUG_X_COLORS
7216 register_color (img
->colors
[i
]);
7219 #endif /* not ALLOC_XPM_COLORS */
7221 img
->width
= attrs
.width
;
7222 img
->height
= attrs
.height
;
7223 xassert (img
->width
> 0 && img
->height
> 0);
7225 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7226 XpmFreeAttributes (&attrs
);
7233 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7236 case XpmFileInvalid
:
7237 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7241 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7244 case XpmColorFailed
:
7245 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7249 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7254 #ifdef ALLOC_XPM_COLORS
7255 xpm_free_color_cache ();
7257 return rc
== XpmSuccess
;
7260 #endif /* HAVE_XPM != 0 */
7263 /***********************************************************************
7265 ***********************************************************************/
7267 /* An entry in the color table mapping an RGB color to a pixel color. */
7272 unsigned long pixel
;
7274 /* Next in color table collision list. */
7275 struct ct_color
*next
;
7278 /* The bucket vector size to use. Must be prime. */
7282 /* Value is a hash of the RGB color given by R, G, and B. */
7284 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7286 /* The color hash table. */
7288 struct ct_color
**ct_table
;
7290 /* Number of entries in the color table. */
7292 int ct_colors_allocated
;
7294 /* Initialize the color table. */
7299 int size
= CT_SIZE
* sizeof (*ct_table
);
7300 ct_table
= (struct ct_color
**) xmalloc (size
);
7301 bzero (ct_table
, size
);
7302 ct_colors_allocated
= 0;
7306 /* Free memory associated with the color table. */
7312 struct ct_color
*p
, *next
;
7314 for (i
= 0; i
< CT_SIZE
; ++i
)
7315 for (p
= ct_table
[i
]; p
; p
= next
)
7326 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7327 entry for that color already is in the color table, return the
7328 pixel color of that entry. Otherwise, allocate a new color for R,
7329 G, B, and make an entry in the color table. */
7331 static unsigned long
7332 lookup_rgb_color (f
, r
, g
, b
)
7336 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7337 int i
= hash
% CT_SIZE
;
7340 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7341 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7354 cmap
= FRAME_X_COLORMAP (f
);
7355 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7359 ++ct_colors_allocated
;
7361 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7365 p
->pixel
= color
.pixel
;
7366 p
->next
= ct_table
[i
];
7370 return FRAME_FOREGROUND_PIXEL (f
);
7377 /* Look up pixel color PIXEL which is used on frame F in the color
7378 table. If not already present, allocate it. Value is PIXEL. */
7380 static unsigned long
7381 lookup_pixel_color (f
, pixel
)
7383 unsigned long pixel
;
7385 int i
= pixel
% CT_SIZE
;
7388 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7389 if (p
->pixel
== pixel
)
7398 cmap
= FRAME_X_COLORMAP (f
);
7399 color
.pixel
= pixel
;
7400 x_query_color (f
, &color
);
7401 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7405 ++ct_colors_allocated
;
7407 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7412 p
->next
= ct_table
[i
];
7416 return FRAME_FOREGROUND_PIXEL (f
);
7423 /* Value is a vector of all pixel colors contained in the color table,
7424 allocated via xmalloc. Set *N to the number of colors. */
7426 static unsigned long *
7427 colors_in_color_table (n
)
7432 unsigned long *colors
;
7434 if (ct_colors_allocated
== 0)
7441 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7443 *n
= ct_colors_allocated
;
7445 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7446 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7447 colors
[j
++] = p
->pixel
;
7455 /***********************************************************************
7457 ***********************************************************************/
7459 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7460 int, XImage
*, int));
7461 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7462 XColor
*, int, XImage
*, int));
7463 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7464 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7465 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7467 /* Non-zero means draw a cross on images having `:algorithm
7470 int cross_disabled_images
;
7472 /* Edge detection matrices for different edge-detection
7475 static int emboss_matrix
[9] = {
7477 2, -1, 0, /* y - 1 */
7479 0, 1, -2 /* y + 1 */
7482 static int laplace_matrix
[9] = {
7484 1, 0, 0, /* y - 1 */
7486 0, 0, -1 /* y + 1 */
7489 /* Value is the intensity of the color whose red/green/blue values
7492 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7495 /* On frame F, return an array of XColor structures describing image
7496 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7497 non-zero means also fill the red/green/blue members of the XColor
7498 structures. Value is a pointer to the array of XColors structures,
7499 allocated with xmalloc; it must be freed by the caller. */
7502 x_to_xcolors (f
, img
, rgb_p
)
7511 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
7513 /* Get the X image IMG->pixmap. */
7514 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7515 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7517 /* Fill the `pixel' members of the XColor array. I wished there
7518 were an easy and portable way to circumvent XGetPixel. */
7520 for (y
= 0; y
< img
->height
; ++y
)
7524 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7525 p
->pixel
= XGetPixel (ximg
, x
, y
);
7528 x_query_colors (f
, row
, img
->width
);
7531 XDestroyImage (ximg
);
7536 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7537 RGB members are set. F is the frame on which this all happens.
7538 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7541 x_from_xcolors (f
, img
, colors
)
7551 init_color_table ();
7553 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7556 for (y
= 0; y
< img
->height
; ++y
)
7557 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7559 unsigned long pixel
;
7560 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
7561 XPutPixel (oimg
, x
, y
, pixel
);
7565 x_clear_image_1 (f
, img
, 1, 0, 1);
7567 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7568 x_destroy_x_image (oimg
);
7569 img
->pixmap
= pixmap
;
7570 img
->colors
= colors_in_color_table (&img
->ncolors
);
7571 free_color_table ();
7575 /* On frame F, perform edge-detection on image IMG.
7577 MATRIX is a nine-element array specifying the transformation
7578 matrix. See emboss_matrix for an example.
7580 COLOR_ADJUST is a color adjustment added to each pixel of the
7584 x_detect_edges (f
, img
, matrix
, color_adjust
)
7587 int matrix
[9], color_adjust
;
7589 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7593 for (i
= sum
= 0; i
< 9; ++i
)
7594 sum
+= abs (matrix
[i
]);
7596 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7598 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
7600 for (y
= 0; y
< img
->height
; ++y
)
7602 p
= COLOR (new, 0, y
);
7603 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7604 p
= COLOR (new, img
->width
- 1, y
);
7605 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7608 for (x
= 1; x
< img
->width
- 1; ++x
)
7610 p
= COLOR (new, x
, 0);
7611 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7612 p
= COLOR (new, x
, img
->height
- 1);
7613 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7616 for (y
= 1; y
< img
->height
- 1; ++y
)
7618 p
= COLOR (new, 1, y
);
7620 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
7622 int r
, g
, b
, y1
, x1
;
7625 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
7626 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
7629 XColor
*t
= COLOR (colors
, x1
, y1
);
7630 r
+= matrix
[i
] * t
->red
;
7631 g
+= matrix
[i
] * t
->green
;
7632 b
+= matrix
[i
] * t
->blue
;
7635 r
= (r
/ sum
+ color_adjust
) & 0xffff;
7636 g
= (g
/ sum
+ color_adjust
) & 0xffff;
7637 b
= (b
/ sum
+ color_adjust
) & 0xffff;
7638 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
7643 x_from_xcolors (f
, img
, new);
7649 /* Perform the pre-defined `emboss' edge-detection on image IMG
7657 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
7661 /* Perform the pre-defined `laplace' edge-detection on image IMG
7669 x_detect_edges (f
, img
, laplace_matrix
, 45000);
7673 /* Perform edge-detection on image IMG on frame F, with specified
7674 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7676 MATRIX must be either
7678 - a list of at least 9 numbers in row-major form
7679 - a vector of at least 9 numbers
7681 COLOR_ADJUST nil means use a default; otherwise it must be a
7685 x_edge_detection (f
, img
, matrix
, color_adjust
)
7688 Lisp_Object matrix
, color_adjust
;
7696 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
7697 ++i
, matrix
= XCDR (matrix
))
7698 trans
[i
] = XFLOATINT (XCAR (matrix
));
7700 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
7702 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
7703 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
7706 if (NILP (color_adjust
))
7707 color_adjust
= make_number (0xffff / 2);
7709 if (i
== 9 && NUMBERP (color_adjust
))
7710 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
7714 /* Transform image IMG on frame F so that it looks disabled. */
7717 x_disable_image (f
, img
)
7721 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7723 if (dpyinfo
->n_planes
>= 2)
7725 /* Color (or grayscale). Convert to gray, and equalize. Just
7726 drawing such images with a stipple can look very odd, so
7727 we're using this method instead. */
7728 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7730 const int h
= 15000;
7731 const int l
= 30000;
7733 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
7737 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
7738 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
7739 p
->red
= p
->green
= p
->blue
= i2
;
7742 x_from_xcolors (f
, img
, colors
);
7745 /* Draw a cross over the disabled image, if we must or if we
7747 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
7749 Display
*dpy
= FRAME_X_DISPLAY (f
);
7752 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
7753 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
7754 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
7755 img
->width
- 1, img
->height
- 1);
7756 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
7762 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
7763 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
7764 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
7765 img
->width
- 1, img
->height
- 1);
7766 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
7774 /* Build a mask for image IMG which is used on frame F. FILE is the
7775 name of an image file, for error messages. HOW determines how to
7776 determine the background color of IMG. If it is a list '(R G B)',
7777 with R, G, and B being integers >= 0, take that as the color of the
7778 background. Otherwise, determine the background color of IMG
7779 heuristically. Value is non-zero if successful. */
7782 x_build_heuristic_mask (f
, img
, how
)
7787 Display
*dpy
= FRAME_X_DISPLAY (f
);
7788 XImage
*ximg
, *mask_img
;
7789 int x
, y
, rc
, look_at_corners_p
;
7790 unsigned long bg
= 0;
7794 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
7798 /* Create an image and pixmap serving as mask. */
7799 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
7800 &mask_img
, &img
->mask
);
7804 /* Get the X image of IMG->pixmap. */
7805 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7808 /* Determine the background color of ximg. If HOW is `(R G B)'
7809 take that as color. Otherwise, try to determine the color
7811 look_at_corners_p
= 1;
7819 && NATNUMP (XCAR (how
)))
7821 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
7825 if (i
== 3 && NILP (how
))
7827 char color_name
[30];
7828 XColor exact
, color
;
7831 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
7833 cmap
= FRAME_X_COLORMAP (f
);
7834 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
7837 look_at_corners_p
= 0;
7842 if (look_at_corners_p
)
7844 unsigned long corners
[4];
7847 /* Get the colors at the corners of ximg. */
7848 corners
[0] = XGetPixel (ximg
, 0, 0);
7849 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7850 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7851 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7853 /* Choose the most frequently found color as background. */
7854 for (i
= best_count
= 0; i
< 4; ++i
)
7858 for (j
= n
= 0; j
< 4; ++j
)
7859 if (corners
[i
] == corners
[j
])
7863 bg
= corners
[i
], best_count
= n
;
7867 /* Set all bits in mask_img to 1 whose color in ximg is different
7868 from the background color bg. */
7869 for (y
= 0; y
< img
->height
; ++y
)
7870 for (x
= 0; x
< img
->width
; ++x
)
7871 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7873 /* Put mask_img into img->mask. */
7874 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7875 x_destroy_x_image (mask_img
);
7876 XDestroyImage (ximg
);
7883 /***********************************************************************
7884 PBM (mono, gray, color)
7885 ***********************************************************************/
7887 static int pbm_image_p
P_ ((Lisp_Object object
));
7888 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7889 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
7891 /* The symbol `pbm' identifying images of this type. */
7895 /* Indices of image specification fields in gs_format, below. */
7897 enum pbm_keyword_index
7913 /* Vector of image_keyword structures describing the format
7914 of valid user-defined image specifications. */
7916 static struct image_keyword pbm_format
[PBM_LAST
] =
7918 {":type", IMAGE_SYMBOL_VALUE
, 1},
7919 {":file", IMAGE_STRING_VALUE
, 0},
7920 {":data", IMAGE_STRING_VALUE
, 0},
7921 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7922 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7923 {":relief", IMAGE_INTEGER_VALUE
, 0},
7924 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7925 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7926 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7927 {":foreground", IMAGE_STRING_VALUE
, 0},
7928 {":background", IMAGE_STRING_VALUE
, 0}
7931 /* Structure describing the image type `pbm'. */
7933 static struct image_type pbm_type
=
7943 /* Return non-zero if OBJECT is a valid PBM image specification. */
7946 pbm_image_p (object
)
7949 struct image_keyword fmt
[PBM_LAST
];
7951 bcopy (pbm_format
, fmt
, sizeof fmt
);
7953 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
7956 /* Must specify either :data or :file. */
7957 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
7961 /* Scan a decimal number from *S and return it. Advance *S while
7962 reading the number. END is the end of the string. Value is -1 at
7966 pbm_scan_number (s
, end
)
7967 unsigned char **s
, *end
;
7969 int c
= 0, val
= -1;
7973 /* Skip white-space. */
7974 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
7979 /* Skip comment to end of line. */
7980 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
7983 else if (isdigit (c
))
7985 /* Read decimal number. */
7987 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
7988 val
= 10 * val
+ c
- '0';
7999 /* Load PBM image IMG for use on frame F. */
8007 int width
, height
, max_color_idx
= 0;
8009 Lisp_Object file
, specified_file
;
8010 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8011 struct gcpro gcpro1
;
8012 unsigned char *contents
= NULL
;
8013 unsigned char *end
, *p
;
8016 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8020 if (STRINGP (specified_file
))
8022 file
= x_find_image_file (specified_file
);
8023 if (!STRINGP (file
))
8025 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8030 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8031 if (contents
== NULL
)
8033 image_error ("Error reading `%s'", file
, Qnil
);
8039 end
= contents
+ size
;
8044 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8045 p
= XSTRING (data
)->data
;
8046 end
= p
+ STRING_BYTES (XSTRING (data
));
8049 /* Check magic number. */
8050 if (end
- p
< 2 || *p
++ != 'P')
8052 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8062 raw_p
= 0, type
= PBM_MONO
;
8066 raw_p
= 0, type
= PBM_GRAY
;
8070 raw_p
= 0, type
= PBM_COLOR
;
8074 raw_p
= 1, type
= PBM_MONO
;
8078 raw_p
= 1, type
= PBM_GRAY
;
8082 raw_p
= 1, type
= PBM_COLOR
;
8086 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8090 /* Read width, height, maximum color-component. Characters
8091 starting with `#' up to the end of a line are ignored. */
8092 width
= pbm_scan_number (&p
, end
);
8093 height
= pbm_scan_number (&p
, end
);
8095 if (type
!= PBM_MONO
)
8097 max_color_idx
= pbm_scan_number (&p
, end
);
8098 if (raw_p
&& max_color_idx
> 255)
8099 max_color_idx
= 255;
8104 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8107 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8108 &ximg
, &img
->pixmap
))
8111 /* Initialize the color hash table. */
8112 init_color_table ();
8114 if (type
== PBM_MONO
)
8117 struct image_keyword fmt
[PBM_LAST
];
8118 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
8119 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
8121 /* Parse the image specification. */
8122 bcopy (pbm_format
, fmt
, sizeof fmt
);
8123 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
8125 /* Get foreground and background colors, maybe allocate colors. */
8126 if (fmt
[PBM_FOREGROUND
].count
)
8127 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
8128 if (fmt
[PBM_BACKGROUND
].count
)
8129 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
8131 for (y
= 0; y
< height
; ++y
)
8132 for (x
= 0; x
< width
; ++x
)
8142 g
= pbm_scan_number (&p
, end
);
8144 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
8149 for (y
= 0; y
< height
; ++y
)
8150 for (x
= 0; x
< width
; ++x
)
8154 if (type
== PBM_GRAY
)
8155 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8164 r
= pbm_scan_number (&p
, end
);
8165 g
= pbm_scan_number (&p
, end
);
8166 b
= pbm_scan_number (&p
, end
);
8169 if (r
< 0 || g
< 0 || b
< 0)
8173 XDestroyImage (ximg
);
8174 image_error ("Invalid pixel value in image `%s'",
8179 /* RGB values are now in the range 0..max_color_idx.
8180 Scale this to the range 0..0xffff supported by X. */
8181 r
= (double) r
* 65535 / max_color_idx
;
8182 g
= (double) g
* 65535 / max_color_idx
;
8183 b
= (double) b
* 65535 / max_color_idx
;
8184 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8188 /* Store in IMG->colors the colors allocated for the image, and
8189 free the color table. */
8190 img
->colors
= colors_in_color_table (&img
->ncolors
);
8191 free_color_table ();
8193 /* Put the image into a pixmap. */
8194 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8195 x_destroy_x_image (ximg
);
8198 img
->height
= height
;
8207 /***********************************************************************
8209 ***********************************************************************/
8215 /* Function prototypes. */
8217 static int png_image_p
P_ ((Lisp_Object object
));
8218 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8220 /* The symbol `png' identifying images of this type. */
8224 /* Indices of image specification fields in png_format, below. */
8226 enum png_keyword_index
8240 /* Vector of image_keyword structures describing the format
8241 of valid user-defined image specifications. */
8243 static struct image_keyword png_format
[PNG_LAST
] =
8245 {":type", IMAGE_SYMBOL_VALUE
, 1},
8246 {":data", IMAGE_STRING_VALUE
, 0},
8247 {":file", IMAGE_STRING_VALUE
, 0},
8248 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8249 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8250 {":relief", IMAGE_INTEGER_VALUE
, 0},
8251 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8252 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8253 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8256 /* Structure describing the image type `png'. */
8258 static struct image_type png_type
=
8268 /* Return non-zero if OBJECT is a valid PNG image specification. */
8271 png_image_p (object
)
8274 struct image_keyword fmt
[PNG_LAST
];
8275 bcopy (png_format
, fmt
, sizeof fmt
);
8277 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8280 /* Must specify either the :data or :file keyword. */
8281 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8285 /* Error and warning handlers installed when the PNG library
8289 my_png_error (png_ptr
, msg
)
8290 png_struct
*png_ptr
;
8293 xassert (png_ptr
!= NULL
);
8294 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8295 longjmp (png_ptr
->jmpbuf
, 1);
8300 my_png_warning (png_ptr
, msg
)
8301 png_struct
*png_ptr
;
8304 xassert (png_ptr
!= NULL
);
8305 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8308 /* Memory source for PNG decoding. */
8310 struct png_memory_storage
8312 unsigned char *bytes
; /* The data */
8313 size_t len
; /* How big is it? */
8314 int index
; /* Where are we? */
8318 /* Function set as reader function when reading PNG image from memory.
8319 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8320 bytes from the input to DATA. */
8323 png_read_from_memory (png_ptr
, data
, length
)
8324 png_structp png_ptr
;
8328 struct png_memory_storage
*tbr
8329 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8331 if (length
> tbr
->len
- tbr
->index
)
8332 png_error (png_ptr
, "Read error");
8334 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8335 tbr
->index
= tbr
->index
+ length
;
8338 /* Load PNG image IMG for use on frame F. Value is non-zero if
8346 Lisp_Object file
, specified_file
;
8347 Lisp_Object specified_data
;
8349 XImage
*ximg
, *mask_img
= NULL
;
8350 struct gcpro gcpro1
;
8351 png_struct
*png_ptr
= NULL
;
8352 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8353 FILE *volatile fp
= NULL
;
8355 png_byte
* volatile pixels
= NULL
;
8356 png_byte
** volatile rows
= NULL
;
8357 png_uint_32 width
, height
;
8358 int bit_depth
, color_type
, interlace_type
;
8360 png_uint_32 row_bytes
;
8363 double screen_gamma
, image_gamma
;
8365 struct png_memory_storage tbr
; /* Data to be read */
8367 /* Find out what file to load. */
8368 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8369 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8373 if (NILP (specified_data
))
8375 file
= x_find_image_file (specified_file
);
8376 if (!STRINGP (file
))
8378 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8383 /* Open the image file. */
8384 fp
= fopen (XSTRING (file
)->data
, "rb");
8387 image_error ("Cannot open image file `%s'", file
, Qnil
);
8393 /* Check PNG signature. */
8394 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8395 || !png_check_sig (sig
, sizeof sig
))
8397 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8405 /* Read from memory. */
8406 tbr
.bytes
= XSTRING (specified_data
)->data
;
8407 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8410 /* Check PNG signature. */
8411 if (tbr
.len
< sizeof sig
8412 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8414 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8419 /* Need to skip past the signature. */
8420 tbr
.bytes
+= sizeof (sig
);
8423 /* Initialize read and info structs for PNG lib. */
8424 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8425 my_png_error
, my_png_warning
);
8428 if (fp
) fclose (fp
);
8433 info_ptr
= png_create_info_struct (png_ptr
);
8436 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8437 if (fp
) fclose (fp
);
8442 end_info
= png_create_info_struct (png_ptr
);
8445 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8446 if (fp
) fclose (fp
);
8451 /* Set error jump-back. We come back here when the PNG library
8452 detects an error. */
8453 if (setjmp (png_ptr
->jmpbuf
))
8457 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8460 if (fp
) fclose (fp
);
8465 /* Read image info. */
8466 if (!NILP (specified_data
))
8467 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8469 png_init_io (png_ptr
, fp
);
8471 png_set_sig_bytes (png_ptr
, sizeof sig
);
8472 png_read_info (png_ptr
, info_ptr
);
8473 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8474 &interlace_type
, NULL
, NULL
);
8476 /* If image contains simply transparency data, we prefer to
8477 construct a clipping mask. */
8478 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8483 /* This function is easier to write if we only have to handle
8484 one data format: RGB or RGBA with 8 bits per channel. Let's
8485 transform other formats into that format. */
8487 /* Strip more than 8 bits per channel. */
8488 if (bit_depth
== 16)
8489 png_set_strip_16 (png_ptr
);
8491 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8493 png_set_expand (png_ptr
);
8495 /* Convert grayscale images to RGB. */
8496 if (color_type
== PNG_COLOR_TYPE_GRAY
8497 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8498 png_set_gray_to_rgb (png_ptr
);
8500 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8501 gamma_str
= getenv ("SCREEN_GAMMA");
8502 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8504 /* Tell the PNG lib to handle gamma correction for us. */
8506 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8507 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8508 /* There is a special chunk in the image specifying the gamma. */
8509 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8512 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8513 /* Image contains gamma information. */
8514 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8516 /* Use a default of 0.5 for the image gamma. */
8517 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8519 /* Handle alpha channel by combining the image with a background
8520 color. Do this only if a real alpha channel is supplied. For
8521 simple transparency, we prefer a clipping mask. */
8524 png_color_16
*image_background
;
8526 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8527 /* Image contains a background color with which to
8528 combine the image. */
8529 png_set_background (png_ptr
, image_background
,
8530 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8533 /* Image does not contain a background color with which
8534 to combine the image data via an alpha channel. Use
8535 the frame's background instead. */
8538 png_color_16 frame_background
;
8540 cmap
= FRAME_X_COLORMAP (f
);
8541 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8542 x_query_color (f
, &color
);
8544 bzero (&frame_background
, sizeof frame_background
);
8545 frame_background
.red
= color
.red
;
8546 frame_background
.green
= color
.green
;
8547 frame_background
.blue
= color
.blue
;
8549 png_set_background (png_ptr
, &frame_background
,
8550 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8554 /* Update info structure. */
8555 png_read_update_info (png_ptr
, info_ptr
);
8557 /* Get number of channels. Valid values are 1 for grayscale images
8558 and images with a palette, 2 for grayscale images with transparency
8559 information (alpha channel), 3 for RGB images, and 4 for RGB
8560 images with alpha channel, i.e. RGBA. If conversions above were
8561 sufficient we should only have 3 or 4 channels here. */
8562 channels
= png_get_channels (png_ptr
, info_ptr
);
8563 xassert (channels
== 3 || channels
== 4);
8565 /* Number of bytes needed for one row of the image. */
8566 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8568 /* Allocate memory for the image. */
8569 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8570 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8571 for (i
= 0; i
< height
; ++i
)
8572 rows
[i
] = pixels
+ i
* row_bytes
;
8574 /* Read the entire image. */
8575 png_read_image (png_ptr
, rows
);
8576 png_read_end (png_ptr
, info_ptr
);
8583 /* Create the X image and pixmap. */
8584 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8588 /* Create an image and pixmap serving as mask if the PNG image
8589 contains an alpha channel. */
8592 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8593 &mask_img
, &img
->mask
))
8595 x_destroy_x_image (ximg
);
8596 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8601 /* Fill the X image and mask from PNG data. */
8602 init_color_table ();
8604 for (y
= 0; y
< height
; ++y
)
8606 png_byte
*p
= rows
[y
];
8608 for (x
= 0; x
< width
; ++x
)
8615 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8617 /* An alpha channel, aka mask channel, associates variable
8618 transparency with an image. Where other image formats
8619 support binary transparency---fully transparent or fully
8620 opaque---PNG allows up to 254 levels of partial transparency.
8621 The PNG library implements partial transparency by combining
8622 the image with a specified background color.
8624 I'm not sure how to handle this here nicely: because the
8625 background on which the image is displayed may change, for
8626 real alpha channel support, it would be necessary to create
8627 a new image for each possible background.
8629 What I'm doing now is that a mask is created if we have
8630 boolean transparency information. Otherwise I'm using
8631 the frame's background color to combine the image with. */
8636 XPutPixel (mask_img
, x
, y
, *p
> 0);
8642 /* Remember colors allocated for this image. */
8643 img
->colors
= colors_in_color_table (&img
->ncolors
);
8644 free_color_table ();
8647 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8652 img
->height
= height
;
8654 /* Put the image into the pixmap, then free the X image and its buffer. */
8655 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8656 x_destroy_x_image (ximg
);
8658 /* Same for the mask. */
8661 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8662 x_destroy_x_image (mask_img
);
8669 #endif /* HAVE_PNG != 0 */
8673 /***********************************************************************
8675 ***********************************************************************/
8679 /* Work around a warning about HAVE_STDLIB_H being redefined in
8681 #ifdef HAVE_STDLIB_H
8682 #define HAVE_STDLIB_H_1
8683 #undef HAVE_STDLIB_H
8684 #endif /* HAVE_STLIB_H */
8686 #include <jpeglib.h>
8690 #ifdef HAVE_STLIB_H_1
8691 #define HAVE_STDLIB_H 1
8694 static int jpeg_image_p
P_ ((Lisp_Object object
));
8695 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8697 /* The symbol `jpeg' identifying images of this type. */
8701 /* Indices of image specification fields in gs_format, below. */
8703 enum jpeg_keyword_index
8712 JPEG_HEURISTIC_MASK
,
8717 /* Vector of image_keyword structures describing the format
8718 of valid user-defined image specifications. */
8720 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8722 {":type", IMAGE_SYMBOL_VALUE
, 1},
8723 {":data", IMAGE_STRING_VALUE
, 0},
8724 {":file", IMAGE_STRING_VALUE
, 0},
8725 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8726 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8727 {":relief", IMAGE_INTEGER_VALUE
, 0},
8728 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8729 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8730 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8733 /* Structure describing the image type `jpeg'. */
8735 static struct image_type jpeg_type
=
8745 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8748 jpeg_image_p (object
)
8751 struct image_keyword fmt
[JPEG_LAST
];
8753 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8755 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
8758 /* Must specify either the :data or :file keyword. */
8759 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
8763 struct my_jpeg_error_mgr
8765 struct jpeg_error_mgr pub
;
8766 jmp_buf setjmp_buffer
;
8771 my_error_exit (cinfo
)
8774 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8775 longjmp (mgr
->setjmp_buffer
, 1);
8779 /* Init source method for JPEG data source manager. Called by
8780 jpeg_read_header() before any data is actually read. See
8781 libjpeg.doc from the JPEG lib distribution. */
8784 our_init_source (cinfo
)
8785 j_decompress_ptr cinfo
;
8790 /* Fill input buffer method for JPEG data source manager. Called
8791 whenever more data is needed. We read the whole image in one step,
8792 so this only adds a fake end of input marker at the end. */
8795 our_fill_input_buffer (cinfo
)
8796 j_decompress_ptr cinfo
;
8798 /* Insert a fake EOI marker. */
8799 struct jpeg_source_mgr
*src
= cinfo
->src
;
8800 static JOCTET buffer
[2];
8802 buffer
[0] = (JOCTET
) 0xFF;
8803 buffer
[1] = (JOCTET
) JPEG_EOI
;
8805 src
->next_input_byte
= buffer
;
8806 src
->bytes_in_buffer
= 2;
8811 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8812 is the JPEG data source manager. */
8815 our_skip_input_data (cinfo
, num_bytes
)
8816 j_decompress_ptr cinfo
;
8819 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8823 if (num_bytes
> src
->bytes_in_buffer
)
8824 ERREXIT (cinfo
, JERR_INPUT_EOF
);
8826 src
->bytes_in_buffer
-= num_bytes
;
8827 src
->next_input_byte
+= num_bytes
;
8832 /* Method to terminate data source. Called by
8833 jpeg_finish_decompress() after all data has been processed. */
8836 our_term_source (cinfo
)
8837 j_decompress_ptr cinfo
;
8842 /* Set up the JPEG lib for reading an image from DATA which contains
8843 LEN bytes. CINFO is the decompression info structure created for
8844 reading the image. */
8847 jpeg_memory_src (cinfo
, data
, len
)
8848 j_decompress_ptr cinfo
;
8852 struct jpeg_source_mgr
*src
;
8854 if (cinfo
->src
== NULL
)
8856 /* First time for this JPEG object? */
8857 cinfo
->src
= (struct jpeg_source_mgr
*)
8858 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
8859 sizeof (struct jpeg_source_mgr
));
8860 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8861 src
->next_input_byte
= data
;
8864 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8865 src
->init_source
= our_init_source
;
8866 src
->fill_input_buffer
= our_fill_input_buffer
;
8867 src
->skip_input_data
= our_skip_input_data
;
8868 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
8869 src
->term_source
= our_term_source
;
8870 src
->bytes_in_buffer
= len
;
8871 src
->next_input_byte
= data
;
8875 /* Load image IMG for use on frame F. Patterned after example.c
8876 from the JPEG lib. */
8883 struct jpeg_decompress_struct cinfo
;
8884 struct my_jpeg_error_mgr mgr
;
8885 Lisp_Object file
, specified_file
;
8886 Lisp_Object specified_data
;
8887 FILE * volatile fp
= NULL
;
8889 int row_stride
, x
, y
;
8890 XImage
*ximg
= NULL
;
8892 unsigned long *colors
;
8894 struct gcpro gcpro1
;
8896 /* Open the JPEG file. */
8897 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8898 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8902 if (NILP (specified_data
))
8904 file
= x_find_image_file (specified_file
);
8905 if (!STRINGP (file
))
8907 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8912 fp
= fopen (XSTRING (file
)->data
, "r");
8915 image_error ("Cannot open `%s'", file
, Qnil
);
8921 /* Customize libjpeg's error handling to call my_error_exit when an
8922 error is detected. This function will perform a longjmp. */
8923 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8924 mgr
.pub
.error_exit
= my_error_exit
;
8926 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8930 /* Called from my_error_exit. Display a JPEG error. */
8931 char buffer
[JMSG_LENGTH_MAX
];
8932 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8933 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
8934 build_string (buffer
));
8937 /* Close the input file and destroy the JPEG object. */
8939 fclose ((FILE *) fp
);
8940 jpeg_destroy_decompress (&cinfo
);
8942 /* If we already have an XImage, free that. */
8943 x_destroy_x_image (ximg
);
8945 /* Free pixmap and colors. */
8946 x_clear_image (f
, img
);
8952 /* Create the JPEG decompression object. Let it read from fp.
8953 Read the JPEG image header. */
8954 jpeg_create_decompress (&cinfo
);
8956 if (NILP (specified_data
))
8957 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
8959 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
8960 STRING_BYTES (XSTRING (specified_data
)));
8962 jpeg_read_header (&cinfo
, TRUE
);
8964 /* Customize decompression so that color quantization will be used.
8965 Start decompression. */
8966 cinfo
.quantize_colors
= TRUE
;
8967 jpeg_start_decompress (&cinfo
);
8968 width
= img
->width
= cinfo
.output_width
;
8969 height
= img
->height
= cinfo
.output_height
;
8971 /* Create X image and pixmap. */
8972 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8973 longjmp (mgr
.setjmp_buffer
, 2);
8975 /* Allocate colors. When color quantization is used,
8976 cinfo.actual_number_of_colors has been set with the number of
8977 colors generated, and cinfo.colormap is a two-dimensional array
8978 of color indices in the range 0..cinfo.actual_number_of_colors.
8979 No more than 255 colors will be generated. */
8983 if (cinfo
.out_color_components
> 2)
8984 ir
= 0, ig
= 1, ib
= 2;
8985 else if (cinfo
.out_color_components
> 1)
8986 ir
= 0, ig
= 1, ib
= 0;
8988 ir
= 0, ig
= 0, ib
= 0;
8990 /* Use the color table mechanism because it handles colors that
8991 cannot be allocated nicely. Such colors will be replaced with
8992 a default color, and we don't have to care about which colors
8993 can be freed safely, and which can't. */
8994 init_color_table ();
8995 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8998 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
9000 /* Multiply RGB values with 255 because X expects RGB values
9001 in the range 0..0xffff. */
9002 int r
= cinfo
.colormap
[ir
][i
] << 8;
9003 int g
= cinfo
.colormap
[ig
][i
] << 8;
9004 int b
= cinfo
.colormap
[ib
][i
] << 8;
9005 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9008 /* Remember those colors actually allocated. */
9009 img
->colors
= colors_in_color_table (&img
->ncolors
);
9010 free_color_table ();
9014 row_stride
= width
* cinfo
.output_components
;
9015 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9017 for (y
= 0; y
< height
; ++y
)
9019 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9020 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9021 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9025 jpeg_finish_decompress (&cinfo
);
9026 jpeg_destroy_decompress (&cinfo
);
9028 fclose ((FILE *) fp
);
9030 /* Put the image into the pixmap. */
9031 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9032 x_destroy_x_image (ximg
);
9037 #endif /* HAVE_JPEG */
9041 /***********************************************************************
9043 ***********************************************************************/
9049 static int tiff_image_p
P_ ((Lisp_Object object
));
9050 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9052 /* The symbol `tiff' identifying images of this type. */
9056 /* Indices of image specification fields in tiff_format, below. */
9058 enum tiff_keyword_index
9067 TIFF_HEURISTIC_MASK
,
9072 /* Vector of image_keyword structures describing the format
9073 of valid user-defined image specifications. */
9075 static struct image_keyword tiff_format
[TIFF_LAST
] =
9077 {":type", IMAGE_SYMBOL_VALUE
, 1},
9078 {":data", IMAGE_STRING_VALUE
, 0},
9079 {":file", IMAGE_STRING_VALUE
, 0},
9080 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9081 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9082 {":relief", IMAGE_INTEGER_VALUE
, 0},
9083 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9084 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9085 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9088 /* Structure describing the image type `tiff'. */
9090 static struct image_type tiff_type
=
9100 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9103 tiff_image_p (object
)
9106 struct image_keyword fmt
[TIFF_LAST
];
9107 bcopy (tiff_format
, fmt
, sizeof fmt
);
9109 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9112 /* Must specify either the :data or :file keyword. */
9113 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9117 /* Reading from a memory buffer for TIFF images Based on the PNG
9118 memory source, but we have to provide a lot of extra functions.
9121 We really only need to implement read and seek, but I am not
9122 convinced that the TIFF library is smart enough not to destroy
9123 itself if we only hand it the function pointers we need to
9128 unsigned char *bytes
;
9136 tiff_read_from_memory (data
, buf
, size
)
9141 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9143 if (size
> src
->len
- src
->index
)
9145 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9152 tiff_write_from_memory (data
, buf
, size
)
9162 tiff_seek_in_memory (data
, off
, whence
)
9167 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9172 case SEEK_SET
: /* Go from beginning of source. */
9176 case SEEK_END
: /* Go from end of source. */
9177 idx
= src
->len
+ off
;
9180 case SEEK_CUR
: /* Go from current position. */
9181 idx
= src
->index
+ off
;
9184 default: /* Invalid `whence'. */
9188 if (idx
> src
->len
|| idx
< 0)
9197 tiff_close_memory (data
)
9206 tiff_mmap_memory (data
, pbase
, psize
)
9211 /* It is already _IN_ memory. */
9217 tiff_unmap_memory (data
, base
, size
)
9222 /* We don't need to do this. */
9227 tiff_size_of_memory (data
)
9230 return ((tiff_memory_source
*) data
)->len
;
9234 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9242 Lisp_Object file
, specified_file
;
9243 Lisp_Object specified_data
;
9245 int width
, height
, x
, y
;
9249 struct gcpro gcpro1
;
9250 tiff_memory_source memsrc
;
9252 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9253 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9257 if (NILP (specified_data
))
9259 /* Read from a file */
9260 file
= x_find_image_file (specified_file
);
9261 if (!STRINGP (file
))
9263 image_error ("Cannot find image file `%s'", file
, Qnil
);
9268 /* Try to open the image file. */
9269 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9272 image_error ("Cannot open `%s'", file
, Qnil
);
9279 /* Memory source! */
9280 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9281 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9284 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9285 (TIFFReadWriteProc
) tiff_read_from_memory
,
9286 (TIFFReadWriteProc
) tiff_write_from_memory
,
9287 tiff_seek_in_memory
,
9289 tiff_size_of_memory
,
9295 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9301 /* Get width and height of the image, and allocate a raster buffer
9302 of width x height 32-bit values. */
9303 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9304 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9305 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9307 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9311 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9317 /* Create the X image and pixmap. */
9318 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9325 /* Initialize the color table. */
9326 init_color_table ();
9328 /* Process the pixel raster. Origin is in the lower-left corner. */
9329 for (y
= 0; y
< height
; ++y
)
9331 uint32
*row
= buf
+ y
* width
;
9333 for (x
= 0; x
< width
; ++x
)
9335 uint32 abgr
= row
[x
];
9336 int r
= TIFFGetR (abgr
) << 8;
9337 int g
= TIFFGetG (abgr
) << 8;
9338 int b
= TIFFGetB (abgr
) << 8;
9339 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9343 /* Remember the colors allocated for the image. Free the color table. */
9344 img
->colors
= colors_in_color_table (&img
->ncolors
);
9345 free_color_table ();
9347 /* Put the image into the pixmap, then free the X image and its buffer. */
9348 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9349 x_destroy_x_image (ximg
);
9353 img
->height
= height
;
9359 #endif /* HAVE_TIFF != 0 */
9363 /***********************************************************************
9365 ***********************************************************************/
9369 #include <gif_lib.h>
9371 static int gif_image_p
P_ ((Lisp_Object object
));
9372 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9374 /* The symbol `gif' identifying images of this type. */
9378 /* Indices of image specification fields in gif_format, below. */
9380 enum gif_keyword_index
9395 /* Vector of image_keyword structures describing the format
9396 of valid user-defined image specifications. */
9398 static struct image_keyword gif_format
[GIF_LAST
] =
9400 {":type", IMAGE_SYMBOL_VALUE
, 1},
9401 {":data", IMAGE_STRING_VALUE
, 0},
9402 {":file", IMAGE_STRING_VALUE
, 0},
9403 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9404 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9405 {":relief", IMAGE_INTEGER_VALUE
, 0},
9406 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9407 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9408 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9409 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
9412 /* Structure describing the image type `gif'. */
9414 static struct image_type gif_type
=
9424 /* Return non-zero if OBJECT is a valid GIF image specification. */
9427 gif_image_p (object
)
9430 struct image_keyword fmt
[GIF_LAST
];
9431 bcopy (gif_format
, fmt
, sizeof fmt
);
9433 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
9436 /* Must specify either the :data or :file keyword. */
9437 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9441 /* Reading a GIF image from memory
9442 Based on the PNG memory stuff to a certain extent. */
9446 unsigned char *bytes
;
9453 /* Make the current memory source available to gif_read_from_memory.
9454 It's done this way because not all versions of libungif support
9455 a UserData field in the GifFileType structure. */
9456 static gif_memory_source
*current_gif_memory_src
;
9459 gif_read_from_memory (file
, buf
, len
)
9464 gif_memory_source
*src
= current_gif_memory_src
;
9466 if (len
> src
->len
- src
->index
)
9469 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9475 /* Load GIF image IMG for use on frame F. Value is non-zero if
9483 Lisp_Object file
, specified_file
;
9484 Lisp_Object specified_data
;
9485 int rc
, width
, height
, x
, y
, i
;
9487 ColorMapObject
*gif_color_map
;
9488 unsigned long pixel_colors
[256];
9490 struct gcpro gcpro1
;
9492 int ino
, image_left
, image_top
, image_width
, image_height
;
9493 gif_memory_source memsrc
;
9494 unsigned char *raster
;
9496 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9497 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9501 if (NILP (specified_data
))
9503 file
= x_find_image_file (specified_file
);
9504 if (!STRINGP (file
))
9506 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9511 /* Open the GIF file. */
9512 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9515 image_error ("Cannot open `%s'", file
, Qnil
);
9522 /* Read from memory! */
9523 current_gif_memory_src
= &memsrc
;
9524 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9525 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9528 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
9531 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
9537 /* Read entire contents. */
9538 rc
= DGifSlurp (gif
);
9539 if (rc
== GIF_ERROR
)
9541 image_error ("Error reading `%s'", img
->spec
, Qnil
);
9542 DGifCloseFile (gif
);
9547 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
9548 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
9549 if (ino
>= gif
->ImageCount
)
9551 image_error ("Invalid image number `%s' in image `%s'",
9553 DGifCloseFile (gif
);
9558 width
= img
->width
= gif
->SWidth
;
9559 height
= img
->height
= gif
->SHeight
;
9561 /* Create the X image and pixmap. */
9562 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9564 DGifCloseFile (gif
);
9569 /* Allocate colors. */
9570 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
9572 gif_color_map
= gif
->SColorMap
;
9573 init_color_table ();
9574 bzero (pixel_colors
, sizeof pixel_colors
);
9576 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9578 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9579 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9580 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9581 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9584 img
->colors
= colors_in_color_table (&img
->ncolors
);
9585 free_color_table ();
9587 /* Clear the part of the screen image that are not covered by
9588 the image from the GIF file. Full animated GIF support
9589 requires more than can be done here (see the gif89 spec,
9590 disposal methods). Let's simply assume that the part
9591 not covered by a sub-image is in the frame's background color. */
9592 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9593 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9594 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9595 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9597 for (y
= 0; y
< image_top
; ++y
)
9598 for (x
= 0; x
< width
; ++x
)
9599 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9601 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9602 for (x
= 0; x
< width
; ++x
)
9603 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9605 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9607 for (x
= 0; x
< image_left
; ++x
)
9608 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9609 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9610 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9613 /* Read the GIF image into the X image. We use a local variable
9614 `raster' here because RasterBits below is a char *, and invites
9615 problems with bytes >= 0x80. */
9616 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9618 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9620 static int interlace_start
[] = {0, 4, 2, 1};
9621 static int interlace_increment
[] = {8, 8, 4, 2};
9623 int row
= interlace_start
[0];
9627 for (y
= 0; y
< image_height
; y
++)
9629 if (row
>= image_height
)
9631 row
= interlace_start
[++pass
];
9632 while (row
>= image_height
)
9633 row
= interlace_start
[++pass
];
9636 for (x
= 0; x
< image_width
; x
++)
9638 int i
= raster
[(y
* image_width
) + x
];
9639 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9643 row
+= interlace_increment
[pass
];
9648 for (y
= 0; y
< image_height
; ++y
)
9649 for (x
= 0; x
< image_width
; ++x
)
9651 int i
= raster
[y
* image_width
+ x
];
9652 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9656 DGifCloseFile (gif
);
9658 /* Put the image into the pixmap, then free the X image and its buffer. */
9659 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9660 x_destroy_x_image (ximg
);
9666 #endif /* HAVE_GIF != 0 */
9670 /***********************************************************************
9672 ***********************************************************************/
9674 static int gs_image_p
P_ ((Lisp_Object object
));
9675 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9676 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9678 /* The symbol `postscript' identifying images of this type. */
9680 Lisp_Object Qpostscript
;
9682 /* Keyword symbols. */
9684 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9686 /* Indices of image specification fields in gs_format, below. */
9688 enum gs_keyword_index
9705 /* Vector of image_keyword structures describing the format
9706 of valid user-defined image specifications. */
9708 static struct image_keyword gs_format
[GS_LAST
] =
9710 {":type", IMAGE_SYMBOL_VALUE
, 1},
9711 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9712 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9713 {":file", IMAGE_STRING_VALUE
, 1},
9714 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9715 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9716 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9717 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9718 {":relief", IMAGE_INTEGER_VALUE
, 0},
9719 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9720 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9721 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9724 /* Structure describing the image type `ghostscript'. */
9726 static struct image_type gs_type
=
9736 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9739 gs_clear_image (f
, img
)
9743 /* IMG->data.ptr_val may contain a recorded colormap. */
9744 xfree (img
->data
.ptr_val
);
9745 x_clear_image (f
, img
);
9749 /* Return non-zero if OBJECT is a valid Ghostscript image
9756 struct image_keyword fmt
[GS_LAST
];
9760 bcopy (gs_format
, fmt
, sizeof fmt
);
9762 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9765 /* Bounding box must be a list or vector containing 4 integers. */
9766 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9769 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9770 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9775 else if (VECTORP (tem
))
9777 if (XVECTOR (tem
)->size
!= 4)
9779 for (i
= 0; i
< 4; ++i
)
9780 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9790 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9799 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9800 struct gcpro gcpro1
, gcpro2
;
9802 double in_width
, in_height
;
9803 Lisp_Object pixel_colors
= Qnil
;
9805 /* Compute pixel size of pixmap needed from the given size in the
9806 image specification. Sizes in the specification are in pt. 1 pt
9807 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9809 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9810 in_width
= XFASTINT (pt_width
) / 72.0;
9811 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9812 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9813 in_height
= XFASTINT (pt_height
) / 72.0;
9814 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9816 /* Create the pixmap. */
9817 xassert (img
->pixmap
== None
);
9818 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9819 img
->width
, img
->height
,
9820 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9824 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9828 /* Call the loader to fill the pixmap. It returns a process object
9829 if successful. We do not record_unwind_protect here because
9830 other places in redisplay like calling window scroll functions
9831 don't either. Let the Lisp loader use `unwind-protect' instead. */
9832 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9834 sprintf (buffer
, "%lu %lu",
9835 (unsigned long) FRAME_X_WINDOW (f
),
9836 (unsigned long) img
->pixmap
);
9837 window_and_pixmap_id
= build_string (buffer
);
9839 sprintf (buffer
, "%lu %lu",
9840 FRAME_FOREGROUND_PIXEL (f
),
9841 FRAME_BACKGROUND_PIXEL (f
));
9842 pixel_colors
= build_string (buffer
);
9844 XSETFRAME (frame
, f
);
9845 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9847 loader
= intern ("gs-load-image");
9849 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9850 make_number (img
->width
),
9851 make_number (img
->height
),
9852 window_and_pixmap_id
,
9855 return PROCESSP (img
->data
.lisp_val
);
9859 /* Kill the Ghostscript process that was started to fill PIXMAP on
9860 frame F. Called from XTread_socket when receiving an event
9861 telling Emacs that Ghostscript has finished drawing. */
9864 x_kill_gs_process (pixmap
, f
)
9868 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9872 /* Find the image containing PIXMAP. */
9873 for (i
= 0; i
< c
->used
; ++i
)
9874 if (c
->images
[i
]->pixmap
== pixmap
)
9877 /* Kill the GS process. We should have found PIXMAP in the image
9878 cache and its image should contain a process object. */
9879 xassert (i
< c
->used
);
9881 xassert (PROCESSP (img
->data
.lisp_val
));
9882 Fkill_process (img
->data
.lisp_val
, Qnil
);
9883 img
->data
.lisp_val
= Qnil
;
9885 /* On displays with a mutable colormap, figure out the colors
9886 allocated for the image by looking at the pixels of an XImage for
9888 class = FRAME_X_VISUAL (f
)->class;
9889 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9895 /* Try to get an XImage for img->pixmep. */
9896 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9897 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9902 /* Initialize the color table. */
9903 init_color_table ();
9905 /* For each pixel of the image, look its color up in the
9906 color table. After having done so, the color table will
9907 contain an entry for each color used by the image. */
9908 for (y
= 0; y
< img
->height
; ++y
)
9909 for (x
= 0; x
< img
->width
; ++x
)
9911 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9912 lookup_pixel_color (f
, pixel
);
9915 /* Record colors in the image. Free color table and XImage. */
9916 img
->colors
= colors_in_color_table (&img
->ncolors
);
9917 free_color_table ();
9918 XDestroyImage (ximg
);
9920 #if 0 /* This doesn't seem to be the case. If we free the colors
9921 here, we get a BadAccess later in x_clear_image when
9922 freeing the colors. */
9923 /* We have allocated colors once, but Ghostscript has also
9924 allocated colors on behalf of us. So, to get the
9925 reference counts right, free them once. */
9927 x_free_colors (f
, img
->colors
, img
->ncolors
);
9931 image_error ("Cannot get X image of `%s'; colors will not be freed",
9940 /***********************************************************************
9942 ***********************************************************************/
9944 DEFUN ("x-change-window-property", Fx_change_window_property
,
9945 Sx_change_window_property
, 2, 3, 0,
9946 "Change window property PROP to VALUE on the X window of FRAME.\n\
9947 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9948 selected frame. Value is VALUE.")
9949 (prop
, value
, frame
)
9950 Lisp_Object frame
, prop
, value
;
9952 struct frame
*f
= check_x_frame (frame
);
9955 CHECK_STRING (prop
, 1);
9956 CHECK_STRING (value
, 2);
9959 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9960 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9961 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9962 XSTRING (value
)->data
, XSTRING (value
)->size
);
9964 /* Make sure the property is set when we return. */
9965 XFlush (FRAME_X_DISPLAY (f
));
9972 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9973 Sx_delete_window_property
, 1, 2, 0,
9974 "Remove window property PROP from X window of FRAME.\n\
9975 FRAME nil or omitted means use the selected frame. Value is PROP.")
9977 Lisp_Object prop
, frame
;
9979 struct frame
*f
= check_x_frame (frame
);
9982 CHECK_STRING (prop
, 1);
9984 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9985 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9987 /* Make sure the property is removed when we return. */
9988 XFlush (FRAME_X_DISPLAY (f
));
9995 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9997 "Value is the value of window property PROP on FRAME.\n\
9998 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9999 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10002 Lisp_Object prop
, frame
;
10004 struct frame
*f
= check_x_frame (frame
);
10007 Lisp_Object prop_value
= Qnil
;
10008 char *tmp_data
= NULL
;
10011 unsigned long actual_size
, bytes_remaining
;
10013 CHECK_STRING (prop
, 1);
10015 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10016 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10017 prop_atom
, 0, 0, False
, XA_STRING
,
10018 &actual_type
, &actual_format
, &actual_size
,
10019 &bytes_remaining
, (unsigned char **) &tmp_data
);
10022 int size
= bytes_remaining
;
10027 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10028 prop_atom
, 0, bytes_remaining
,
10030 &actual_type
, &actual_format
,
10031 &actual_size
, &bytes_remaining
,
10032 (unsigned char **) &tmp_data
);
10034 prop_value
= make_string (tmp_data
, size
);
10045 /***********************************************************************
10047 ***********************************************************************/
10049 /* If non-null, an asynchronous timer that, when it expires, displays
10050 a busy cursor on all frames. */
10052 static struct atimer
*busy_cursor_atimer
;
10054 /* Non-zero means a busy cursor is currently shown. */
10056 static int busy_cursor_shown_p
;
10058 /* Number of seconds to wait before displaying a busy cursor. */
10060 static Lisp_Object Vbusy_cursor_delay
;
10062 /* Default number of seconds to wait before displaying a busy
10065 #define DEFAULT_BUSY_CURSOR_DELAY 1
10067 /* Function prototypes. */
10069 static void show_busy_cursor
P_ ((struct atimer
*));
10070 static void hide_busy_cursor
P_ ((void));
10073 /* Cancel a currently active busy-cursor timer, and start a new one. */
10076 start_busy_cursor ()
10079 int secs
, usecs
= 0;
10081 cancel_busy_cursor ();
10083 if (INTEGERP (Vbusy_cursor_delay
)
10084 && XINT (Vbusy_cursor_delay
) > 0)
10085 secs
= XFASTINT (Vbusy_cursor_delay
);
10086 else if (FLOATP (Vbusy_cursor_delay
)
10087 && XFLOAT_DATA (Vbusy_cursor_delay
) > 0)
10090 tem
= Ftruncate (Vbusy_cursor_delay
, Qnil
);
10091 secs
= XFASTINT (tem
);
10092 usecs
= (XFLOAT_DATA (Vbusy_cursor_delay
) - secs
) * 1000000;
10095 secs
= DEFAULT_BUSY_CURSOR_DELAY
;
10097 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10098 busy_cursor_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10099 show_busy_cursor
, NULL
);
10103 /* Cancel the busy cursor timer if active, hide a busy cursor if
10107 cancel_busy_cursor ()
10109 if (busy_cursor_atimer
)
10111 cancel_atimer (busy_cursor_atimer
);
10112 busy_cursor_atimer
= NULL
;
10115 if (busy_cursor_shown_p
)
10116 hide_busy_cursor ();
10120 /* Timer function of busy_cursor_atimer. TIMER is equal to
10121 busy_cursor_atimer.
10123 Display a busy cursor on all frames by mapping the frames'
10124 busy_window. Set the busy_p flag in the frames' output_data.x
10125 structure to indicate that a busy cursor is shown on the
10129 show_busy_cursor (timer
)
10130 struct atimer
*timer
;
10132 /* The timer implementation will cancel this timer automatically
10133 after this function has run. Set busy_cursor_atimer to null
10134 so that we know the timer doesn't have to be canceled. */
10135 busy_cursor_atimer
= NULL
;
10137 if (!busy_cursor_shown_p
)
10139 Lisp_Object rest
, frame
;
10143 FOR_EACH_FRAME (rest
, frame
)
10144 if (FRAME_X_P (XFRAME (frame
)))
10146 struct frame
*f
= XFRAME (frame
);
10148 f
->output_data
.x
->busy_p
= 1;
10150 if (!f
->output_data
.x
->busy_window
)
10152 unsigned long mask
= CWCursor
;
10153 XSetWindowAttributes attrs
;
10155 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
10157 f
->output_data
.x
->busy_window
10158 = XCreateWindow (FRAME_X_DISPLAY (f
),
10159 FRAME_OUTER_WINDOW (f
),
10160 0, 0, 32000, 32000, 0, 0,
10166 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10167 XFlush (FRAME_X_DISPLAY (f
));
10170 busy_cursor_shown_p
= 1;
10176 /* Hide the busy cursor on all frames, if it is currently shown. */
10179 hide_busy_cursor ()
10181 if (busy_cursor_shown_p
)
10183 Lisp_Object rest
, frame
;
10186 FOR_EACH_FRAME (rest
, frame
)
10188 struct frame
*f
= XFRAME (frame
);
10191 /* Watch out for newly created frames. */
10192 && f
->output_data
.x
->busy_window
)
10194 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10195 /* Sync here because XTread_socket looks at the busy_p flag
10196 that is reset to zero below. */
10197 XSync (FRAME_X_DISPLAY (f
), False
);
10198 f
->output_data
.x
->busy_p
= 0;
10202 busy_cursor_shown_p
= 0;
10209 /***********************************************************************
10211 ***********************************************************************/
10213 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10216 /* The frame of a currently visible tooltip, or null. */
10218 struct frame
*tip_frame
;
10220 /* If non-nil, a timer started that hides the last tooltip when it
10223 Lisp_Object tip_timer
;
10226 /* Create a frame for a tooltip on the display described by DPYINFO.
10227 PARMS is a list of frame parameters. Value is the frame. */
10230 x_create_tip_frame (dpyinfo
, parms
)
10231 struct x_display_info
*dpyinfo
;
10235 Lisp_Object frame
, tem
;
10237 long window_prompting
= 0;
10239 int count
= specpdl_ptr
- specpdl
;
10240 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10245 /* Use this general default value to start with until we know if
10246 this frame has a specified name. */
10247 Vx_resource_name
= Vinvocation_name
;
10249 #ifdef MULTI_KBOARD
10250 kb
= dpyinfo
->kboard
;
10252 kb
= &the_only_kboard
;
10255 /* Get the name of the frame to use for resource lookup. */
10256 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10257 if (!STRINGP (name
)
10258 && !EQ (name
, Qunbound
)
10260 error ("Invalid frame name--not a string or nil");
10261 Vx_resource_name
= name
;
10264 GCPRO3 (parms
, name
, frame
);
10265 tip_frame
= f
= make_frame (1);
10266 XSETFRAME (frame
, f
);
10267 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10269 f
->output_method
= output_x_window
;
10270 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10271 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10272 f
->output_data
.x
->icon_bitmap
= -1;
10273 f
->output_data
.x
->fontset
= -1;
10274 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10275 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10276 f
->icon_name
= Qnil
;
10277 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10278 #ifdef MULTI_KBOARD
10279 FRAME_KBOARD (f
) = kb
;
10281 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10282 f
->output_data
.x
->explicit_parent
= 0;
10284 /* These colors will be set anyway later, but it's important
10285 to get the color reference counts right, so initialize them! */
10288 struct gcpro gcpro1
;
10290 black
= build_string ("black");
10292 f
->output_data
.x
->foreground_pixel
10293 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10294 f
->output_data
.x
->background_pixel
10295 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10296 f
->output_data
.x
->cursor_pixel
10297 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10298 f
->output_data
.x
->cursor_foreground_pixel
10299 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10300 f
->output_data
.x
->border_pixel
10301 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10302 f
->output_data
.x
->mouse_pixel
10303 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10307 /* Set the name; the functions to which we pass f expect the name to
10309 if (EQ (name
, Qunbound
) || NILP (name
))
10311 f
->name
= build_string (dpyinfo
->x_id_name
);
10312 f
->explicit_name
= 0;
10317 f
->explicit_name
= 1;
10318 /* use the frame's title when getting resources for this frame. */
10319 specbind (Qx_resource_name
, name
);
10322 /* Extract the window parameters from the supplied values
10323 that are needed to determine window geometry. */
10327 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10330 /* First, try whatever font the caller has specified. */
10331 if (STRINGP (font
))
10333 tem
= Fquery_fontset (font
, Qnil
);
10335 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10337 font
= x_new_font (f
, XSTRING (font
)->data
);
10340 /* Try out a font which we hope has bold and italic variations. */
10341 if (!STRINGP (font
))
10342 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10343 if (!STRINGP (font
))
10344 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10345 if (! STRINGP (font
))
10346 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10347 if (! STRINGP (font
))
10348 /* This was formerly the first thing tried, but it finds too many fonts
10349 and takes too long. */
10350 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10351 /* If those didn't work, look for something which will at least work. */
10352 if (! STRINGP (font
))
10353 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10355 if (! STRINGP (font
))
10356 font
= build_string ("fixed");
10358 x_default_parameter (f
, parms
, Qfont
, font
,
10359 "font", "Font", RES_TYPE_STRING
);
10362 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10363 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10365 /* This defaults to 2 in order to match xterm. We recognize either
10366 internalBorderWidth or internalBorder (which is what xterm calls
10368 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10372 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10373 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10374 if (! EQ (value
, Qunbound
))
10375 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10379 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10380 "internalBorderWidth", "internalBorderWidth",
10383 /* Also do the stuff which must be set before the window exists. */
10384 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10385 "foreground", "Foreground", RES_TYPE_STRING
);
10386 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10387 "background", "Background", RES_TYPE_STRING
);
10388 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10389 "pointerColor", "Foreground", RES_TYPE_STRING
);
10390 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10391 "cursorColor", "Foreground", RES_TYPE_STRING
);
10392 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10393 "borderColor", "BorderColor", RES_TYPE_STRING
);
10395 /* Init faces before x_default_parameter is called for scroll-bar
10396 parameters because that function calls x_set_scroll_bar_width,
10397 which calls change_frame_size, which calls Fset_window_buffer,
10398 which runs hooks, which call Fvertical_motion. At the end, we
10399 end up in init_iterator with a null face cache, which should not
10401 init_frame_faces (f
);
10403 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10404 window_prompting
= x_figure_window_size (f
, parms
);
10406 if (window_prompting
& XNegative
)
10408 if (window_prompting
& YNegative
)
10409 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10411 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10415 if (window_prompting
& YNegative
)
10416 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10418 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10421 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10423 XSetWindowAttributes attrs
;
10424 unsigned long mask
;
10427 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
10428 /* Window managers look at the override-redirect flag to determine
10429 whether or net to give windows a decoration (Xlib spec, chapter
10431 attrs
.override_redirect
= True
;
10432 attrs
.save_under
= True
;
10433 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
10434 /* Arrange for getting MapNotify and UnmapNotify events. */
10435 attrs
.event_mask
= StructureNotifyMask
;
10437 = FRAME_X_WINDOW (f
)
10438 = XCreateWindow (FRAME_X_DISPLAY (f
),
10439 FRAME_X_DISPLAY_INFO (f
)->root_window
,
10440 /* x, y, width, height */
10444 CopyFromParent
, InputOutput
, CopyFromParent
,
10451 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
10452 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10453 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
10454 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10455 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
10456 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
10458 /* Dimensions, especially f->height, must be done via change_frame_size.
10459 Change will not be effected unless different from the current
10462 height
= f
->height
;
10464 SET_FRAME_WIDTH (f
, 0);
10465 change_frame_size (f
, height
, width
, 1, 0, 0);
10471 /* It is now ok to make the frame official even if we get an error
10472 below. And the frame needs to be on Vframe_list or making it
10473 visible won't work. */
10474 Vframe_list
= Fcons (frame
, Vframe_list
);
10476 /* Now that the frame is official, it counts as a reference to
10478 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
10480 return unbind_to (count
, frame
);
10484 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
10485 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10486 A tooltip window is a small X window displaying a string.\n\
10488 FRAME nil or omitted means use the selected frame.\n\
10490 PARMS is an optional list of frame parameters which can be\n\
10491 used to change the tooltip's appearance.\n\
10493 Automatically hide the tooltip after TIMEOUT seconds.\n\
10494 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10496 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10497 the tooltip is displayed at that x-position. Otherwise it is\n\
10498 displayed at the mouse position, with offset DX added (default is 5 if\n\
10499 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10500 parameter is specified, it determines the y-position of the tooltip\n\
10501 window, otherwise it is displayed at the mouse position, with offset\n\
10502 DY added (default is -5).")
10503 (string
, frame
, parms
, timeout
, dx
, dy
)
10504 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
10508 Window root
, child
;
10509 Lisp_Object buffer
, top
, left
;
10510 struct buffer
*old_buffer
;
10511 struct text_pos pos
;
10512 int i
, width
, height
;
10513 int root_x
, root_y
, win_x
, win_y
;
10515 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
10516 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
10517 int count
= specpdl_ptr
- specpdl
;
10519 specbind (Qinhibit_redisplay
, Qt
);
10521 GCPRO4 (string
, parms
, frame
, timeout
);
10523 CHECK_STRING (string
, 0);
10524 f
= check_x_frame (frame
);
10525 if (NILP (timeout
))
10526 timeout
= make_number (5);
10528 CHECK_NATNUM (timeout
, 2);
10531 dx
= make_number (5);
10533 CHECK_NUMBER (dx
, 5);
10536 dy
= make_number (-5);
10538 CHECK_NUMBER (dy
, 6);
10540 /* Hide a previous tip, if any. */
10543 /* Add default values to frame parameters. */
10544 if (NILP (Fassq (Qname
, parms
)))
10545 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
10546 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10547 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
10548 if (NILP (Fassq (Qborder_width
, parms
)))
10549 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
10550 if (NILP (Fassq (Qborder_color
, parms
)))
10551 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
10552 if (NILP (Fassq (Qbackground_color
, parms
)))
10553 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
10556 /* Create a frame for the tooltip, and record it in the global
10557 variable tip_frame. */
10558 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
10559 tip_frame
= f
= XFRAME (frame
);
10561 /* Set up the frame's root window. Currently we use a size of 80
10562 columns x 40 lines. If someone wants to show a larger tip, he
10563 will loose. I don't think this is a realistic case. */
10564 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
10565 w
->left
= w
->top
= make_number (0);
10566 w
->width
= make_number (80);
10567 w
->height
= make_number (40);
10569 w
->pseudo_window_p
= 1;
10571 /* Display the tooltip text in a temporary buffer. */
10572 buffer
= Fget_buffer_create (build_string (" *tip*"));
10573 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10574 old_buffer
= current_buffer
;
10575 set_buffer_internal_1 (XBUFFER (buffer
));
10577 Finsert (1, &string
);
10578 clear_glyph_matrix (w
->desired_matrix
);
10579 clear_glyph_matrix (w
->current_matrix
);
10580 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
10581 try_window (FRAME_ROOT_WINDOW (f
), pos
);
10583 /* Compute width and height of the tooltip. */
10584 width
= height
= 0;
10585 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
10587 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
10588 struct glyph
*last
;
10591 /* Stop at the first empty row at the end. */
10592 if (!row
->enabled_p
|| !row
->displays_text_p
)
10595 /* Let the row go over the full width of the frame. */
10596 row
->full_width_p
= 1;
10598 /* There's a glyph at the end of rows that is used to place
10599 the cursor there. Don't include the width of this glyph. */
10600 if (row
->used
[TEXT_AREA
])
10602 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
10603 row_width
= row
->pixel_width
- last
->pixel_width
;
10606 row_width
= row
->pixel_width
;
10608 height
+= row
->height
;
10609 width
= max (width
, row_width
);
10612 /* Add the frame's internal border to the width and height the X
10613 window should have. */
10614 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10615 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10617 /* User-specified position? */
10618 left
= Fcdr (Fassq (Qleft
, parms
));
10619 top
= Fcdr (Fassq (Qtop
, parms
));
10621 /* Move the tooltip window where the mouse pointer is. Resize and
10624 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10625 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
10628 root_x
+= XINT (dx
);
10629 root_y
+= XINT (dy
);
10631 if (INTEGERP (left
))
10632 root_x
= XINT (left
);
10633 if (INTEGERP (top
))
10634 root_y
= XINT (top
);
10637 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10638 root_x
, root_y
- height
, width
, height
);
10639 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10642 /* Draw into the window. */
10643 w
->must_be_updated_p
= 1;
10644 update_single_window (w
, 1);
10646 /* Restore original current buffer. */
10647 set_buffer_internal_1 (old_buffer
);
10648 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
10650 /* Let the tip disappear after timeout seconds. */
10651 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
10652 intern ("x-hide-tip"));
10655 return unbind_to (count
, Qnil
);
10659 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
10660 "Hide the current tooltip window, if there is any.\n\
10661 Value is t is tooltip was open, nil otherwise.")
10664 int count
= specpdl_ptr
- specpdl
;
10667 specbind (Qinhibit_redisplay
, Qt
);
10669 if (!NILP (tip_timer
))
10671 call1 (intern ("cancel-timer"), tip_timer
);
10679 XSETFRAME (frame
, tip_frame
);
10680 Fdelete_frame (frame
, Qt
);
10685 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
10690 /***********************************************************************
10691 File selection dialog
10692 ***********************************************************************/
10696 /* Callback for "OK" and "Cancel" on file selection dialog. */
10699 file_dialog_cb (widget
, client_data
, call_data
)
10701 XtPointer call_data
, client_data
;
10703 int *result
= (int *) client_data
;
10704 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
10705 *result
= cb
->reason
;
10709 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
10710 "Read file name, prompting with PROMPT in directory DIR.\n\
10711 Use a file selection dialog.\n\
10712 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10713 specified. Don't let the user enter a file name in the file\n\
10714 selection dialog's entry field, if MUSTMATCH is non-nil.")
10715 (prompt
, dir
, default_filename
, mustmatch
)
10716 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
10719 struct frame
*f
= SELECTED_FRAME ();
10720 Lisp_Object file
= Qnil
;
10721 Widget dialog
, text
, list
, help
;
10724 extern XtAppContext Xt_app_con
;
10726 XmString dir_xmstring
, pattern_xmstring
;
10727 int popup_activated_flag
;
10728 int count
= specpdl_ptr
- specpdl
;
10729 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
10731 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
10732 CHECK_STRING (prompt
, 0);
10733 CHECK_STRING (dir
, 1);
10735 /* Prevent redisplay. */
10736 specbind (Qinhibit_redisplay
, Qt
);
10740 /* Create the dialog with PROMPT as title, using DIR as initial
10741 directory and using "*" as pattern. */
10742 dir
= Fexpand_file_name (dir
, Qnil
);
10743 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
10744 pattern_xmstring
= XmStringCreateLocalized ("*");
10746 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
10747 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
10748 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
10749 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
10750 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
10751 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
10753 XmStringFree (dir_xmstring
);
10754 XmStringFree (pattern_xmstring
);
10756 /* Add callbacks for OK and Cancel. */
10757 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
10758 (XtPointer
) &result
);
10759 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
10760 (XtPointer
) &result
);
10762 /* Disable the help button since we can't display help. */
10763 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
10764 XtSetSensitive (help
, False
);
10766 /* Mark OK button as default. */
10767 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
10768 XmNshowAsDefault
, True
, NULL
);
10770 /* If MUSTMATCH is non-nil, disable the file entry field of the
10771 dialog, so that the user must select a file from the files list
10772 box. We can't remove it because we wouldn't have a way to get at
10773 the result file name, then. */
10774 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
10775 if (!NILP (mustmatch
))
10778 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
10779 XtSetSensitive (text
, False
);
10780 XtSetSensitive (label
, False
);
10783 /* Manage the dialog, so that list boxes get filled. */
10784 XtManageChild (dialog
);
10786 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10787 must include the path for this to work. */
10788 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
10789 if (STRINGP (default_filename
))
10791 XmString default_xmstring
;
10795 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
10797 if (!XmListItemExists (list
, default_xmstring
))
10799 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10800 XmListAddItem (list
, default_xmstring
, 0);
10804 item_pos
= XmListItemPos (list
, default_xmstring
);
10805 XmStringFree (default_xmstring
);
10807 /* Select the item and scroll it into view. */
10808 XmListSelectPos (list
, item_pos
, True
);
10809 XmListSetPos (list
, item_pos
);
10812 #ifdef HAVE_MOTIF_2_1
10814 /* Process events until the user presses Cancel or OK. */
10816 while (result
== 0 || XtAppPending (Xt_app_con
))
10817 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
10819 #else /* not HAVE_MOTIF_2_1 */
10821 /* Process all events until the user presses Cancel or OK. */
10822 for (result
= 0; result
== 0;)
10825 Widget widget
, parent
;
10827 XtAppNextEvent (Xt_app_con
, &event
);
10829 /* See if the receiver of the event is one of the widgets of
10830 the file selection dialog. If so, dispatch it. If not,
10832 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
10834 while (parent
&& parent
!= dialog
)
10835 parent
= XtParent (parent
);
10837 if (parent
== dialog
10838 || (event
.type
== Expose
10839 && !process_expose_from_menu (event
)))
10840 XtDispatchEvent (&event
);
10843 #endif /* not HAVE_MOTIF_2_1 */
10845 /* Get the result. */
10846 if (result
== XmCR_OK
)
10851 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
10852 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
10853 XmStringFree (text
);
10854 file
= build_string (data
);
10861 XtUnmanageChild (dialog
);
10862 XtDestroyWidget (dialog
);
10866 /* Make "Cancel" equivalent to C-g. */
10868 Fsignal (Qquit
, Qnil
);
10870 return unbind_to (count
, file
);
10873 #endif /* USE_MOTIF */
10877 /***********************************************************************
10879 ***********************************************************************/
10884 /* This is zero if not using X windows. */
10887 /* The section below is built by the lisp expression at the top of the file,
10888 just above where these variables are declared. */
10889 /*&&& init symbols here &&&*/
10890 Qauto_raise
= intern ("auto-raise");
10891 staticpro (&Qauto_raise
);
10892 Qauto_lower
= intern ("auto-lower");
10893 staticpro (&Qauto_lower
);
10894 Qbar
= intern ("bar");
10896 Qborder_color
= intern ("border-color");
10897 staticpro (&Qborder_color
);
10898 Qborder_width
= intern ("border-width");
10899 staticpro (&Qborder_width
);
10900 Qbox
= intern ("box");
10902 Qcursor_color
= intern ("cursor-color");
10903 staticpro (&Qcursor_color
);
10904 Qcursor_type
= intern ("cursor-type");
10905 staticpro (&Qcursor_type
);
10906 Qgeometry
= intern ("geometry");
10907 staticpro (&Qgeometry
);
10908 Qicon_left
= intern ("icon-left");
10909 staticpro (&Qicon_left
);
10910 Qicon_top
= intern ("icon-top");
10911 staticpro (&Qicon_top
);
10912 Qicon_type
= intern ("icon-type");
10913 staticpro (&Qicon_type
);
10914 Qicon_name
= intern ("icon-name");
10915 staticpro (&Qicon_name
);
10916 Qinternal_border_width
= intern ("internal-border-width");
10917 staticpro (&Qinternal_border_width
);
10918 Qleft
= intern ("left");
10919 staticpro (&Qleft
);
10920 Qright
= intern ("right");
10921 staticpro (&Qright
);
10922 Qmouse_color
= intern ("mouse-color");
10923 staticpro (&Qmouse_color
);
10924 Qnone
= intern ("none");
10925 staticpro (&Qnone
);
10926 Qparent_id
= intern ("parent-id");
10927 staticpro (&Qparent_id
);
10928 Qscroll_bar_width
= intern ("scroll-bar-width");
10929 staticpro (&Qscroll_bar_width
);
10930 Qsuppress_icon
= intern ("suppress-icon");
10931 staticpro (&Qsuppress_icon
);
10932 Qundefined_color
= intern ("undefined-color");
10933 staticpro (&Qundefined_color
);
10934 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10935 staticpro (&Qvertical_scroll_bars
);
10936 Qvisibility
= intern ("visibility");
10937 staticpro (&Qvisibility
);
10938 Qwindow_id
= intern ("window-id");
10939 staticpro (&Qwindow_id
);
10940 Qouter_window_id
= intern ("outer-window-id");
10941 staticpro (&Qouter_window_id
);
10942 Qx_frame_parameter
= intern ("x-frame-parameter");
10943 staticpro (&Qx_frame_parameter
);
10944 Qx_resource_name
= intern ("x-resource-name");
10945 staticpro (&Qx_resource_name
);
10946 Quser_position
= intern ("user-position");
10947 staticpro (&Quser_position
);
10948 Quser_size
= intern ("user-size");
10949 staticpro (&Quser_size
);
10950 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10951 staticpro (&Qscroll_bar_foreground
);
10952 Qscroll_bar_background
= intern ("scroll-bar-background");
10953 staticpro (&Qscroll_bar_background
);
10954 Qscreen_gamma
= intern ("screen-gamma");
10955 staticpro (&Qscreen_gamma
);
10956 Qline_spacing
= intern ("line-spacing");
10957 staticpro (&Qline_spacing
);
10958 Qcenter
= intern ("center");
10959 staticpro (&Qcenter
);
10960 Qcompound_text
= intern ("compound-text");
10961 staticpro (&Qcompound_text
);
10962 /* This is the end of symbol initialization. */
10964 /* Text property `display' should be nonsticky by default. */
10965 Vtext_property_default_nonsticky
10966 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
10969 Qlaplace
= intern ("laplace");
10970 staticpro (&Qlaplace
);
10971 Qemboss
= intern ("emboss");
10972 staticpro (&Qemboss
);
10973 Qedge_detection
= intern ("edge-detection");
10974 staticpro (&Qedge_detection
);
10975 Qheuristic
= intern ("heuristic");
10976 staticpro (&Qheuristic
);
10977 QCmatrix
= intern (":matrix");
10978 staticpro (&QCmatrix
);
10979 QCcolor_adjustment
= intern (":color-adjustment");
10980 staticpro (&QCcolor_adjustment
);
10981 QCmask
= intern (":mask");
10982 staticpro (&QCmask
);
10984 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10985 staticpro (&Qface_set_after_frame_default
);
10987 Fput (Qundefined_color
, Qerror_conditions
,
10988 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10989 Fput (Qundefined_color
, Qerror_message
,
10990 build_string ("Undefined color"));
10992 init_x_parm_symbols ();
10994 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
10995 "Non-nil means always draw a cross over disabled images.\n\
10996 Disabled images are those having an `:algorithm disabled' property.\n\
10997 A cross is always drawn on black & white displays.");
10998 cross_disabled_images
= 0;
11000 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
11001 "List of directories to search for bitmap files for X.");
11002 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
11004 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
11005 "The shape of the pointer when over text.\n\
11006 Changing the value does not affect existing frames\n\
11007 unless you set the mouse color.");
11008 Vx_pointer_shape
= Qnil
;
11010 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11011 "The name Emacs uses to look up X resources.\n\
11012 `x-get-resource' uses this as the first component of the instance name\n\
11013 when requesting resource values.\n\
11014 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11015 was invoked, or to the value specified with the `-name' or `-rn'\n\
11016 switches, if present.\n\
11018 It may be useful to bind this variable locally around a call\n\
11019 to `x-get-resource'. See also the variable `x-resource-class'.");
11020 Vx_resource_name
= Qnil
;
11022 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11023 "The class Emacs uses to look up X resources.\n\
11024 `x-get-resource' uses this as the first component of the instance class\n\
11025 when requesting resource values.\n\
11026 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11028 Setting this variable permanently is not a reasonable thing to do,\n\
11029 but binding this variable locally around a call to `x-get-resource'\n\
11030 is a reasonable practice. See also the variable `x-resource-name'.");
11031 Vx_resource_class
= build_string (EMACS_CLASS
);
11033 #if 0 /* This doesn't really do anything. */
11034 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11035 "The shape of the pointer when not over text.\n\
11036 This variable takes effect when you create a new frame\n\
11037 or when you set the mouse color.");
11039 Vx_nontext_pointer_shape
= Qnil
;
11041 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
11042 "The shape of the pointer when Emacs is busy.\n\
11043 This variable takes effect when you create a new frame\n\
11044 or when you set the mouse color.");
11045 Vx_busy_pointer_shape
= Qnil
;
11047 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
11048 "Non-zero means Emacs displays a busy cursor on window systems.");
11049 display_busy_cursor_p
= 1;
11051 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay
,
11052 "*Seconds to wait before displaying a busy-cursor.\n\
11053 Value must be an integer or float.");
11054 Vbusy_cursor_delay
= make_number (DEFAULT_BUSY_CURSOR_DELAY
);
11056 #if 0 /* This doesn't really do anything. */
11057 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11058 "The shape of the pointer when over the mode line.\n\
11059 This variable takes effect when you create a new frame\n\
11060 or when you set the mouse color.");
11062 Vx_mode_pointer_shape
= Qnil
;
11064 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11065 &Vx_sensitive_text_pointer_shape
,
11066 "The shape of the pointer when over mouse-sensitive text.\n\
11067 This variable takes effect when you create a new frame\n\
11068 or when you set the mouse color.");
11069 Vx_sensitive_text_pointer_shape
= Qnil
;
11071 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11072 "A string indicating the foreground color of the cursor box.");
11073 Vx_cursor_fore_pixel
= Qnil
;
11075 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11076 "Non-nil if no X window manager is in use.\n\
11077 Emacs doesn't try to figure this out; this is always nil\n\
11078 unless you set it to something else.");
11079 /* We don't have any way to find this out, so set it to nil
11080 and maybe the user would like to set it to t. */
11081 Vx_no_window_manager
= Qnil
;
11083 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11084 &Vx_pixel_size_width_font_regexp
,
11085 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11087 Since Emacs gets width of a font matching with this regexp from\n\
11088 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11089 such a font. This is especially effective for such large fonts as\n\
11090 Chinese, Japanese, and Korean.");
11091 Vx_pixel_size_width_font_regexp
= Qnil
;
11093 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
11094 "Time after which cached images are removed from the cache.\n\
11095 When an image has not been displayed this many seconds, remove it\n\
11096 from the image cache. Value must be an integer or nil with nil\n\
11097 meaning don't clear the cache.");
11098 Vimage_cache_eviction_delay
= make_number (30 * 60);
11100 #ifdef USE_X_TOOLKIT
11101 Fprovide (intern ("x-toolkit"));
11104 Fprovide (intern ("motif"));
11107 defsubr (&Sx_get_resource
);
11109 /* X window properties. */
11110 defsubr (&Sx_change_window_property
);
11111 defsubr (&Sx_delete_window_property
);
11112 defsubr (&Sx_window_property
);
11114 defsubr (&Sxw_display_color_p
);
11115 defsubr (&Sx_display_grayscale_p
);
11116 defsubr (&Sxw_color_defined_p
);
11117 defsubr (&Sxw_color_values
);
11118 defsubr (&Sx_server_max_request_size
);
11119 defsubr (&Sx_server_vendor
);
11120 defsubr (&Sx_server_version
);
11121 defsubr (&Sx_display_pixel_width
);
11122 defsubr (&Sx_display_pixel_height
);
11123 defsubr (&Sx_display_mm_width
);
11124 defsubr (&Sx_display_mm_height
);
11125 defsubr (&Sx_display_screens
);
11126 defsubr (&Sx_display_planes
);
11127 defsubr (&Sx_display_color_cells
);
11128 defsubr (&Sx_display_visual_class
);
11129 defsubr (&Sx_display_backing_store
);
11130 defsubr (&Sx_display_save_under
);
11131 defsubr (&Sx_parse_geometry
);
11132 defsubr (&Sx_create_frame
);
11133 defsubr (&Sx_open_connection
);
11134 defsubr (&Sx_close_connection
);
11135 defsubr (&Sx_display_list
);
11136 defsubr (&Sx_synchronize
);
11137 defsubr (&Sx_focus_frame
);
11139 /* Setting callback functions for fontset handler. */
11140 get_font_info_func
= x_get_font_info
;
11142 #if 0 /* This function pointer doesn't seem to be used anywhere.
11143 And the pointer assigned has the wrong type, anyway. */
11144 list_fonts_func
= x_list_fonts
;
11147 load_font_func
= x_load_font
;
11148 find_ccl_program_func
= x_find_ccl_program
;
11149 query_font_func
= x_query_font
;
11150 set_frame_fontset_func
= x_set_font
;
11151 check_window_system_func
= check_x
;
11154 Qxbm
= intern ("xbm");
11156 QCtype
= intern (":type");
11157 staticpro (&QCtype
);
11158 QCalgorithm
= intern (":algorithm");
11159 staticpro (&QCalgorithm
);
11160 QCheuristic_mask
= intern (":heuristic-mask");
11161 staticpro (&QCheuristic_mask
);
11162 QCcolor_symbols
= intern (":color-symbols");
11163 staticpro (&QCcolor_symbols
);
11164 QCascent
= intern (":ascent");
11165 staticpro (&QCascent
);
11166 QCmargin
= intern (":margin");
11167 staticpro (&QCmargin
);
11168 QCrelief
= intern (":relief");
11169 staticpro (&QCrelief
);
11170 Qpostscript
= intern ("postscript");
11171 staticpro (&Qpostscript
);
11172 QCloader
= intern (":loader");
11173 staticpro (&QCloader
);
11174 QCbounding_box
= intern (":bounding-box");
11175 staticpro (&QCbounding_box
);
11176 QCpt_width
= intern (":pt-width");
11177 staticpro (&QCpt_width
);
11178 QCpt_height
= intern (":pt-height");
11179 staticpro (&QCpt_height
);
11180 QCindex
= intern (":index");
11181 staticpro (&QCindex
);
11182 Qpbm
= intern ("pbm");
11186 Qxpm
= intern ("xpm");
11191 Qjpeg
= intern ("jpeg");
11192 staticpro (&Qjpeg
);
11196 Qtiff
= intern ("tiff");
11197 staticpro (&Qtiff
);
11201 Qgif
= intern ("gif");
11206 Qpng
= intern ("png");
11210 defsubr (&Sclear_image_cache
);
11211 defsubr (&Simage_size
);
11212 defsubr (&Simage_mask_p
);
11214 busy_cursor_atimer
= NULL
;
11215 busy_cursor_shown_p
= 0;
11217 defsubr (&Sx_show_tip
);
11218 defsubr (&Sx_hide_tip
);
11219 staticpro (&tip_timer
);
11223 defsubr (&Sx_file_dialog
);
11231 image_types
= NULL
;
11232 Vimage_types
= Qnil
;
11234 define_image_type (&xbm_type
);
11235 define_image_type (&gs_type
);
11236 define_image_type (&pbm_type
);
11239 define_image_type (&xpm_type
);
11243 define_image_type (&jpeg_type
);
11247 define_image_type (&tiff_type
);
11251 define_image_type (&gif_type
);
11255 define_image_type (&png_type
);
11259 #endif /* HAVE_X_WINDOWS */