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 back_color
.pixel
= mask_color
;
1510 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
1512 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
1514 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1515 &fore_color
, &back_color
);
1516 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1517 &fore_color
, &back_color
);
1518 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1519 &fore_color
, &back_color
);
1520 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1521 &fore_color
, &back_color
);
1522 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1523 &fore_color
, &back_color
);
1526 if (FRAME_X_WINDOW (f
) != 0)
1527 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1529 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1530 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1531 f
->output_data
.x
->text_cursor
= cursor
;
1533 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1534 && f
->output_data
.x
->nontext_cursor
!= 0)
1535 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1536 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1538 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1539 && f
->output_data
.x
->busy_cursor
!= 0)
1540 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1541 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1543 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1544 && f
->output_data
.x
->modeline_cursor
!= 0)
1545 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1546 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1548 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1549 && f
->output_data
.x
->cross_cursor
!= 0)
1550 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1551 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1553 XFlush (FRAME_X_DISPLAY (f
));
1556 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1560 x_set_cursor_color (f
, arg
, oldval
)
1562 Lisp_Object arg
, oldval
;
1564 unsigned long fore_pixel
, pixel
;
1565 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1567 if (!NILP (Vx_cursor_fore_pixel
))
1569 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1570 WHITE_PIX_DEFAULT (f
));
1571 fore_pixel_allocated_p
= 1;
1574 fore_pixel
= f
->output_data
.x
->background_pixel
;
1576 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1577 pixel_allocated_p
= 1;
1579 /* Make sure that the cursor color differs from the background color. */
1580 if (pixel
== f
->output_data
.x
->background_pixel
)
1582 if (pixel_allocated_p
)
1584 x_free_colors (f
, &pixel
, 1);
1585 pixel_allocated_p
= 0;
1588 pixel
= f
->output_data
.x
->mouse_pixel
;
1589 if (pixel
== fore_pixel
)
1591 if (fore_pixel_allocated_p
)
1593 x_free_colors (f
, &fore_pixel
, 1);
1594 fore_pixel_allocated_p
= 0;
1596 fore_pixel
= f
->output_data
.x
->background_pixel
;
1600 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1601 if (!fore_pixel_allocated_p
)
1602 fore_pixel
= x_copy_color (f
, fore_pixel
);
1603 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1605 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1606 if (!pixel_allocated_p
)
1607 pixel
= x_copy_color (f
, pixel
);
1608 f
->output_data
.x
->cursor_pixel
= pixel
;
1610 if (FRAME_X_WINDOW (f
) != 0)
1613 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1614 f
->output_data
.x
->cursor_pixel
);
1615 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1619 if (FRAME_VISIBLE_P (f
))
1621 x_update_cursor (f
, 0);
1622 x_update_cursor (f
, 1);
1626 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1629 /* Set the border-color of frame F to value described by ARG.
1630 ARG can be a string naming a color.
1631 The border-color is used for the border that is drawn by the X server.
1632 Note that this does not fully take effect if done before
1633 F has an x-window; it must be redone when the window is created.
1635 Note: this is done in two routines because of the way X10 works.
1637 Note: under X11, this is normally the province of the window manager,
1638 and so emacs' border colors may be overridden. */
1641 x_set_border_color (f
, arg
, oldval
)
1643 Lisp_Object arg
, oldval
;
1647 CHECK_STRING (arg
, 0);
1648 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1649 x_set_border_pixel (f
, pix
);
1650 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1653 /* Set the border-color of frame F to pixel value PIX.
1654 Note that this does not fully take effect if done before
1655 F has an x-window. */
1658 x_set_border_pixel (f
, pix
)
1662 unload_color (f
, f
->output_data
.x
->border_pixel
);
1663 f
->output_data
.x
->border_pixel
= pix
;
1665 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1668 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1669 (unsigned long)pix
);
1672 if (FRAME_VISIBLE_P (f
))
1678 /* Value is the internal representation of the specified cursor type
1679 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1680 of the bar cursor. */
1682 enum text_cursor_kinds
1683 x_specified_cursor_type (arg
, width
)
1687 enum text_cursor_kinds type
;
1694 else if (CONSP (arg
)
1695 && EQ (XCAR (arg
), Qbar
)
1696 && INTEGERP (XCDR (arg
))
1697 && XINT (XCDR (arg
)) >= 0)
1700 *width
= XINT (XCDR (arg
));
1702 else if (NILP (arg
))
1705 /* Treat anything unknown as "box cursor".
1706 It was bad to signal an error; people have trouble fixing
1707 .Xdefaults with Emacs, when it has something bad in it. */
1708 type
= FILLED_BOX_CURSOR
;
1714 x_set_cursor_type (f
, arg
, oldval
)
1716 Lisp_Object arg
, oldval
;
1720 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1721 f
->output_data
.x
->cursor_width
= width
;
1723 /* Make sure the cursor gets redrawn. This is overkill, but how
1724 often do people change cursor types? */
1725 update_mode_lines
++;
1729 x_set_icon_type (f
, arg
, oldval
)
1731 Lisp_Object arg
, oldval
;
1737 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1740 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1745 result
= x_text_icon (f
,
1746 (char *) XSTRING ((!NILP (f
->icon_name
)
1750 result
= x_bitmap_icon (f
, arg
);
1755 error ("No icon window available");
1758 XFlush (FRAME_X_DISPLAY (f
));
1762 /* Return non-nil if frame F wants a bitmap icon. */
1770 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1778 x_set_icon_name (f
, arg
, oldval
)
1780 Lisp_Object arg
, oldval
;
1786 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1789 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1794 if (f
->output_data
.x
->icon_bitmap
!= 0)
1799 result
= x_text_icon (f
,
1800 (char *) XSTRING ((!NILP (f
->icon_name
)
1809 error ("No icon window available");
1812 XFlush (FRAME_X_DISPLAY (f
));
1817 x_set_font (f
, arg
, oldval
)
1819 Lisp_Object arg
, oldval
;
1822 Lisp_Object fontset_name
;
1825 CHECK_STRING (arg
, 1);
1827 fontset_name
= Fquery_fontset (arg
, Qnil
);
1830 result
= (STRINGP (fontset_name
)
1831 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1832 : x_new_font (f
, XSTRING (arg
)->data
));
1835 if (EQ (result
, Qnil
))
1836 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1837 else if (EQ (result
, Qt
))
1838 error ("The characters of the given font have varying widths");
1839 else if (STRINGP (result
))
1841 store_frame_param (f
, Qfont
, result
);
1842 recompute_basic_faces (f
);
1847 do_pending_window_change (0);
1849 /* Don't call `face-set-after-frame-default' when faces haven't been
1850 initialized yet. This is the case when called from
1851 Fx_create_frame. In that case, the X widget or window doesn't
1852 exist either, and we can end up in x_report_frame_params with a
1853 null widget which gives a segfault. */
1854 if (FRAME_FACE_CACHE (f
))
1856 XSETFRAME (frame
, f
);
1857 call1 (Qface_set_after_frame_default
, frame
);
1862 x_set_border_width (f
, arg
, oldval
)
1864 Lisp_Object arg
, oldval
;
1866 CHECK_NUMBER (arg
, 0);
1868 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1871 if (FRAME_X_WINDOW (f
) != 0)
1872 error ("Cannot change the border width of a window");
1874 f
->output_data
.x
->border_width
= XINT (arg
);
1878 x_set_internal_border_width (f
, arg
, oldval
)
1880 Lisp_Object arg
, oldval
;
1882 int old
= f
->output_data
.x
->internal_border_width
;
1884 CHECK_NUMBER (arg
, 0);
1885 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1886 if (f
->output_data
.x
->internal_border_width
< 0)
1887 f
->output_data
.x
->internal_border_width
= 0;
1889 #ifdef USE_X_TOOLKIT
1890 if (f
->output_data
.x
->edit_widget
)
1891 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1894 if (f
->output_data
.x
->internal_border_width
== old
)
1897 if (FRAME_X_WINDOW (f
) != 0)
1899 x_set_window_size (f
, 0, f
->width
, f
->height
);
1900 SET_FRAME_GARBAGED (f
);
1901 do_pending_window_change (0);
1906 x_set_visibility (f
, value
, oldval
)
1908 Lisp_Object value
, oldval
;
1911 XSETFRAME (frame
, f
);
1914 Fmake_frame_invisible (frame
, Qt
);
1915 else if (EQ (value
, Qicon
))
1916 Ficonify_frame (frame
);
1918 Fmake_frame_visible (frame
);
1922 /* Change window heights in windows rooted in WINDOW by N lines. */
1925 x_change_window_heights (window
, n
)
1929 struct window
*w
= XWINDOW (window
);
1931 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1932 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1934 if (INTEGERP (w
->orig_top
))
1935 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
1936 if (INTEGERP (w
->orig_height
))
1937 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
1939 /* Handle just the top child in a vertical split. */
1940 if (!NILP (w
->vchild
))
1941 x_change_window_heights (w
->vchild
, n
);
1943 /* Adjust all children in a horizontal split. */
1944 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1946 w
= XWINDOW (window
);
1947 x_change_window_heights (window
, n
);
1952 x_set_menu_bar_lines (f
, value
, oldval
)
1954 Lisp_Object value
, oldval
;
1957 #ifndef USE_X_TOOLKIT
1958 int olines
= FRAME_MENU_BAR_LINES (f
);
1961 /* Right now, menu bars don't work properly in minibuf-only frames;
1962 most of the commands try to apply themselves to the minibuffer
1963 frame itself, and get an error because you can't switch buffers
1964 in or split the minibuffer window. */
1965 if (FRAME_MINIBUF_ONLY_P (f
))
1968 if (INTEGERP (value
))
1969 nlines
= XINT (value
);
1973 /* Make sure we redisplay all windows in this frame. */
1974 windows_or_buffers_changed
++;
1976 #ifdef USE_X_TOOLKIT
1977 FRAME_MENU_BAR_LINES (f
) = 0;
1980 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1981 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1982 /* Make sure next redisplay shows the menu bar. */
1983 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1987 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1988 free_frame_menubar (f
);
1989 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1991 f
->output_data
.x
->menubar_widget
= 0;
1993 #else /* not USE_X_TOOLKIT */
1994 FRAME_MENU_BAR_LINES (f
) = nlines
;
1995 x_change_window_heights (f
->root_window
, nlines
- olines
);
1996 #endif /* not USE_X_TOOLKIT */
2001 /* Set the number of lines used for the tool bar of frame F to VALUE.
2002 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2003 is the old number of tool bar lines. This function changes the
2004 height of all windows on frame F to match the new tool bar height.
2005 The frame's height doesn't change. */
2008 x_set_tool_bar_lines (f
, value
, oldval
)
2010 Lisp_Object value
, oldval
;
2012 int delta
, nlines
, root_height
;
2013 Lisp_Object root_window
;
2015 /* Use VALUE only if an integer >= 0. */
2016 if (INTEGERP (value
) && XINT (value
) >= 0)
2017 nlines
= XFASTINT (value
);
2021 /* Make sure we redisplay all windows in this frame. */
2022 ++windows_or_buffers_changed
;
2024 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2026 /* Don't resize the tool-bar to more than we have room for. */
2027 root_window
= FRAME_ROOT_WINDOW (f
);
2028 root_height
= XINT (XWINDOW (root_window
)->height
);
2029 if (root_height
- delta
< 1)
2031 delta
= root_height
- 1;
2032 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
2035 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2036 x_change_window_heights (root_window
, delta
);
2039 /* We also have to make sure that the internal border at the top of
2040 the frame, below the menu bar or tool bar, is redrawn when the
2041 tool bar disappears. This is so because the internal border is
2042 below the tool bar if one is displayed, but is below the menu bar
2043 if there isn't a tool bar. The tool bar draws into the area
2044 below the menu bar. */
2045 if (FRAME_X_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
2049 updating_frame
= NULL
;
2054 /* Set the foreground color for scroll bars on frame F to VALUE.
2055 VALUE should be a string, a color name. If it isn't a string or
2056 isn't a valid color name, do nothing. OLDVAL is the old value of
2057 the frame parameter. */
2060 x_set_scroll_bar_foreground (f
, value
, oldval
)
2062 Lisp_Object value
, oldval
;
2064 unsigned long pixel
;
2066 if (STRINGP (value
))
2067 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2071 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2072 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2074 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2075 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2077 /* Remove all scroll bars because they have wrong colors. */
2078 if (condemn_scroll_bars_hook
)
2079 (*condemn_scroll_bars_hook
) (f
);
2080 if (judge_scroll_bars_hook
)
2081 (*judge_scroll_bars_hook
) (f
);
2083 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2089 /* Set the background color for scroll bars on frame F to VALUE VALUE
2090 should be a string, a color name. If it isn't a string or isn't a
2091 valid color name, do nothing. OLDVAL is the old value of the frame
2095 x_set_scroll_bar_background (f
, value
, oldval
)
2097 Lisp_Object value
, oldval
;
2099 unsigned long pixel
;
2101 if (STRINGP (value
))
2102 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2106 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2107 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2109 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2110 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2112 /* Remove all scroll bars because they have wrong colors. */
2113 if (condemn_scroll_bars_hook
)
2114 (*condemn_scroll_bars_hook
) (f
);
2115 if (judge_scroll_bars_hook
)
2116 (*judge_scroll_bars_hook
) (f
);
2118 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2124 /* Encode Lisp string STRING as a text in a format appropriate for
2125 XICCC (X Inter Client Communication Conventions).
2127 If STRING contains only ASCII characters, do no conversion and
2128 return the string data of STRING. Otherwise, encode the text by
2129 CODING_SYSTEM, and return a newly allocated memory area which
2130 should be freed by `xfree' by a caller.
2132 Store the byte length of resulting text in *TEXT_BYTES.
2134 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2135 which means that the `encoding' of the result can be `STRING'.
2136 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2137 the result should be `COMPOUND_TEXT'. */
2140 x_encode_text (string
, coding_system
, text_bytes
, stringp
)
2141 Lisp_Object string
, coding_system
;
2142 int *text_bytes
, *stringp
;
2144 unsigned char *str
= XSTRING (string
)->data
;
2145 int chars
= XSTRING (string
)->size
;
2146 int bytes
= STRING_BYTES (XSTRING (string
));
2150 struct coding_system coding
;
2152 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2153 if (charset_info
== 0)
2155 /* No multibyte character in OBJ. We need not encode it. */
2156 *text_bytes
= bytes
;
2161 setup_coding_system (coding_system
, &coding
);
2162 coding
.src_multibyte
= 1;
2163 coding
.dst_multibyte
= 0;
2164 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2165 if (coding
.type
== coding_type_iso2022
)
2166 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2167 bufsize
= encoding_buffer_size (&coding
, bytes
);
2168 buf
= (unsigned char *) xmalloc (bufsize
);
2169 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2170 *text_bytes
= coding
.produced
;
2171 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2176 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2179 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2180 name; if NAME is a string, set F's name to NAME and set
2181 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2183 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2184 suggesting a new name, which lisp code should override; if
2185 F->explicit_name is set, ignore the new name; otherwise, set it. */
2188 x_set_name (f
, name
, explicit)
2193 /* Make sure that requests from lisp code override requests from
2194 Emacs redisplay code. */
2197 /* If we're switching from explicit to implicit, we had better
2198 update the mode lines and thereby update the title. */
2199 if (f
->explicit_name
&& NILP (name
))
2200 update_mode_lines
= 1;
2202 f
->explicit_name
= ! NILP (name
);
2204 else if (f
->explicit_name
)
2207 /* If NAME is nil, set the name to the x_id_name. */
2210 /* Check for no change needed in this very common case
2211 before we do any consing. */
2212 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2213 XSTRING (f
->name
)->data
))
2215 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2218 CHECK_STRING (name
, 0);
2220 /* Don't change the name if it's already NAME. */
2221 if (! NILP (Fstring_equal (name
, f
->name
)))
2226 /* For setting the frame title, the title parameter should override
2227 the name parameter. */
2228 if (! NILP (f
->title
))
2231 if (FRAME_X_WINDOW (f
))
2236 XTextProperty text
, icon
;
2238 Lisp_Object coding_system
;
2240 coding_system
= Vlocale_coding_system
;
2241 if (NILP (coding_system
))
2242 coding_system
= Qcompound_text
;
2243 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2244 text
.encoding
= (stringp
? XA_STRING
2245 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2247 text
.nitems
= bytes
;
2249 if (NILP (f
->icon_name
))
2255 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2257 icon
.encoding
= (stringp
? XA_STRING
2258 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2260 icon
.nitems
= bytes
;
2262 #ifdef USE_X_TOOLKIT
2263 XSetWMName (FRAME_X_DISPLAY (f
),
2264 XtWindow (f
->output_data
.x
->widget
), &text
);
2265 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2267 #else /* not USE_X_TOOLKIT */
2268 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2269 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2270 #endif /* not USE_X_TOOLKIT */
2271 if (!NILP (f
->icon_name
)
2272 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2274 if (text
.value
!= XSTRING (name
)->data
)
2277 #else /* not HAVE_X11R4 */
2278 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2279 XSTRING (name
)->data
);
2280 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2281 XSTRING (name
)->data
);
2282 #endif /* not HAVE_X11R4 */
2287 /* This function should be called when the user's lisp code has
2288 specified a name for the frame; the name will override any set by the
2291 x_explicitly_set_name (f
, arg
, oldval
)
2293 Lisp_Object arg
, oldval
;
2295 x_set_name (f
, arg
, 1);
2298 /* This function should be called by Emacs redisplay code to set the
2299 name; names set this way will never override names set by the user's
2302 x_implicitly_set_name (f
, arg
, oldval
)
2304 Lisp_Object arg
, oldval
;
2306 x_set_name (f
, arg
, 0);
2309 /* Change the title of frame F to NAME.
2310 If NAME is nil, use the frame name as the title.
2312 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2313 name; if NAME is a string, set F's name to NAME and set
2314 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2316 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2317 suggesting a new name, which lisp code should override; if
2318 F->explicit_name is set, ignore the new name; otherwise, set it. */
2321 x_set_title (f
, name
, old_name
)
2323 Lisp_Object name
, old_name
;
2325 /* Don't change the title if it's already NAME. */
2326 if (EQ (name
, f
->title
))
2329 update_mode_lines
= 1;
2336 CHECK_STRING (name
, 0);
2338 if (FRAME_X_WINDOW (f
))
2343 XTextProperty text
, icon
;
2345 Lisp_Object coding_system
;
2347 coding_system
= Vlocale_coding_system
;
2348 if (NILP (coding_system
))
2349 coding_system
= Qcompound_text
;
2350 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2351 text
.encoding
= (stringp
? XA_STRING
2352 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2354 text
.nitems
= bytes
;
2356 if (NILP (f
->icon_name
))
2362 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2364 icon
.encoding
= (stringp
? XA_STRING
2365 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2367 icon
.nitems
= bytes
;
2369 #ifdef USE_X_TOOLKIT
2370 XSetWMName (FRAME_X_DISPLAY (f
),
2371 XtWindow (f
->output_data
.x
->widget
), &text
);
2372 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2374 #else /* not USE_X_TOOLKIT */
2375 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2376 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2377 #endif /* not USE_X_TOOLKIT */
2378 if (!NILP (f
->icon_name
)
2379 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2381 if (text
.value
!= XSTRING (name
)->data
)
2384 #else /* not HAVE_X11R4 */
2385 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2386 XSTRING (name
)->data
);
2387 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2388 XSTRING (name
)->data
);
2389 #endif /* not HAVE_X11R4 */
2395 x_set_autoraise (f
, arg
, oldval
)
2397 Lisp_Object arg
, oldval
;
2399 f
->auto_raise
= !EQ (Qnil
, arg
);
2403 x_set_autolower (f
, arg
, oldval
)
2405 Lisp_Object arg
, oldval
;
2407 f
->auto_lower
= !EQ (Qnil
, arg
);
2411 x_set_unsplittable (f
, arg
, oldval
)
2413 Lisp_Object arg
, oldval
;
2415 f
->no_split
= !NILP (arg
);
2419 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2421 Lisp_Object arg
, oldval
;
2423 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2424 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2425 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2426 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2428 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2430 ? vertical_scroll_bar_none
2432 ? vertical_scroll_bar_right
2433 : vertical_scroll_bar_left
);
2435 /* We set this parameter before creating the X window for the
2436 frame, so we can get the geometry right from the start.
2437 However, if the window hasn't been created yet, we shouldn't
2438 call x_set_window_size. */
2439 if (FRAME_X_WINDOW (f
))
2440 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2441 do_pending_window_change (0);
2446 x_set_scroll_bar_width (f
, arg
, oldval
)
2448 Lisp_Object arg
, oldval
;
2450 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2454 #ifdef USE_TOOLKIT_SCROLL_BARS
2455 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2456 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2457 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2458 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2460 /* Make the actual width at least 14 pixels and a multiple of a
2462 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2464 /* Use all of that space (aside from required margins) for the
2466 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2469 if (FRAME_X_WINDOW (f
))
2470 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2471 do_pending_window_change (0);
2473 else if (INTEGERP (arg
) && XINT (arg
) > 0
2474 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2476 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2477 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2479 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2480 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2481 if (FRAME_X_WINDOW (f
))
2482 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2485 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2486 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2487 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2492 /* Subroutines of creating an X frame. */
2494 /* Make sure that Vx_resource_name is set to a reasonable value.
2495 Fix it up, or set it to `emacs' if it is too hopeless. */
2498 validate_x_resource_name ()
2501 /* Number of valid characters in the resource name. */
2503 /* Number of invalid characters in the resource name. */
2508 if (!STRINGP (Vx_resource_class
))
2509 Vx_resource_class
= build_string (EMACS_CLASS
);
2511 if (STRINGP (Vx_resource_name
))
2513 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2516 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2518 /* Only letters, digits, - and _ are valid in resource names.
2519 Count the valid characters and count the invalid ones. */
2520 for (i
= 0; i
< len
; i
++)
2523 if (! ((c
>= 'a' && c
<= 'z')
2524 || (c
>= 'A' && c
<= 'Z')
2525 || (c
>= '0' && c
<= '9')
2526 || c
== '-' || c
== '_'))
2533 /* Not a string => completely invalid. */
2534 bad_count
= 5, good_count
= 0;
2536 /* If name is valid already, return. */
2540 /* If name is entirely invalid, or nearly so, use `emacs'. */
2542 || (good_count
== 1 && bad_count
> 0))
2544 Vx_resource_name
= build_string ("emacs");
2548 /* Name is partly valid. Copy it and replace the invalid characters
2549 with underscores. */
2551 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2553 for (i
= 0; i
< len
; i
++)
2555 int c
= XSTRING (new)->data
[i
];
2556 if (! ((c
>= 'a' && c
<= 'z')
2557 || (c
>= 'A' && c
<= 'Z')
2558 || (c
>= '0' && c
<= '9')
2559 || c
== '-' || c
== '_'))
2560 XSTRING (new)->data
[i
] = '_';
2565 extern char *x_get_string_resource ();
2567 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2568 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2569 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2570 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2571 the name specified by the `-name' or `-rn' command-line arguments.\n\
2573 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2574 class, respectively. You must specify both of them or neither.\n\
2575 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2576 and the class is `Emacs.CLASS.SUBCLASS'.")
2577 (attribute
, class, component
, subclass
)
2578 Lisp_Object attribute
, class, component
, subclass
;
2580 register char *value
;
2586 CHECK_STRING (attribute
, 0);
2587 CHECK_STRING (class, 0);
2589 if (!NILP (component
))
2590 CHECK_STRING (component
, 1);
2591 if (!NILP (subclass
))
2592 CHECK_STRING (subclass
, 2);
2593 if (NILP (component
) != NILP (subclass
))
2594 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2596 validate_x_resource_name ();
2598 /* Allocate space for the components, the dots which separate them,
2599 and the final '\0'. Make them big enough for the worst case. */
2600 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2601 + (STRINGP (component
)
2602 ? STRING_BYTES (XSTRING (component
)) : 0)
2603 + STRING_BYTES (XSTRING (attribute
))
2606 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2607 + STRING_BYTES (XSTRING (class))
2608 + (STRINGP (subclass
)
2609 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2612 /* Start with emacs.FRAMENAME for the name (the specific one)
2613 and with `Emacs' for the class key (the general one). */
2614 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2615 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2617 strcat (class_key
, ".");
2618 strcat (class_key
, XSTRING (class)->data
);
2620 if (!NILP (component
))
2622 strcat (class_key
, ".");
2623 strcat (class_key
, XSTRING (subclass
)->data
);
2625 strcat (name_key
, ".");
2626 strcat (name_key
, XSTRING (component
)->data
);
2629 strcat (name_key
, ".");
2630 strcat (name_key
, XSTRING (attribute
)->data
);
2632 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2633 name_key
, class_key
);
2635 if (value
!= (char *) 0)
2636 return build_string (value
);
2641 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2644 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2645 struct x_display_info
*dpyinfo
;
2646 Lisp_Object attribute
, class, component
, subclass
;
2648 register char *value
;
2652 CHECK_STRING (attribute
, 0);
2653 CHECK_STRING (class, 0);
2655 if (!NILP (component
))
2656 CHECK_STRING (component
, 1);
2657 if (!NILP (subclass
))
2658 CHECK_STRING (subclass
, 2);
2659 if (NILP (component
) != NILP (subclass
))
2660 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2662 validate_x_resource_name ();
2664 /* Allocate space for the components, the dots which separate them,
2665 and the final '\0'. Make them big enough for the worst case. */
2666 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2667 + (STRINGP (component
)
2668 ? STRING_BYTES (XSTRING (component
)) : 0)
2669 + STRING_BYTES (XSTRING (attribute
))
2672 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2673 + STRING_BYTES (XSTRING (class))
2674 + (STRINGP (subclass
)
2675 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2678 /* Start with emacs.FRAMENAME for the name (the specific one)
2679 and with `Emacs' for the class key (the general one). */
2680 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2681 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2683 strcat (class_key
, ".");
2684 strcat (class_key
, XSTRING (class)->data
);
2686 if (!NILP (component
))
2688 strcat (class_key
, ".");
2689 strcat (class_key
, XSTRING (subclass
)->data
);
2691 strcat (name_key
, ".");
2692 strcat (name_key
, XSTRING (component
)->data
);
2695 strcat (name_key
, ".");
2696 strcat (name_key
, XSTRING (attribute
)->data
);
2698 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2700 if (value
!= (char *) 0)
2701 return build_string (value
);
2706 /* Used when C code wants a resource value. */
2709 x_get_resource_string (attribute
, class)
2710 char *attribute
, *class;
2714 struct frame
*sf
= SELECTED_FRAME ();
2716 /* Allocate space for the components, the dots which separate them,
2717 and the final '\0'. */
2718 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2719 + strlen (attribute
) + 2);
2720 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2721 + strlen (class) + 2);
2723 sprintf (name_key
, "%s.%s",
2724 XSTRING (Vinvocation_name
)->data
,
2726 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2728 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2729 name_key
, class_key
);
2732 /* Types we might convert a resource string into. */
2742 /* Return the value of parameter PARAM.
2744 First search ALIST, then Vdefault_frame_alist, then the X defaults
2745 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2747 Convert the resource to the type specified by desired_type.
2749 If no default is specified, return Qunbound. If you call
2750 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2751 and don't let it get stored in any Lisp-visible variables! */
2754 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2755 struct x_display_info
*dpyinfo
;
2756 Lisp_Object alist
, param
;
2759 enum resource_types type
;
2761 register Lisp_Object tem
;
2763 tem
= Fassq (param
, alist
);
2765 tem
= Fassq (param
, Vdefault_frame_alist
);
2771 tem
= display_x_get_resource (dpyinfo
,
2772 build_string (attribute
),
2773 build_string (class),
2781 case RES_TYPE_NUMBER
:
2782 return make_number (atoi (XSTRING (tem
)->data
));
2784 case RES_TYPE_FLOAT
:
2785 return make_float (atof (XSTRING (tem
)->data
));
2787 case RES_TYPE_BOOLEAN
:
2788 tem
= Fdowncase (tem
);
2789 if (!strcmp (XSTRING (tem
)->data
, "on")
2790 || !strcmp (XSTRING (tem
)->data
, "true"))
2795 case RES_TYPE_STRING
:
2798 case RES_TYPE_SYMBOL
:
2799 /* As a special case, we map the values `true' and `on'
2800 to Qt, and `false' and `off' to Qnil. */
2803 lower
= Fdowncase (tem
);
2804 if (!strcmp (XSTRING (lower
)->data
, "on")
2805 || !strcmp (XSTRING (lower
)->data
, "true"))
2807 else if (!strcmp (XSTRING (lower
)->data
, "off")
2808 || !strcmp (XSTRING (lower
)->data
, "false"))
2811 return Fintern (tem
, Qnil
);
2824 /* Like x_get_arg, but also record the value in f->param_alist. */
2827 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2829 Lisp_Object alist
, param
;
2832 enum resource_types type
;
2836 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2837 attribute
, class, type
);
2839 store_frame_param (f
, param
, value
);
2844 /* Record in frame F the specified or default value according to ALIST
2845 of the parameter named PROP (a Lisp symbol).
2846 If no value is specified for PROP, look for an X default for XPROP
2847 on the frame named NAME.
2848 If that is not found either, use the value DEFLT. */
2851 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2858 enum resource_types type
;
2862 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2863 if (EQ (tem
, Qunbound
))
2865 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2870 /* Record in frame F the specified or default value according to ALIST
2871 of the parameter named PROP (a Lisp symbol). If no value is
2872 specified for PROP, look for an X default for XPROP on the frame
2873 named NAME. If that is not found either, use the value DEFLT. */
2876 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2885 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2888 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2889 if (EQ (tem
, Qunbound
))
2891 #ifdef USE_TOOLKIT_SCROLL_BARS
2893 /* See if an X resource for the scroll bar color has been
2895 tem
= display_x_get_resource (dpyinfo
,
2896 build_string (foreground_p
2900 build_string ("verticalScrollBar"),
2904 /* If nothing has been specified, scroll bars will use a
2905 toolkit-dependent default. Because these defaults are
2906 difficult to get at without actually creating a scroll
2907 bar, use nil to indicate that no color has been
2912 #else /* not USE_TOOLKIT_SCROLL_BARS */
2916 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2919 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2925 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2926 "Parse an X-style geometry string STRING.\n\
2927 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2928 The properties returned may include `top', `left', `height', and `width'.\n\
2929 The value of `left' or `top' may be an integer,\n\
2930 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2931 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2936 unsigned int width
, height
;
2939 CHECK_STRING (string
, 0);
2941 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2942 &x
, &y
, &width
, &height
);
2945 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2946 error ("Must specify both x and y position, or neither");
2950 if (geometry
& XValue
)
2952 Lisp_Object element
;
2954 if (x
>= 0 && (geometry
& XNegative
))
2955 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2956 else if (x
< 0 && ! (geometry
& XNegative
))
2957 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2959 element
= Fcons (Qleft
, make_number (x
));
2960 result
= Fcons (element
, result
);
2963 if (geometry
& YValue
)
2965 Lisp_Object element
;
2967 if (y
>= 0 && (geometry
& YNegative
))
2968 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2969 else if (y
< 0 && ! (geometry
& YNegative
))
2970 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2972 element
= Fcons (Qtop
, make_number (y
));
2973 result
= Fcons (element
, result
);
2976 if (geometry
& WidthValue
)
2977 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2978 if (geometry
& HeightValue
)
2979 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2984 /* Calculate the desired size and position of this window,
2985 and return the flags saying which aspects were specified.
2987 This function does not make the coordinates positive. */
2989 #define DEFAULT_ROWS 40
2990 #define DEFAULT_COLS 80
2993 x_figure_window_size (f
, parms
)
2997 register Lisp_Object tem0
, tem1
, tem2
;
2998 long window_prompting
= 0;
2999 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3001 /* Default values if we fall through.
3002 Actually, if that happens we should get
3003 window manager prompting. */
3004 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
3005 f
->height
= DEFAULT_ROWS
;
3006 /* Window managers expect that if program-specified
3007 positions are not (0,0), they're intentional, not defaults. */
3008 f
->output_data
.x
->top_pos
= 0;
3009 f
->output_data
.x
->left_pos
= 0;
3011 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
3012 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
3013 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
3014 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3016 if (!EQ (tem0
, Qunbound
))
3018 CHECK_NUMBER (tem0
, 0);
3019 f
->height
= XINT (tem0
);
3021 if (!EQ (tem1
, Qunbound
))
3023 CHECK_NUMBER (tem1
, 0);
3024 SET_FRAME_WIDTH (f
, XINT (tem1
));
3026 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
3027 window_prompting
|= USSize
;
3029 window_prompting
|= PSize
;
3032 f
->output_data
.x
->vertical_scroll_bar_extra
3033 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3035 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3036 f
->output_data
.x
->flags_areas_extra
3037 = FRAME_FLAGS_AREA_WIDTH (f
);
3038 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
3039 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
3041 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
3042 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3043 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3044 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3046 if (EQ (tem0
, Qminus
))
3048 f
->output_data
.x
->top_pos
= 0;
3049 window_prompting
|= YNegative
;
3051 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3052 && CONSP (XCDR (tem0
))
3053 && INTEGERP (XCAR (XCDR (tem0
))))
3055 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3056 window_prompting
|= YNegative
;
3058 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3059 && CONSP (XCDR (tem0
))
3060 && INTEGERP (XCAR (XCDR (tem0
))))
3062 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3064 else if (EQ (tem0
, Qunbound
))
3065 f
->output_data
.x
->top_pos
= 0;
3068 CHECK_NUMBER (tem0
, 0);
3069 f
->output_data
.x
->top_pos
= XINT (tem0
);
3070 if (f
->output_data
.x
->top_pos
< 0)
3071 window_prompting
|= YNegative
;
3074 if (EQ (tem1
, Qminus
))
3076 f
->output_data
.x
->left_pos
= 0;
3077 window_prompting
|= XNegative
;
3079 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3080 && CONSP (XCDR (tem1
))
3081 && INTEGERP (XCAR (XCDR (tem1
))))
3083 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3084 window_prompting
|= XNegative
;
3086 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3087 && CONSP (XCDR (tem1
))
3088 && INTEGERP (XCAR (XCDR (tem1
))))
3090 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3092 else if (EQ (tem1
, Qunbound
))
3093 f
->output_data
.x
->left_pos
= 0;
3096 CHECK_NUMBER (tem1
, 0);
3097 f
->output_data
.x
->left_pos
= XINT (tem1
);
3098 if (f
->output_data
.x
->left_pos
< 0)
3099 window_prompting
|= XNegative
;
3102 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3103 window_prompting
|= USPosition
;
3105 window_prompting
|= PPosition
;
3108 return window_prompting
;
3111 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3114 XSetWMProtocols (dpy
, w
, protocols
, count
)
3121 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3122 if (prop
== None
) return False
;
3123 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3124 (unsigned char *) protocols
, count
);
3127 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3129 #ifdef USE_X_TOOLKIT
3131 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3132 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3133 already be present because of the toolkit (Motif adds some of them,
3134 for example, but Xt doesn't). */
3137 hack_wm_protocols (f
, widget
)
3141 Display
*dpy
= XtDisplay (widget
);
3142 Window w
= XtWindow (widget
);
3143 int need_delete
= 1;
3149 Atom type
, *atoms
= 0;
3151 unsigned long nitems
= 0;
3152 unsigned long bytes_after
;
3154 if ((XGetWindowProperty (dpy
, w
,
3155 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3156 (long)0, (long)100, False
, XA_ATOM
,
3157 &type
, &format
, &nitems
, &bytes_after
,
3158 (unsigned char **) &atoms
)
3160 && format
== 32 && type
== XA_ATOM
)
3164 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3166 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3168 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3171 if (atoms
) XFree ((char *) atoms
);
3177 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3179 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3181 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3183 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3184 XA_ATOM
, 32, PropModeAppend
,
3185 (unsigned char *) props
, count
);
3193 /* Support routines for XIC (X Input Context). */
3197 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3198 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3201 /* Supported XIM styles, ordered by preferenc. */
3203 static XIMStyle supported_xim_styles
[] =
3205 XIMPreeditPosition
| XIMStatusArea
,
3206 XIMPreeditPosition
| XIMStatusNothing
,
3207 XIMPreeditPosition
| XIMStatusNone
,
3208 XIMPreeditNothing
| XIMStatusArea
,
3209 XIMPreeditNothing
| XIMStatusNothing
,
3210 XIMPreeditNothing
| XIMStatusNone
,
3211 XIMPreeditNone
| XIMStatusArea
,
3212 XIMPreeditNone
| XIMStatusNothing
,
3213 XIMPreeditNone
| XIMStatusNone
,
3218 /* Create an X fontset on frame F with base font name
3222 xic_create_xfontset (f
, base_fontname
)
3224 char *base_fontname
;
3227 char **missing_list
;
3231 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3232 base_fontname
, &missing_list
,
3233 &missing_count
, &def_string
);
3235 XFreeStringList (missing_list
);
3237 /* No need to free def_string. */
3242 /* Value is the best input style, given user preferences USER (already
3243 checked to be supported by Emacs), and styles supported by the
3244 input method XIM. */
3247 best_xim_style (user
, xim
)
3253 for (i
= 0; i
< user
->count_styles
; ++i
)
3254 for (j
= 0; j
< xim
->count_styles
; ++j
)
3255 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3256 return user
->supported_styles
[i
];
3258 /* Return the default style. */
3259 return XIMPreeditNothing
| XIMStatusNothing
;
3262 /* Create XIC for frame F. */
3265 create_frame_xic (f
)
3270 XFontSet xfs
= NULL
;
3271 static XIMStyle xic_style
;
3276 xim
= FRAME_X_XIM (f
);
3281 XVaNestedList preedit_attr
;
3282 XVaNestedList status_attr
;
3283 char *base_fontname
;
3286 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3287 spot
.x
= 0; spot
.y
= 1;
3288 /* Create X fontset. */
3289 fontset
= FRAME_FONTSET (f
);
3291 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3294 /* Determine the base fontname from the ASCII font name of
3296 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3297 char *p
= ascii_font
;
3300 for (i
= 0; *p
; p
++)
3303 /* As the font name doesn't conform to XLFD, we can't
3304 modify it to get a suitable base fontname for the
3306 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3309 int len
= strlen (ascii_font
) + 1;
3312 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3321 base_fontname
= (char *) alloca (len
);
3322 bzero (base_fontname
, len
);
3323 strcpy (base_fontname
, "-*-*-");
3324 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3325 strcat (base_fontname
, "*-*-*-*-*-*-*");
3328 xfs
= xic_create_xfontset (f
, base_fontname
);
3330 /* Determine XIC style. */
3333 XIMStyles supported_list
;
3334 supported_list
.count_styles
= (sizeof supported_xim_styles
3335 / sizeof supported_xim_styles
[0]);
3336 supported_list
.supported_styles
= supported_xim_styles
;
3337 xic_style
= best_xim_style (&supported_list
,
3338 FRAME_X_XIM_STYLES (f
));
3341 preedit_attr
= XVaCreateNestedList (0,
3344 FRAME_FOREGROUND_PIXEL (f
),
3346 FRAME_BACKGROUND_PIXEL (f
),
3347 (xic_style
& XIMPreeditPosition
3352 status_attr
= XVaCreateNestedList (0,
3358 FRAME_FOREGROUND_PIXEL (f
),
3360 FRAME_BACKGROUND_PIXEL (f
),
3363 xic
= XCreateIC (xim
,
3364 XNInputStyle
, xic_style
,
3365 XNClientWindow
, FRAME_X_WINDOW(f
),
3366 XNFocusWindow
, FRAME_X_WINDOW(f
),
3367 XNStatusAttributes
, status_attr
,
3368 XNPreeditAttributes
, preedit_attr
,
3370 XFree (preedit_attr
);
3371 XFree (status_attr
);
3374 FRAME_XIC (f
) = xic
;
3375 FRAME_XIC_STYLE (f
) = xic_style
;
3376 FRAME_XIC_FONTSET (f
) = xfs
;
3380 /* Destroy XIC and free XIC fontset of frame F, if any. */
3386 if (FRAME_XIC (f
) == NULL
)
3389 XDestroyIC (FRAME_XIC (f
));
3390 if (FRAME_XIC_FONTSET (f
))
3391 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3393 FRAME_XIC (f
) = NULL
;
3394 FRAME_XIC_FONTSET (f
) = NULL
;
3398 /* Place preedit area for XIC of window W's frame to specified
3399 pixel position X/Y. X and Y are relative to window W. */
3402 xic_set_preeditarea (w
, x
, y
)
3406 struct frame
*f
= XFRAME (w
->frame
);
3410 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3411 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3412 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3413 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3418 /* Place status area for XIC in bottom right corner of frame F.. */
3421 xic_set_statusarea (f
)
3424 XIC xic
= FRAME_XIC (f
);
3429 /* Negotiate geometry of status area. If input method has existing
3430 status area, use its current size. */
3431 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3432 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3433 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3436 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3437 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3440 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3442 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3443 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3447 area
.width
= needed
->width
;
3448 area
.height
= needed
->height
;
3449 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3450 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3451 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3454 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3455 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3460 /* Set X fontset for XIC of frame F, using base font name
3461 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3464 xic_set_xfontset (f
, base_fontname
)
3466 char *base_fontname
;
3471 xfs
= xic_create_xfontset (f
, base_fontname
);
3473 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3474 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3475 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3476 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3477 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3480 if (FRAME_XIC_FONTSET (f
))
3481 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3482 FRAME_XIC_FONTSET (f
) = xfs
;
3485 #endif /* HAVE_X_I18N */
3489 #ifdef USE_X_TOOLKIT
3491 /* Create and set up the X widget for frame F. */
3494 x_window (f
, window_prompting
, minibuffer_only
)
3496 long window_prompting
;
3497 int minibuffer_only
;
3499 XClassHint class_hints
;
3500 XSetWindowAttributes attributes
;
3501 unsigned long attribute_mask
;
3502 Widget shell_widget
;
3504 Widget frame_widget
;
3510 /* Use the resource name as the top-level widget name
3511 for looking up resources. Make a non-Lisp copy
3512 for the window manager, so GC relocation won't bother it.
3514 Elsewhere we specify the window name for the window manager. */
3517 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3518 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3519 strcpy (f
->namebuf
, str
);
3523 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3524 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3525 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3526 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3527 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3528 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3529 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3530 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3531 applicationShellWidgetClass
,
3532 FRAME_X_DISPLAY (f
), al
, ac
);
3534 f
->output_data
.x
->widget
= shell_widget
;
3535 /* maybe_set_screen_title_format (shell_widget); */
3537 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3538 (widget_value
*) NULL
,
3539 shell_widget
, False
,
3543 (lw_callback
) NULL
);
3546 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3547 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3548 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3549 XtSetValues (pane_widget
, al
, ac
);
3550 f
->output_data
.x
->column_widget
= pane_widget
;
3552 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3553 the emacs screen when changing menubar. This reduces flickering. */
3556 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3557 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3558 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3559 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3560 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3561 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3562 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3563 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3564 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3567 f
->output_data
.x
->edit_widget
= frame_widget
;
3569 XtManageChild (frame_widget
);
3571 /* Do some needed geometry management. */
3574 char *tem
, shell_position
[32];
3577 int extra_borders
= 0;
3579 = (f
->output_data
.x
->menubar_widget
3580 ? (f
->output_data
.x
->menubar_widget
->core
.height
3581 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3584 #if 0 /* Experimentally, we now get the right results
3585 for -geometry -0-0 without this. 24 Aug 96, rms. */
3586 if (FRAME_EXTERNAL_MENU_BAR (f
))
3589 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3590 menubar_size
+= ibw
;
3594 f
->output_data
.x
->menubar_height
= menubar_size
;
3597 /* Motif seems to need this amount added to the sizes
3598 specified for the shell widget. The Athena/Lucid widgets don't.
3599 Both conclusions reached experimentally. -- rms. */
3600 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3601 &extra_borders
, NULL
);
3605 /* Convert our geometry parameters into a geometry string
3607 Note that we do not specify here whether the position
3608 is a user-specified or program-specified one.
3609 We pass that information later, in x_wm_set_size_hints. */
3611 int left
= f
->output_data
.x
->left_pos
;
3612 int xneg
= window_prompting
& XNegative
;
3613 int top
= f
->output_data
.x
->top_pos
;
3614 int yneg
= window_prompting
& YNegative
;
3620 if (window_prompting
& USPosition
)
3621 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3622 PIXEL_WIDTH (f
) + extra_borders
,
3623 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3624 (xneg
? '-' : '+'), left
,
3625 (yneg
? '-' : '+'), top
);
3627 sprintf (shell_position
, "=%dx%d",
3628 PIXEL_WIDTH (f
) + extra_borders
,
3629 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3632 len
= strlen (shell_position
) + 1;
3633 /* We don't free this because we don't know whether
3634 it is safe to free it while the frame exists.
3635 It isn't worth the trouble of arranging to free it
3636 when the frame is deleted. */
3637 tem
= (char *) xmalloc (len
);
3638 strncpy (tem
, shell_position
, len
);
3639 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3640 XtSetValues (shell_widget
, al
, ac
);
3643 XtManageChild (pane_widget
);
3644 XtRealizeWidget (shell_widget
);
3646 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3648 validate_x_resource_name ();
3650 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3651 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3652 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3655 FRAME_XIC (f
) = NULL
;
3657 create_frame_xic (f
);
3661 f
->output_data
.x
->wm_hints
.input
= True
;
3662 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3663 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3664 &f
->output_data
.x
->wm_hints
);
3666 hack_wm_protocols (f
, shell_widget
);
3669 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3672 /* Do a stupid property change to force the server to generate a
3673 PropertyNotify event so that the event_stream server timestamp will
3674 be initialized to something relevant to the time we created the window.
3676 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3677 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3678 XA_ATOM
, 32, PropModeAppend
,
3679 (unsigned char*) NULL
, 0);
3681 /* Make all the standard events reach the Emacs frame. */
3682 attributes
.event_mask
= STANDARD_EVENT_SET
;
3687 /* XIM server might require some X events. */
3688 unsigned long fevent
= NoEventMask
;
3689 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3690 attributes
.event_mask
|= fevent
;
3692 #endif /* HAVE_X_I18N */
3694 attribute_mask
= CWEventMask
;
3695 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3696 attribute_mask
, &attributes
);
3698 XtMapWidget (frame_widget
);
3700 /* x_set_name normally ignores requests to set the name if the
3701 requested name is the same as the current name. This is the one
3702 place where that assumption isn't correct; f->name is set, but
3703 the X server hasn't been told. */
3706 int explicit = f
->explicit_name
;
3708 f
->explicit_name
= 0;
3711 x_set_name (f
, name
, explicit);
3714 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3715 f
->output_data
.x
->text_cursor
);
3719 /* This is a no-op, except under Motif. Make sure main areas are
3720 set to something reasonable, in case we get an error later. */
3721 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3724 #else /* not USE_X_TOOLKIT */
3726 /* Create and set up the X window for frame F. */
3733 XClassHint class_hints
;
3734 XSetWindowAttributes attributes
;
3735 unsigned long attribute_mask
;
3737 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3738 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3739 attributes
.bit_gravity
= StaticGravity
;
3740 attributes
.backing_store
= NotUseful
;
3741 attributes
.save_under
= True
;
3742 attributes
.event_mask
= STANDARD_EVENT_SET
;
3743 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3744 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3749 = XCreateWindow (FRAME_X_DISPLAY (f
),
3750 f
->output_data
.x
->parent_desc
,
3751 f
->output_data
.x
->left_pos
,
3752 f
->output_data
.x
->top_pos
,
3753 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3754 f
->output_data
.x
->border_width
,
3755 CopyFromParent
, /* depth */
3756 InputOutput
, /* class */
3758 attribute_mask
, &attributes
);
3762 create_frame_xic (f
);
3765 /* XIM server might require some X events. */
3766 unsigned long fevent
= NoEventMask
;
3767 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3768 attributes
.event_mask
|= fevent
;
3769 attribute_mask
= CWEventMask
;
3770 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3771 attribute_mask
, &attributes
);
3774 #endif /* HAVE_X_I18N */
3776 validate_x_resource_name ();
3778 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3779 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3780 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3782 /* The menubar is part of the ordinary display;
3783 it does not count in addition to the height of the window. */
3784 f
->output_data
.x
->menubar_height
= 0;
3786 /* This indicates that we use the "Passive Input" input model.
3787 Unless we do this, we don't get the Focus{In,Out} events that we
3788 need to draw the cursor correctly. Accursed bureaucrats.
3789 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3791 f
->output_data
.x
->wm_hints
.input
= True
;
3792 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3793 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3794 &f
->output_data
.x
->wm_hints
);
3795 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3797 /* Request "save yourself" and "delete window" commands from wm. */
3800 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3801 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3802 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3805 /* x_set_name normally ignores requests to set the name if the
3806 requested name is the same as the current name. This is the one
3807 place where that assumption isn't correct; f->name is set, but
3808 the X server hasn't been told. */
3811 int explicit = f
->explicit_name
;
3813 f
->explicit_name
= 0;
3816 x_set_name (f
, name
, explicit);
3819 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3820 f
->output_data
.x
->text_cursor
);
3824 if (FRAME_X_WINDOW (f
) == 0)
3825 error ("Unable to create window");
3828 #endif /* not USE_X_TOOLKIT */
3830 /* Handle the icon stuff for this window. Perhaps later we might
3831 want an x_set_icon_position which can be called interactively as
3839 Lisp_Object icon_x
, icon_y
;
3840 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3842 /* Set the position of the icon. Note that twm groups all
3843 icons in an icon window. */
3844 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3845 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3846 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3848 CHECK_NUMBER (icon_x
, 0);
3849 CHECK_NUMBER (icon_y
, 0);
3851 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3852 error ("Both left and top icon corners of icon must be specified");
3856 if (! EQ (icon_x
, Qunbound
))
3857 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3859 /* Start up iconic or window? */
3860 x_wm_set_window_state
3861 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3866 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3873 /* Make the GCs needed for this window, setting the
3874 background, border and mouse colors; also create the
3875 mouse cursor and the gray border tile. */
3877 static char cursor_bits
[] =
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,
3882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3889 XGCValues gc_values
;
3893 /* Create the GCs of this frame.
3894 Note that many default values are used. */
3897 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3898 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3899 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3900 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3901 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3903 GCLineWidth
| GCFont
3904 | GCForeground
| GCBackground
,
3907 /* Reverse video style. */
3908 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3909 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3910 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3912 GCFont
| GCForeground
| GCBackground
3916 /* Cursor has cursor-color background, background-color foreground. */
3917 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3918 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3919 gc_values
.fill_style
= FillOpaqueStippled
;
3921 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3922 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3923 cursor_bits
, 16, 16);
3924 f
->output_data
.x
->cursor_gc
3925 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3926 (GCFont
| GCForeground
| GCBackground
3927 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3931 f
->output_data
.x
->white_relief
.gc
= 0;
3932 f
->output_data
.x
->black_relief
.gc
= 0;
3934 /* Create the gray border tile used when the pointer is not in
3935 the frame. Since this depends on the frame's pixel values,
3936 this must be done on a per-frame basis. */
3937 f
->output_data
.x
->border_tile
3938 = (XCreatePixmapFromBitmapData
3939 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3940 gray_bits
, gray_width
, gray_height
,
3941 f
->output_data
.x
->foreground_pixel
,
3942 f
->output_data
.x
->background_pixel
,
3943 DefaultDepth (FRAME_X_DISPLAY (f
),
3944 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3949 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3951 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3952 Returns an Emacs frame object.\n\
3953 ALIST is an alist of frame parameters.\n\
3954 If the parameters specify that the frame should not have a minibuffer,\n\
3955 and do not specify a specific minibuffer window to use,\n\
3956 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3957 be shared by the new frame.\n\
3959 This function is an internal primitive--use `make-frame' instead.")
3964 Lisp_Object frame
, tem
;
3966 int minibuffer_only
= 0;
3967 long window_prompting
= 0;
3969 int count
= specpdl_ptr
- specpdl
;
3970 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3971 Lisp_Object display
;
3972 struct x_display_info
*dpyinfo
= NULL
;
3978 /* Use this general default value to start with
3979 until we know if this frame has a specified name. */
3980 Vx_resource_name
= Vinvocation_name
;
3982 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3983 if (EQ (display
, Qunbound
))
3985 dpyinfo
= check_x_display_info (display
);
3987 kb
= dpyinfo
->kboard
;
3989 kb
= &the_only_kboard
;
3992 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3994 && ! EQ (name
, Qunbound
)
3996 error ("Invalid frame name--not a string or nil");
3999 Vx_resource_name
= name
;
4001 /* See if parent window is specified. */
4002 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4003 if (EQ (parent
, Qunbound
))
4005 if (! NILP (parent
))
4006 CHECK_NUMBER (parent
, 0);
4008 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4009 /* No need to protect DISPLAY because that's not used after passing
4010 it to make_frame_without_minibuffer. */
4012 GCPRO4 (parms
, parent
, name
, frame
);
4013 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
4015 if (EQ (tem
, Qnone
) || NILP (tem
))
4016 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4017 else if (EQ (tem
, Qonly
))
4019 f
= make_minibuffer_frame ();
4020 minibuffer_only
= 1;
4022 else if (WINDOWP (tem
))
4023 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4027 XSETFRAME (frame
, f
);
4029 /* Note that X Windows does support scroll bars. */
4030 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4032 f
->output_method
= output_x_window
;
4033 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
4034 bzero (f
->output_data
.x
, sizeof (struct x_output
));
4035 f
->output_data
.x
->icon_bitmap
= -1;
4036 f
->output_data
.x
->fontset
= -1;
4037 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
4038 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
4041 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4043 if (! STRINGP (f
->icon_name
))
4044 f
->icon_name
= Qnil
;
4046 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4048 FRAME_KBOARD (f
) = kb
;
4051 /* These colors will be set anyway later, but it's important
4052 to get the color reference counts right, so initialize them! */
4055 struct gcpro gcpro1
;
4057 black
= build_string ("black");
4059 f
->output_data
.x
->foreground_pixel
4060 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4061 f
->output_data
.x
->background_pixel
4062 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4063 f
->output_data
.x
->cursor_pixel
4064 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4065 f
->output_data
.x
->cursor_foreground_pixel
4066 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4067 f
->output_data
.x
->border_pixel
4068 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4069 f
->output_data
.x
->mouse_pixel
4070 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4074 /* Specify the parent under which to make this X window. */
4078 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4079 f
->output_data
.x
->explicit_parent
= 1;
4083 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4084 f
->output_data
.x
->explicit_parent
= 0;
4087 /* Set the name; the functions to which we pass f expect the name to
4089 if (EQ (name
, Qunbound
) || NILP (name
))
4091 f
->name
= build_string (dpyinfo
->x_id_name
);
4092 f
->explicit_name
= 0;
4097 f
->explicit_name
= 1;
4098 /* use the frame's title when getting resources for this frame. */
4099 specbind (Qx_resource_name
, name
);
4102 /* Extract the window parameters from the supplied values
4103 that are needed to determine window geometry. */
4107 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4110 /* First, try whatever font the caller has specified. */
4113 tem
= Fquery_fontset (font
, Qnil
);
4115 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4117 font
= x_new_font (f
, XSTRING (font
)->data
);
4120 /* Try out a font which we hope has bold and italic variations. */
4121 if (!STRINGP (font
))
4122 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4123 if (!STRINGP (font
))
4124 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4125 if (! STRINGP (font
))
4126 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4127 if (! STRINGP (font
))
4128 /* This was formerly the first thing tried, but it finds too many fonts
4129 and takes too long. */
4130 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4131 /* If those didn't work, look for something which will at least work. */
4132 if (! STRINGP (font
))
4133 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4135 if (! STRINGP (font
))
4136 font
= build_string ("fixed");
4138 x_default_parameter (f
, parms
, Qfont
, font
,
4139 "font", "Font", RES_TYPE_STRING
);
4143 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4144 whereby it fails to get any font. */
4145 xlwmenu_default_font
= f
->output_data
.x
->font
;
4148 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4149 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4151 /* This defaults to 2 in order to match xterm. We recognize either
4152 internalBorderWidth or internalBorder (which is what xterm calls
4154 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4158 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4159 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4160 if (! EQ (value
, Qunbound
))
4161 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4164 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4165 "internalBorderWidth", "internalBorderWidth",
4167 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4168 "verticalScrollBars", "ScrollBars",
4171 /* Also do the stuff which must be set before the window exists. */
4172 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4173 "foreground", "Foreground", RES_TYPE_STRING
);
4174 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4175 "background", "Background", RES_TYPE_STRING
);
4176 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4177 "pointerColor", "Foreground", RES_TYPE_STRING
);
4178 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4179 "cursorColor", "Foreground", RES_TYPE_STRING
);
4180 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4181 "borderColor", "BorderColor", RES_TYPE_STRING
);
4182 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4183 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4184 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4185 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4187 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4188 "scrollBarForeground",
4189 "ScrollBarForeground", 1);
4190 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4191 "scrollBarBackground",
4192 "ScrollBarBackground", 0);
4194 /* Init faces before x_default_parameter is called for scroll-bar
4195 parameters because that function calls x_set_scroll_bar_width,
4196 which calls change_frame_size, which calls Fset_window_buffer,
4197 which runs hooks, which call Fvertical_motion. At the end, we
4198 end up in init_iterator with a null face cache, which should not
4200 init_frame_faces (f
);
4202 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4203 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4204 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (1),
4205 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4206 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4207 "bufferPredicate", "BufferPredicate",
4209 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4210 "title", "Title", RES_TYPE_STRING
);
4212 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4213 window_prompting
= x_figure_window_size (f
, parms
);
4215 if (window_prompting
& XNegative
)
4217 if (window_prompting
& YNegative
)
4218 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4220 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4224 if (window_prompting
& YNegative
)
4225 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4227 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4230 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4232 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4233 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4235 /* Create the X widget or window. Add the tool-bar height to the
4236 initial frame height so that the user gets a text display area of
4237 the size he specified with -g or via .Xdefaults. Later changes
4238 of the tool-bar height don't change the frame size. This is done
4239 so that users can create tall Emacs frames without having to
4240 guess how tall the tool-bar will get. */
4241 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
4243 #ifdef USE_X_TOOLKIT
4244 x_window (f
, window_prompting
, minibuffer_only
);
4252 /* Now consider the frame official. */
4253 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4254 Vframe_list
= Fcons (frame
, Vframe_list
);
4256 /* We need to do this after creating the X window, so that the
4257 icon-creation functions can say whose icon they're describing. */
4258 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4259 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4261 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4262 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4263 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4264 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4265 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4266 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4267 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4268 "scrollBarWidth", "ScrollBarWidth",
4271 /* Dimensions, especially f->height, must be done via change_frame_size.
4272 Change will not be effected unless different from the current
4277 SET_FRAME_WIDTH (f
, 0);
4278 change_frame_size (f
, height
, width
, 1, 0, 0);
4280 /* Set up faces after all frame parameters are known. */
4281 call1 (Qface_set_after_frame_default
, frame
);
4283 #ifdef USE_X_TOOLKIT
4284 /* Create the menu bar. */
4285 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4287 /* If this signals an error, we haven't set size hints for the
4288 frame and we didn't make it visible. */
4289 initialize_frame_menubar (f
);
4291 /* This is a no-op, except under Motif where it arranges the
4292 main window for the widgets on it. */
4293 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4294 f
->output_data
.x
->menubar_widget
,
4295 f
->output_data
.x
->edit_widget
);
4297 #endif /* USE_X_TOOLKIT */
4299 /* Tell the server what size and position, etc, we want, and how
4300 badly we want them. This should be done after we have the menu
4301 bar so that its size can be taken into account. */
4303 x_wm_set_size_hint (f
, window_prompting
, 0);
4306 /* Make the window appear on the frame and enable display, unless
4307 the caller says not to. However, with explicit parent, Emacs
4308 cannot control visibility, so don't try. */
4309 if (! f
->output_data
.x
->explicit_parent
)
4311 Lisp_Object visibility
;
4313 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4315 if (EQ (visibility
, Qunbound
))
4318 if (EQ (visibility
, Qicon
))
4319 x_iconify_frame (f
);
4320 else if (! NILP (visibility
))
4321 x_make_frame_visible (f
);
4323 /* Must have been Qnil. */
4328 return unbind_to (count
, frame
);
4331 /* FRAME is used only to get a handle on the X display. We don't pass the
4332 display info directly because we're called from frame.c, which doesn't
4333 know about that structure. */
4336 x_get_focus_frame (frame
)
4337 struct frame
*frame
;
4339 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4341 if (! dpyinfo
->x_focus_frame
)
4344 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4349 /* In certain situations, when the window manager follows a
4350 click-to-focus policy, there seems to be no way around calling
4351 XSetInputFocus to give another frame the input focus .
4353 In an ideal world, XSetInputFocus should generally be avoided so
4354 that applications don't interfere with the window manager's focus
4355 policy. But I think it's okay to use when it's clearly done
4356 following a user-command. */
4358 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4359 "Set the input focus to FRAME.\n\
4360 FRAME nil means use the selected frame.")
4364 struct frame
*f
= check_x_frame (frame
);
4365 Display
*dpy
= FRAME_X_DISPLAY (f
);
4369 count
= x_catch_errors (dpy
);
4370 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4371 RevertToParent
, CurrentTime
);
4372 x_uncatch_errors (dpy
, count
);
4379 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4380 "Internal function called by `color-defined-p', which see.")
4382 Lisp_Object color
, frame
;
4385 FRAME_PTR f
= check_x_frame (frame
);
4387 CHECK_STRING (color
, 1);
4389 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4395 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4396 "Internal function called by `color-values', which see.")
4398 Lisp_Object color
, frame
;
4401 FRAME_PTR f
= check_x_frame (frame
);
4403 CHECK_STRING (color
, 1);
4405 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4409 rgb
[0] = make_number (foo
.red
);
4410 rgb
[1] = make_number (foo
.green
);
4411 rgb
[2] = make_number (foo
.blue
);
4412 return Flist (3, rgb
);
4418 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4419 "Internal function called by `display-color-p', which see.")
4421 Lisp_Object display
;
4423 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4425 if (dpyinfo
->n_planes
<= 2)
4428 switch (dpyinfo
->visual
->class)
4441 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4443 "Return t if the X display supports shades of gray.\n\
4444 Note that color displays do support shades of gray.\n\
4445 The optional argument DISPLAY specifies which display to ask about.\n\
4446 DISPLAY should be either a frame or a display name (a string).\n\
4447 If omitted or nil, that stands for the selected frame's display.")
4449 Lisp_Object display
;
4451 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4453 if (dpyinfo
->n_planes
<= 1)
4456 switch (dpyinfo
->visual
->class)
4471 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4473 "Returns the width in pixels of the X display DISPLAY.\n\
4474 The optional argument DISPLAY specifies which display to ask about.\n\
4475 DISPLAY should be either a frame or a display name (a string).\n\
4476 If omitted or nil, that stands for the selected frame's display.")
4478 Lisp_Object display
;
4480 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4482 return make_number (dpyinfo
->width
);
4485 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4486 Sx_display_pixel_height
, 0, 1, 0,
4487 "Returns the height in pixels of the X display DISPLAY.\n\
4488 The optional argument DISPLAY specifies which display to ask about.\n\
4489 DISPLAY should be either a frame or a display name (a string).\n\
4490 If omitted or nil, that stands for the selected frame's display.")
4492 Lisp_Object display
;
4494 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4496 return make_number (dpyinfo
->height
);
4499 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4501 "Returns the number of bitplanes of the X display DISPLAY.\n\
4502 The optional argument DISPLAY specifies which display to ask about.\n\
4503 DISPLAY should be either a frame or a display name (a string).\n\
4504 If omitted or nil, that stands for the selected frame's display.")
4506 Lisp_Object display
;
4508 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4510 return make_number (dpyinfo
->n_planes
);
4513 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4515 "Returns the number of color cells of the X display DISPLAY.\n\
4516 The optional argument DISPLAY specifies which display to ask about.\n\
4517 DISPLAY should be either a frame or a display name (a string).\n\
4518 If omitted or nil, that stands for the selected frame's display.")
4520 Lisp_Object display
;
4522 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4524 return make_number (DisplayCells (dpyinfo
->display
,
4525 XScreenNumberOfScreen (dpyinfo
->screen
)));
4528 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4529 Sx_server_max_request_size
,
4531 "Returns the maximum request size of the X server of display DISPLAY.\n\
4532 The optional argument DISPLAY specifies which display to ask about.\n\
4533 DISPLAY should be either a frame or a display name (a string).\n\
4534 If omitted or nil, that stands for the selected frame's display.")
4536 Lisp_Object display
;
4538 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4540 return make_number (MAXREQUEST (dpyinfo
->display
));
4543 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4544 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4545 The optional argument DISPLAY specifies which display to ask about.\n\
4546 DISPLAY should be either a frame or a display name (a string).\n\
4547 If omitted or nil, that stands for the selected frame's display.")
4549 Lisp_Object display
;
4551 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4552 char *vendor
= ServerVendor (dpyinfo
->display
);
4554 if (! vendor
) vendor
= "";
4555 return build_string (vendor
);
4558 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4559 "Returns the version numbers of the X server of display DISPLAY.\n\
4560 The value is a list of three integers: the major and minor\n\
4561 version numbers of the X Protocol in use, and the vendor-specific release\n\
4562 number. See also the function `x-server-vendor'.\n\n\
4563 The optional argument DISPLAY specifies which display to ask about.\n\
4564 DISPLAY should be either a frame or a display name (a string).\n\
4565 If omitted or nil, that stands for the selected frame's display.")
4567 Lisp_Object display
;
4569 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4570 Display
*dpy
= dpyinfo
->display
;
4572 return Fcons (make_number (ProtocolVersion (dpy
)),
4573 Fcons (make_number (ProtocolRevision (dpy
)),
4574 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4577 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4578 "Returns the number of screens on the X server of display DISPLAY.\n\
4579 The optional argument DISPLAY specifies which display to ask about.\n\
4580 DISPLAY should be either a frame or a display name (a string).\n\
4581 If omitted or nil, that stands for the selected frame's display.")
4583 Lisp_Object display
;
4585 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4587 return make_number (ScreenCount (dpyinfo
->display
));
4590 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4591 "Returns the height in millimeters of the X display DISPLAY.\n\
4592 The optional argument DISPLAY specifies which display to ask about.\n\
4593 DISPLAY should be either a frame or a display name (a string).\n\
4594 If omitted or nil, that stands for the selected frame's display.")
4596 Lisp_Object display
;
4598 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4600 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4603 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4604 "Returns the width in millimeters of the X display DISPLAY.\n\
4605 The optional argument DISPLAY specifies which display to ask about.\n\
4606 DISPLAY should be either a frame or a display name (a string).\n\
4607 If omitted or nil, that stands for the selected frame's display.")
4609 Lisp_Object display
;
4611 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4613 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4616 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4617 Sx_display_backing_store
, 0, 1, 0,
4618 "Returns an indication of whether X display DISPLAY does backing store.\n\
4619 The value may be `always', `when-mapped', or `not-useful'.\n\
4620 The optional argument DISPLAY specifies which display to ask about.\n\
4621 DISPLAY should be either a frame or a display name (a string).\n\
4622 If omitted or nil, that stands for the selected frame's display.")
4624 Lisp_Object display
;
4626 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4629 switch (DoesBackingStore (dpyinfo
->screen
))
4632 result
= intern ("always");
4636 result
= intern ("when-mapped");
4640 result
= intern ("not-useful");
4644 error ("Strange value for BackingStore parameter of screen");
4651 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4652 Sx_display_visual_class
, 0, 1, 0,
4653 "Returns the visual class of the X display DISPLAY.\n\
4654 The value is one of the symbols `static-gray', `gray-scale',\n\
4655 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4656 The optional argument DISPLAY specifies which display to ask about.\n\
4657 DISPLAY should be either a frame or a display name (a string).\n\
4658 If omitted or nil, that stands for the selected frame's display.")
4660 Lisp_Object display
;
4662 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4665 switch (dpyinfo
->visual
->class)
4668 result
= intern ("static-gray");
4671 result
= intern ("gray-scale");
4674 result
= intern ("static-color");
4677 result
= intern ("pseudo-color");
4680 result
= intern ("true-color");
4683 result
= intern ("direct-color");
4686 error ("Display has an unknown visual class");
4693 DEFUN ("x-display-save-under", Fx_display_save_under
,
4694 Sx_display_save_under
, 0, 1, 0,
4695 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4696 The optional argument DISPLAY specifies which display to ask about.\n\
4697 DISPLAY should be either a frame or a display name (a string).\n\
4698 If omitted or nil, that stands for the selected frame's display.")
4700 Lisp_Object display
;
4702 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4704 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4712 register struct frame
*f
;
4714 return PIXEL_WIDTH (f
);
4719 register struct frame
*f
;
4721 return PIXEL_HEIGHT (f
);
4726 register struct frame
*f
;
4728 return FONT_WIDTH (f
->output_data
.x
->font
);
4733 register struct frame
*f
;
4735 return f
->output_data
.x
->line_height
;
4740 register struct frame
*f
;
4742 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4747 /************************************************************************
4749 ************************************************************************/
4752 /* Mapping visual names to visuals. */
4754 static struct visual_class
4761 {"StaticGray", StaticGray
},
4762 {"GrayScale", GrayScale
},
4763 {"StaticColor", StaticColor
},
4764 {"PseudoColor", PseudoColor
},
4765 {"TrueColor", TrueColor
},
4766 {"DirectColor", DirectColor
},
4771 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4773 /* Value is the screen number of screen SCR. This is a substitute for
4774 the X function with the same name when that doesn't exist. */
4777 XScreenNumberOfScreen (scr
)
4778 register Screen
*scr
;
4780 Display
*dpy
= scr
->display
;
4783 for (i
= 0; i
< dpy
->nscreens
; ++i
)
4784 if (scr
== dpy
->screens
[i
])
4790 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4793 /* Select the visual that should be used on display DPYINFO. Set
4794 members of DPYINFO appropriately. Called from x_term_init. */
4797 select_visual (dpyinfo
)
4798 struct x_display_info
*dpyinfo
;
4800 Display
*dpy
= dpyinfo
->display
;
4801 Screen
*screen
= dpyinfo
->screen
;
4804 /* See if a visual is specified. */
4805 value
= display_x_get_resource (dpyinfo
,
4806 build_string ("visualClass"),
4807 build_string ("VisualClass"),
4809 if (STRINGP (value
))
4811 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4812 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4813 depth, a decimal number. NAME is compared with case ignored. */
4814 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
4819 strcpy (s
, XSTRING (value
)->data
);
4820 dash
= index (s
, '-');
4823 dpyinfo
->n_planes
= atoi (dash
+ 1);
4827 /* We won't find a matching visual with depth 0, so that
4828 an error will be printed below. */
4829 dpyinfo
->n_planes
= 0;
4831 /* Determine the visual class. */
4832 for (i
= 0; visual_classes
[i
].name
; ++i
)
4833 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
4835 class = visual_classes
[i
].class;
4839 /* Look up a matching visual for the specified class. */
4841 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
4842 dpyinfo
->n_planes
, class, &vinfo
))
4843 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
4845 dpyinfo
->visual
= vinfo
.visual
;
4850 XVisualInfo
*vinfo
, vinfo_template
;
4852 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
4855 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
4857 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
4859 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
4860 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
4861 &vinfo_template
, &n_visuals
);
4863 fatal ("Can't get proper X visual info");
4865 dpyinfo
->n_planes
= vinfo
->depth
;
4866 XFree ((char *) vinfo
);
4871 /* Return the X display structure for the display named NAME.
4872 Open a new connection if necessary. */
4874 struct x_display_info
*
4875 x_display_info_for_name (name
)
4879 struct x_display_info
*dpyinfo
;
4881 CHECK_STRING (name
, 0);
4883 if (! EQ (Vwindow_system
, intern ("x")))
4884 error ("Not using X Windows");
4886 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
4888 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4891 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4896 /* Use this general default value to start with. */
4897 Vx_resource_name
= Vinvocation_name
;
4899 validate_x_resource_name ();
4901 dpyinfo
= x_term_init (name
, (unsigned char *)0,
4902 (char *) XSTRING (Vx_resource_name
)->data
);
4905 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
4908 XSETFASTINT (Vwindow_system_version
, 11);
4914 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4915 1, 3, 0, "Open a connection to an X server.\n\
4916 DISPLAY is the name of the display to connect to.\n\
4917 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4918 If the optional third arg MUST-SUCCEED is non-nil,\n\
4919 terminate Emacs if we can't open the connection.")
4920 (display
, xrm_string
, must_succeed
)
4921 Lisp_Object display
, xrm_string
, must_succeed
;
4923 unsigned char *xrm_option
;
4924 struct x_display_info
*dpyinfo
;
4926 CHECK_STRING (display
, 0);
4927 if (! NILP (xrm_string
))
4928 CHECK_STRING (xrm_string
, 1);
4930 if (! EQ (Vwindow_system
, intern ("x")))
4931 error ("Not using X Windows");
4933 if (! NILP (xrm_string
))
4934 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
4936 xrm_option
= (unsigned char *) 0;
4938 validate_x_resource_name ();
4940 /* This is what opens the connection and sets x_current_display.
4941 This also initializes many symbols, such as those used for input. */
4942 dpyinfo
= x_term_init (display
, xrm_option
,
4943 (char *) XSTRING (Vx_resource_name
)->data
);
4947 if (!NILP (must_succeed
))
4948 fatal ("Cannot connect to X server %s.\n\
4949 Check the DISPLAY environment variable or use `-d'.\n\
4950 Also use the `xhost' program to verify that it is set to permit\n\
4951 connections from your machine.\n",
4952 XSTRING (display
)->data
);
4954 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
4959 XSETFASTINT (Vwindow_system_version
, 11);
4963 DEFUN ("x-close-connection", Fx_close_connection
,
4964 Sx_close_connection
, 1, 1, 0,
4965 "Close the connection to DISPLAY's X server.\n\
4966 For DISPLAY, specify either a frame or a display name (a string).\n\
4967 If DISPLAY is nil, that stands for the selected frame's display.")
4969 Lisp_Object display
;
4971 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4974 if (dpyinfo
->reference_count
> 0)
4975 error ("Display still has frames on it");
4978 /* Free the fonts in the font table. */
4979 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4980 if (dpyinfo
->font_table
[i
].name
)
4982 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
4983 xfree (dpyinfo
->font_table
[i
].full_name
);
4984 xfree (dpyinfo
->font_table
[i
].name
);
4985 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
4988 x_destroy_all_bitmaps (dpyinfo
);
4989 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
4991 #ifdef USE_X_TOOLKIT
4992 XtCloseDisplay (dpyinfo
->display
);
4994 XCloseDisplay (dpyinfo
->display
);
4997 x_delete_display (dpyinfo
);
5003 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5004 "Return the list of display names that Emacs has connections to.")
5007 Lisp_Object tail
, result
;
5010 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5011 result
= Fcons (XCAR (XCAR (tail
)), result
);
5016 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5017 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5018 If ON is nil, allow buffering of requests.\n\
5019 Turning on synchronization prohibits the Xlib routines from buffering\n\
5020 requests and seriously degrades performance, but makes debugging much\n\
5022 The optional second argument DISPLAY specifies which display to act on.\n\
5023 DISPLAY should be either a frame or a display name (a string).\n\
5024 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5026 Lisp_Object display
, on
;
5028 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5030 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5035 /* Wait for responses to all X commands issued so far for frame F. */
5042 XSync (FRAME_X_DISPLAY (f
), False
);
5047 /***********************************************************************
5049 ***********************************************************************/
5051 /* Value is the number of elements of vector VECTOR. */
5053 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5055 /* List of supported image types. Use define_image_type to add new
5056 types. Use lookup_image_type to find a type for a given symbol. */
5058 static struct image_type
*image_types
;
5060 /* The symbol `image' which is the car of the lists used to represent
5063 extern Lisp_Object Qimage
;
5065 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5071 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5072 extern Lisp_Object QCdata
;
5073 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5074 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5075 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
5077 /* Other symbols. */
5079 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
5081 /* Time in seconds after which images should be removed from the cache
5082 if not displayed. */
5084 Lisp_Object Vimage_cache_eviction_delay
;
5086 /* Function prototypes. */
5088 static void define_image_type
P_ ((struct image_type
*type
));
5089 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5090 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5091 static void x_laplace
P_ ((struct frame
*, struct image
*));
5092 static void x_emboss
P_ ((struct frame
*, struct image
*));
5093 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5097 /* Define a new image type from TYPE. This adds a copy of TYPE to
5098 image_types and adds the symbol *TYPE->type to Vimage_types. */
5101 define_image_type (type
)
5102 struct image_type
*type
;
5104 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5105 The initialized data segment is read-only. */
5106 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5107 bcopy (type
, p
, sizeof *p
);
5108 p
->next
= image_types
;
5110 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5114 /* Look up image type SYMBOL, and return a pointer to its image_type
5115 structure. Value is null if SYMBOL is not a known image type. */
5117 static INLINE
struct image_type
*
5118 lookup_image_type (symbol
)
5121 struct image_type
*type
;
5123 for (type
= image_types
; type
; type
= type
->next
)
5124 if (EQ (symbol
, *type
->type
))
5131 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5132 valid image specification is a list whose car is the symbol
5133 `image', and whose rest is a property list. The property list must
5134 contain a value for key `:type'. That value must be the name of a
5135 supported image type. The rest of the property list depends on the
5139 valid_image_p (object
)
5144 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5146 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5147 struct image_type
*type
= lookup_image_type (symbol
);
5150 valid_p
= type
->valid_p (object
);
5157 /* Log error message with format string FORMAT and argument ARG.
5158 Signaling an error, e.g. when an image cannot be loaded, is not a
5159 good idea because this would interrupt redisplay, and the error
5160 message display would lead to another redisplay. This function
5161 therefore simply displays a message. */
5164 image_error (format
, arg1
, arg2
)
5166 Lisp_Object arg1
, arg2
;
5168 add_to_log (format
, arg1
, arg2
);
5173 /***********************************************************************
5174 Image specifications
5175 ***********************************************************************/
5177 enum image_value_type
5179 IMAGE_DONT_CHECK_VALUE_TYPE
,
5182 IMAGE_POSITIVE_INTEGER_VALUE
,
5183 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5185 IMAGE_INTEGER_VALUE
,
5186 IMAGE_FUNCTION_VALUE
,
5191 /* Structure used when parsing image specifications. */
5193 struct image_keyword
5195 /* Name of keyword. */
5198 /* The type of value allowed. */
5199 enum image_value_type type
;
5201 /* Non-zero means key must be present. */
5204 /* Used to recognize duplicate keywords in a property list. */
5207 /* The value that was found. */
5212 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5214 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5217 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5218 has the format (image KEYWORD VALUE ...). One of the keyword/
5219 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5220 image_keywords structures of size NKEYWORDS describing other
5221 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5224 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5226 struct image_keyword
*keywords
;
5233 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5236 plist
= XCDR (spec
);
5237 while (CONSP (plist
))
5239 Lisp_Object key
, value
;
5241 /* First element of a pair must be a symbol. */
5243 plist
= XCDR (plist
);
5247 /* There must follow a value. */
5250 value
= XCAR (plist
);
5251 plist
= XCDR (plist
);
5253 /* Find key in KEYWORDS. Error if not found. */
5254 for (i
= 0; i
< nkeywords
; ++i
)
5255 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5261 /* Record that we recognized the keyword. If a keywords
5262 was found more than once, it's an error. */
5263 keywords
[i
].value
= value
;
5264 ++keywords
[i
].count
;
5266 if (keywords
[i
].count
> 1)
5269 /* Check type of value against allowed type. */
5270 switch (keywords
[i
].type
)
5272 case IMAGE_STRING_VALUE
:
5273 if (!STRINGP (value
))
5277 case IMAGE_SYMBOL_VALUE
:
5278 if (!SYMBOLP (value
))
5282 case IMAGE_POSITIVE_INTEGER_VALUE
:
5283 if (!INTEGERP (value
) || XINT (value
) <= 0)
5287 case IMAGE_ASCENT_VALUE
:
5288 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5290 else if (INTEGERP (value
)
5291 && XINT (value
) >= 0
5292 && XINT (value
) <= 100)
5296 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5297 if (!INTEGERP (value
) || XINT (value
) < 0)
5301 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5304 case IMAGE_FUNCTION_VALUE
:
5305 value
= indirect_function (value
);
5307 || COMPILEDP (value
)
5308 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5312 case IMAGE_NUMBER_VALUE
:
5313 if (!INTEGERP (value
) && !FLOATP (value
))
5317 case IMAGE_INTEGER_VALUE
:
5318 if (!INTEGERP (value
))
5322 case IMAGE_BOOL_VALUE
:
5323 if (!NILP (value
) && !EQ (value
, Qt
))
5332 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5336 /* Check that all mandatory fields are present. */
5337 for (i
= 0; i
< nkeywords
; ++i
)
5338 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5341 return NILP (plist
);
5345 /* Return the value of KEY in image specification SPEC. Value is nil
5346 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5347 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5350 image_spec_value (spec
, key
, found
)
5351 Lisp_Object spec
, key
;
5356 xassert (valid_image_p (spec
));
5358 for (tail
= XCDR (spec
);
5359 CONSP (tail
) && CONSP (XCDR (tail
));
5360 tail
= XCDR (XCDR (tail
)))
5362 if (EQ (XCAR (tail
), key
))
5366 return XCAR (XCDR (tail
));
5376 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5377 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5378 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5379 size in canonical character units.\n\
5380 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5381 or omitted means use the selected frame.")
5382 (spec
, pixels
, frame
)
5383 Lisp_Object spec
, pixels
, frame
;
5388 if (valid_image_p (spec
))
5390 struct frame
*f
= check_x_frame (frame
);
5391 int id
= lookup_image (f
, spec
);
5392 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5393 int width
= img
->width
+ 2 * img
->margin
;
5394 int height
= img
->height
+ 2 * img
->margin
;
5397 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5398 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5400 size
= Fcons (make_number (width
), make_number (height
));
5403 error ("Invalid image specification");
5409 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
5410 "Return t if image SPEC has a mask bitmap.\n\
5411 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5412 or omitted means use the selected frame.")
5414 Lisp_Object spec
, frame
;
5419 if (valid_image_p (spec
))
5421 struct frame
*f
= check_x_frame (frame
);
5422 int id
= lookup_image (f
, spec
);
5423 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5428 error ("Invalid image specification");
5435 /***********************************************************************
5436 Image type independent image structures
5437 ***********************************************************************/
5439 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5440 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5443 /* Allocate and return a new image structure for image specification
5444 SPEC. SPEC has a hash value of HASH. */
5446 static struct image
*
5447 make_image (spec
, hash
)
5451 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5453 xassert (valid_image_p (spec
));
5454 bzero (img
, sizeof *img
);
5455 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5456 xassert (img
->type
!= NULL
);
5458 img
->data
.lisp_val
= Qnil
;
5459 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5465 /* Free image IMG which was used on frame F, including its resources. */
5474 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5476 /* Remove IMG from the hash table of its cache. */
5478 img
->prev
->next
= img
->next
;
5480 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5483 img
->next
->prev
= img
->prev
;
5485 c
->images
[img
->id
] = NULL
;
5487 /* Free resources, then free IMG. */
5488 img
->type
->free (f
, img
);
5494 /* Prepare image IMG for display on frame F. Must be called before
5495 drawing an image. */
5498 prepare_image_for_display (f
, img
)
5504 /* We're about to display IMG, so set its timestamp to `now'. */
5506 img
->timestamp
= EMACS_SECS (t
);
5508 /* If IMG doesn't have a pixmap yet, load it now, using the image
5509 type dependent loader function. */
5510 if (img
->pixmap
== None
&& !img
->load_failed_p
)
5511 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5515 /* Value is the number of pixels for the ascent of image IMG when
5516 drawn in face FACE. */
5519 image_ascent (img
, face
)
5523 int height
= img
->height
+ img
->margin
;
5526 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5529 /* This expression is arranged so that if the image can't be
5530 exactly centered, it will be moved slightly up. This is
5531 because a typical font is `top-heavy' (due to the presence
5532 uppercase letters), so the image placement should err towards
5533 being top-heavy too. It also just generally looks better. */
5534 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
5536 ascent
= height
/ 2;
5539 ascent
= height
* img
->ascent
/ 100.0;
5546 /***********************************************************************
5547 Helper functions for X image types
5548 ***********************************************************************/
5550 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
5552 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5553 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5555 Lisp_Object color_name
,
5556 unsigned long dflt
));
5559 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5560 free the pixmap if any. MASK_P non-zero means clear the mask
5561 pixmap if any. COLORS_P non-zero means free colors allocated for
5562 the image, if any. */
5565 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
5568 int pixmap_p
, mask_p
, colors_p
;
5570 if (pixmap_p
&& img
->pixmap
)
5572 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5576 if (mask_p
&& img
->mask
)
5578 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5582 if (colors_p
&& img
->ncolors
)
5584 x_free_colors (f
, img
->colors
, img
->ncolors
);
5585 xfree (img
->colors
);
5591 /* Free X resources of image IMG which is used on frame F. */
5594 x_clear_image (f
, img
)
5599 x_clear_image_1 (f
, img
, 1, 1, 1);
5604 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5605 cannot be allocated, use DFLT. Add a newly allocated color to
5606 IMG->colors, so that it can be freed again. Value is the pixel
5609 static unsigned long
5610 x_alloc_image_color (f
, img
, color_name
, dflt
)
5613 Lisp_Object color_name
;
5617 unsigned long result
;
5619 xassert (STRINGP (color_name
));
5621 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5623 /* This isn't called frequently so we get away with simply
5624 reallocating the color vector to the needed size, here. */
5627 (unsigned long *) xrealloc (img
->colors
,
5628 img
->ncolors
* sizeof *img
->colors
);
5629 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5630 result
= color
.pixel
;
5640 /***********************************************************************
5642 ***********************************************************************/
5644 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5647 /* Return a new, initialized image cache that is allocated from the
5648 heap. Call free_image_cache to free an image cache. */
5650 struct image_cache
*
5653 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5656 bzero (c
, sizeof *c
);
5658 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5659 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5660 c
->buckets
= (struct image
**) xmalloc (size
);
5661 bzero (c
->buckets
, size
);
5666 /* Free image cache of frame F. Be aware that X frames share images
5670 free_image_cache (f
)
5673 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5678 /* Cache should not be referenced by any frame when freed. */
5679 xassert (c
->refcount
== 0);
5681 for (i
= 0; i
< c
->used
; ++i
)
5682 free_image (f
, c
->images
[i
]);
5686 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5691 /* Clear image cache of frame F. FORCE_P non-zero means free all
5692 images. FORCE_P zero means clear only images that haven't been
5693 displayed for some time. Should be called from time to time to
5694 reduce the number of loaded images. If image-eviction-seconds is
5695 non-nil, this frees images in the cache which weren't displayed for
5696 at least that many seconds. */
5699 clear_image_cache (f
, force_p
)
5703 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5705 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5712 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5714 /* Block input so that we won't be interrupted by a SIGIO
5715 while being in an inconsistent state. */
5718 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
5720 struct image
*img
= c
->images
[i
];
5722 && (force_p
|| img
->timestamp
< old
))
5724 free_image (f
, img
);
5729 /* We may be clearing the image cache because, for example,
5730 Emacs was iconified for a longer period of time. In that
5731 case, current matrices may still contain references to
5732 images freed above. So, clear these matrices. */
5735 Lisp_Object tail
, frame
;
5737 FOR_EACH_FRAME (tail
, frame
)
5739 struct frame
*f
= XFRAME (frame
);
5741 && FRAME_X_IMAGE_CACHE (f
) == c
)
5742 clear_current_matrices (f
);
5745 ++windows_or_buffers_changed
;
5753 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5755 "Clear the image cache of FRAME.\n\
5756 FRAME nil or omitted means use the selected frame.\n\
5757 FRAME t means clear the image caches of all frames.")
5765 FOR_EACH_FRAME (tail
, frame
)
5766 if (FRAME_X_P (XFRAME (frame
)))
5767 clear_image_cache (XFRAME (frame
), 1);
5770 clear_image_cache (check_x_frame (frame
), 1);
5776 /* Return the id of image with Lisp specification SPEC on frame F.
5777 SPEC must be a valid Lisp image specification (see valid_image_p). */
5780 lookup_image (f
, spec
)
5784 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5788 struct gcpro gcpro1
;
5791 /* F must be a window-system frame, and SPEC must be a valid image
5793 xassert (FRAME_WINDOW_P (f
));
5794 xassert (valid_image_p (spec
));
5798 /* Look up SPEC in the hash table of the image cache. */
5799 hash
= sxhash (spec
, 0);
5800 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5802 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
5803 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
5806 /* If not found, create a new image and cache it. */
5810 img
= make_image (spec
, hash
);
5811 cache_image (f
, img
);
5812 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5814 /* If we can't load the image, and we don't have a width and
5815 height, use some arbitrary width and height so that we can
5816 draw a rectangle for it. */
5817 if (img
->load_failed_p
)
5821 value
= image_spec_value (spec
, QCwidth
, NULL
);
5822 img
->width
= (INTEGERP (value
)
5823 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
5824 value
= image_spec_value (spec
, QCheight
, NULL
);
5825 img
->height
= (INTEGERP (value
)
5826 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
5830 /* Handle image type independent image attributes
5831 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5832 Lisp_Object ascent
, margin
, relief
;
5835 ascent
= image_spec_value (spec
, QCascent
, NULL
);
5836 if (INTEGERP (ascent
))
5837 img
->ascent
= XFASTINT (ascent
);
5838 else if (EQ (ascent
, Qcenter
))
5839 img
->ascent
= CENTERED_IMAGE_ASCENT
;
5841 margin
= image_spec_value (spec
, QCmargin
, NULL
);
5842 if (INTEGERP (margin
) && XINT (margin
) >= 0)
5843 img
->margin
= XFASTINT (margin
);
5845 relief
= image_spec_value (spec
, QCrelief
, NULL
);
5846 if (INTEGERP (relief
))
5848 img
->relief
= XINT (relief
);
5849 img
->margin
+= abs (img
->relief
);
5852 /* Manipulation of the image's mask. */
5855 /* `:heuristic-mask t'
5857 means build a mask heuristically.
5858 `:heuristic-mask (R G B)'
5859 `:mask (heuristic (R G B))'
5860 means build a mask from color (R G B) in the
5863 means remove a mask, if any. */
5867 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
5869 x_build_heuristic_mask (f
, img
, mask
);
5874 mask
= image_spec_value (spec
, QCmask
, &found_p
);
5876 if (EQ (mask
, Qheuristic
))
5877 x_build_heuristic_mask (f
, img
, Qt
);
5878 else if (CONSP (mask
)
5879 && EQ (XCAR (mask
), Qheuristic
))
5881 if (CONSP (XCDR (mask
)))
5882 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
5884 x_build_heuristic_mask (f
, img
, XCDR (mask
));
5886 else if (NILP (mask
) && found_p
&& img
->mask
)
5888 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5894 /* Should we apply an image transformation algorithm? */
5897 Lisp_Object algorithm
;
5899 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
5900 if (EQ (algorithm
, Qdisabled
))
5901 x_disable_image (f
, img
);
5902 else if (EQ (algorithm
, Qlaplace
))
5904 else if (EQ (algorithm
, Qemboss
))
5906 else if (CONSP (algorithm
)
5907 && EQ (XCAR (algorithm
), Qedge_detection
))
5910 tem
= XCDR (algorithm
);
5912 x_edge_detection (f
, img
,
5913 Fplist_get (tem
, QCmatrix
),
5914 Fplist_get (tem
, QCcolor_adjustment
));
5920 xassert (!interrupt_input_blocked
);
5923 /* We're using IMG, so set its timestamp to `now'. */
5924 EMACS_GET_TIME (now
);
5925 img
->timestamp
= EMACS_SECS (now
);
5929 /* Value is the image id. */
5934 /* Cache image IMG in the image cache of frame F. */
5937 cache_image (f
, img
)
5941 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5944 /* Find a free slot in c->images. */
5945 for (i
= 0; i
< c
->used
; ++i
)
5946 if (c
->images
[i
] == NULL
)
5949 /* If no free slot found, maybe enlarge c->images. */
5950 if (i
== c
->used
&& c
->used
== c
->size
)
5953 c
->images
= (struct image
**) xrealloc (c
->images
,
5954 c
->size
* sizeof *c
->images
);
5957 /* Add IMG to c->images, and assign IMG an id. */
5963 /* Add IMG to the cache's hash table. */
5964 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5965 img
->next
= c
->buckets
[i
];
5967 img
->next
->prev
= img
;
5969 c
->buckets
[i
] = img
;
5973 /* Call FN on every image in the image cache of frame F. Used to mark
5974 Lisp Objects in the image cache. */
5977 forall_images_in_image_cache (f
, fn
)
5979 void (*fn
) P_ ((struct image
*img
));
5981 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
5983 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5987 for (i
= 0; i
< c
->used
; ++i
)
5996 /***********************************************************************
5998 ***********************************************************************/
6000 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6001 XImage
**, Pixmap
*));
6002 static void x_destroy_x_image
P_ ((XImage
*));
6003 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6006 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6007 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6008 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6009 via xmalloc. Print error messages via image_error if an error
6010 occurs. Value is non-zero if successful. */
6013 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6015 int width
, height
, depth
;
6019 Display
*display
= FRAME_X_DISPLAY (f
);
6020 Screen
*screen
= FRAME_X_SCREEN (f
);
6021 Window window
= FRAME_X_WINDOW (f
);
6023 xassert (interrupt_input_blocked
);
6026 depth
= DefaultDepthOfScreen (screen
);
6027 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6028 depth
, ZPixmap
, 0, NULL
, width
, height
,
6029 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6032 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6036 /* Allocate image raster. */
6037 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6039 /* Allocate a pixmap of the same size. */
6040 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6041 if (*pixmap
== None
)
6043 x_destroy_x_image (*ximg
);
6045 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6053 /* Destroy XImage XIMG. Free XIMG->data. */
6056 x_destroy_x_image (ximg
)
6059 xassert (interrupt_input_blocked
);
6064 XDestroyImage (ximg
);
6069 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6070 are width and height of both the image and pixmap. */
6073 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6080 xassert (interrupt_input_blocked
);
6081 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6082 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6083 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6088 /***********************************************************************
6090 ***********************************************************************/
6092 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6093 static char *slurp_file
P_ ((char *, int *));
6096 /* Find image file FILE. Look in data-directory, then
6097 x-bitmap-file-path. Value is the full name of the file found, or
6098 nil if not found. */
6101 x_find_image_file (file
)
6104 Lisp_Object file_found
, search_path
;
6105 struct gcpro gcpro1
, gcpro2
;
6109 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6110 GCPRO2 (file_found
, search_path
);
6112 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6113 fd
= openp (search_path
, file
, "", &file_found
, 0);
6125 /* Read FILE into memory. Value is a pointer to a buffer allocated
6126 with xmalloc holding FILE's contents. Value is null if an error
6127 occurred. *SIZE is set to the size of the file. */
6130 slurp_file (file
, size
)
6138 if (stat (file
, &st
) == 0
6139 && (fp
= fopen (file
, "r")) != NULL
6140 && (buf
= (char *) xmalloc (st
.st_size
),
6141 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6162 /***********************************************************************
6164 ***********************************************************************/
6166 static int xbm_scan
P_ ((char **, char *, char *, int *));
6167 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6168 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
6170 static int xbm_image_p
P_ ((Lisp_Object object
));
6171 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
6173 static int xbm_file_p
P_ ((Lisp_Object
));
6176 /* Indices of image specification fields in xbm_format, below. */
6178 enum xbm_keyword_index
6196 /* Vector of image_keyword structures describing the format
6197 of valid XBM image specifications. */
6199 static struct image_keyword xbm_format
[XBM_LAST
] =
6201 {":type", IMAGE_SYMBOL_VALUE
, 1},
6202 {":file", IMAGE_STRING_VALUE
, 0},
6203 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6204 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6205 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6206 {":foreground", IMAGE_STRING_VALUE
, 0},
6207 {":background", IMAGE_STRING_VALUE
, 0},
6208 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6209 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6210 {":relief", IMAGE_INTEGER_VALUE
, 0},
6211 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6212 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6213 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6216 /* Structure describing the image type XBM. */
6218 static struct image_type xbm_type
=
6227 /* Tokens returned from xbm_scan. */
6236 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6237 A valid specification is a list starting with the symbol `image'
6238 The rest of the list is a property list which must contain an
6241 If the specification specifies a file to load, it must contain
6242 an entry `:file FILENAME' where FILENAME is a string.
6244 If the specification is for a bitmap loaded from memory it must
6245 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6246 WIDTH and HEIGHT are integers > 0. DATA may be:
6248 1. a string large enough to hold the bitmap data, i.e. it must
6249 have a size >= (WIDTH + 7) / 8 * HEIGHT
6251 2. a bool-vector of size >= WIDTH * HEIGHT
6253 3. a vector of strings or bool-vectors, one for each line of the
6256 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6257 may not be specified in this case because they are defined in the
6260 Both the file and data forms may contain the additional entries
6261 `:background COLOR' and `:foreground COLOR'. If not present,
6262 foreground and background of the frame on which the image is
6263 displayed is used. */
6266 xbm_image_p (object
)
6269 struct image_keyword kw
[XBM_LAST
];
6271 bcopy (xbm_format
, kw
, sizeof kw
);
6272 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6275 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6277 if (kw
[XBM_FILE
].count
)
6279 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6282 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6284 /* In-memory XBM file. */
6285 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6293 /* Entries for `:width', `:height' and `:data' must be present. */
6294 if (!kw
[XBM_WIDTH
].count
6295 || !kw
[XBM_HEIGHT
].count
6296 || !kw
[XBM_DATA
].count
)
6299 data
= kw
[XBM_DATA
].value
;
6300 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6301 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6303 /* Check type of data, and width and height against contents of
6309 /* Number of elements of the vector must be >= height. */
6310 if (XVECTOR (data
)->size
< height
)
6313 /* Each string or bool-vector in data must be large enough
6314 for one line of the image. */
6315 for (i
= 0; i
< height
; ++i
)
6317 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6321 if (XSTRING (elt
)->size
6322 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6325 else if (BOOL_VECTOR_P (elt
))
6327 if (XBOOL_VECTOR (elt
)->size
< width
)
6334 else if (STRINGP (data
))
6336 if (XSTRING (data
)->size
6337 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6340 else if (BOOL_VECTOR_P (data
))
6342 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6353 /* Scan a bitmap file. FP is the stream to read from. Value is
6354 either an enumerator from enum xbm_token, or a character for a
6355 single-character token, or 0 at end of file. If scanning an
6356 identifier, store the lexeme of the identifier in SVAL. If
6357 scanning a number, store its value in *IVAL. */
6360 xbm_scan (s
, end
, sval
, ival
)
6369 /* Skip white space. */
6370 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6375 else if (isdigit (c
))
6377 int value
= 0, digit
;
6379 if (c
== '0' && *s
< end
)
6382 if (c
== 'x' || c
== 'X')
6389 else if (c
>= 'a' && c
<= 'f')
6390 digit
= c
- 'a' + 10;
6391 else if (c
>= 'A' && c
<= 'F')
6392 digit
= c
- 'A' + 10;
6395 value
= 16 * value
+ digit
;
6398 else if (isdigit (c
))
6402 && (c
= *(*s
)++, isdigit (c
)))
6403 value
= 8 * value
+ c
- '0';
6410 && (c
= *(*s
)++, isdigit (c
)))
6411 value
= 10 * value
+ c
- '0';
6419 else if (isalpha (c
) || c
== '_')
6423 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6430 else if (c
== '/' && **s
== '*')
6432 /* C-style comment. */
6434 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
6447 /* Replacement for XReadBitmapFileData which isn't available under old
6448 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6449 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6450 the image. Return in *DATA the bitmap data allocated with xmalloc.
6451 Value is non-zero if successful. DATA null means just test if
6452 CONTENTS looks like an in-memory XBM file. */
6455 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6456 char *contents
, *end
;
6457 int *width
, *height
;
6458 unsigned char **data
;
6461 char buffer
[BUFSIZ
];
6464 int bytes_per_line
, i
, nbytes
;
6470 LA1 = xbm_scan (&s, end, buffer, &value)
6472 #define expect(TOKEN) \
6473 if (LA1 != (TOKEN)) \
6478 #define expect_ident(IDENT) \
6479 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6484 *width
= *height
= -1;
6487 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6489 /* Parse defines for width, height and hot-spots. */
6493 expect_ident ("define");
6494 expect (XBM_TK_IDENT
);
6496 if (LA1
== XBM_TK_NUMBER
);
6498 char *p
= strrchr (buffer
, '_');
6499 p
= p
? p
+ 1 : buffer
;
6500 if (strcmp (p
, "width") == 0)
6502 else if (strcmp (p
, "height") == 0)
6505 expect (XBM_TK_NUMBER
);
6508 if (*width
< 0 || *height
< 0)
6510 else if (data
== NULL
)
6513 /* Parse bits. Must start with `static'. */
6514 expect_ident ("static");
6515 if (LA1
== XBM_TK_IDENT
)
6517 if (strcmp (buffer
, "unsigned") == 0)
6520 expect_ident ("char");
6522 else if (strcmp (buffer
, "short") == 0)
6526 if (*width
% 16 && *width
% 16 < 9)
6529 else if (strcmp (buffer
, "char") == 0)
6537 expect (XBM_TK_IDENT
);
6543 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6544 nbytes
= bytes_per_line
* *height
;
6545 p
= *data
= (char *) xmalloc (nbytes
);
6549 for (i
= 0; i
< nbytes
; i
+= 2)
6552 expect (XBM_TK_NUMBER
);
6555 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6558 if (LA1
== ',' || LA1
== '}')
6566 for (i
= 0; i
< nbytes
; ++i
)
6569 expect (XBM_TK_NUMBER
);
6573 if (LA1
== ',' || LA1
== '}')
6598 /* Load XBM image IMG which will be displayed on frame F from buffer
6599 CONTENTS. END is the end of the buffer. Value is non-zero if
6603 xbm_load_image (f
, img
, contents
, end
)
6606 char *contents
, *end
;
6609 unsigned char *data
;
6612 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
6615 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6616 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6617 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6620 xassert (img
->width
> 0 && img
->height
> 0);
6622 /* Get foreground and background colors, maybe allocate colors. */
6623 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6625 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6627 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6629 background
= x_alloc_image_color (f
, img
, value
, background
);
6632 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6635 img
->width
, img
->height
,
6636 foreground
, background
,
6640 if (img
->pixmap
== None
)
6642 x_clear_image (f
, img
);
6643 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
6649 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6655 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6662 return (STRINGP (data
)
6663 && xbm_read_bitmap_data (XSTRING (data
)->data
,
6664 (XSTRING (data
)->data
6665 + STRING_BYTES (XSTRING (data
))),
6670 /* Fill image IMG which is used on frame F with pixmap data. Value is
6671 non-zero if successful. */
6679 Lisp_Object file_name
;
6681 xassert (xbm_image_p (img
->spec
));
6683 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6684 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6685 if (STRINGP (file_name
))
6690 struct gcpro gcpro1
;
6692 file
= x_find_image_file (file_name
);
6694 if (!STRINGP (file
))
6696 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
6701 contents
= slurp_file (XSTRING (file
)->data
, &size
);
6702 if (contents
== NULL
)
6704 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6709 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
6714 struct image_keyword fmt
[XBM_LAST
];
6716 unsigned char *bitmap_data
;
6718 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6719 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6721 int parsed_p
, height
, width
;
6722 int in_memory_file_p
= 0;
6724 /* See if data looks like an in-memory XBM file. */
6725 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6726 in_memory_file_p
= xbm_file_p (data
);
6728 /* Parse the image specification. */
6729 bcopy (xbm_format
, fmt
, sizeof fmt
);
6730 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6733 /* Get specified width, and height. */
6734 if (!in_memory_file_p
)
6736 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6737 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6738 xassert (img
->width
> 0 && img
->height
> 0);
6741 /* Get foreground and background colors, maybe allocate colors. */
6742 if (fmt
[XBM_FOREGROUND
].count
)
6743 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6745 if (fmt
[XBM_BACKGROUND
].count
)
6746 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6749 if (in_memory_file_p
)
6750 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
6751 (XSTRING (data
)->data
6752 + STRING_BYTES (XSTRING (data
))));
6759 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6761 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6762 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6764 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6766 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6768 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6771 else if (STRINGP (data
))
6772 bits
= XSTRING (data
)->data
;
6774 bits
= XBOOL_VECTOR (data
)->data
;
6776 /* Create the pixmap. */
6777 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6779 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6782 img
->width
, img
->height
,
6783 foreground
, background
,
6789 image_error ("Unable to create pixmap for XBM image `%s'",
6791 x_clear_image (f
, img
);
6801 /***********************************************************************
6803 ***********************************************************************/
6807 static int xpm_image_p
P_ ((Lisp_Object object
));
6808 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6809 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6811 #include "X11/xpm.h"
6813 /* The symbol `xpm' identifying XPM-format images. */
6817 /* Indices of image specification fields in xpm_format, below. */
6819 enum xpm_keyword_index
6834 /* Vector of image_keyword structures describing the format
6835 of valid XPM image specifications. */
6837 static struct image_keyword xpm_format
[XPM_LAST
] =
6839 {":type", IMAGE_SYMBOL_VALUE
, 1},
6840 {":file", IMAGE_STRING_VALUE
, 0},
6841 {":data", IMAGE_STRING_VALUE
, 0},
6842 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6843 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6844 {":relief", IMAGE_INTEGER_VALUE
, 0},
6845 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6846 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6847 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6848 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6851 /* Structure describing the image type XBM. */
6853 static struct image_type xpm_type
=
6863 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6864 functions for allocating image colors. Our own functions handle
6865 color allocation failures more gracefully than the ones on the XPM
6868 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6869 #define ALLOC_XPM_COLORS
6872 #ifdef ALLOC_XPM_COLORS
6874 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
6875 static void xpm_free_color_cache
P_ ((void));
6876 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
6877 static int xpm_color_bucket
P_ ((char *));
6878 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
6881 /* An entry in a hash table used to cache color definitions of named
6882 colors. This cache is necessary to speed up XPM image loading in
6883 case we do color allocations ourselves. Without it, we would need
6884 a call to XParseColor per pixel in the image. */
6886 struct xpm_cached_color
6888 /* Next in collision chain. */
6889 struct xpm_cached_color
*next
;
6891 /* Color definition (RGB and pixel color). */
6898 /* The hash table used for the color cache, and its bucket vector
6901 #define XPM_COLOR_CACHE_BUCKETS 1001
6902 struct xpm_cached_color
**xpm_color_cache
;
6904 /* Initialize the color cache. */
6907 xpm_init_color_cache (f
, attrs
)
6909 XpmAttributes
*attrs
;
6911 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
6912 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
6913 memset (xpm_color_cache
, 0, nbytes
);
6914 init_color_table ();
6916 if (attrs
->valuemask
& XpmColorSymbols
)
6921 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
6922 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
6923 attrs
->colorsymbols
[i
].value
, &color
))
6925 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
6927 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
6933 /* Free the color cache. */
6936 xpm_free_color_cache ()
6938 struct xpm_cached_color
*p
, *next
;
6941 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
6942 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
6948 xfree (xpm_color_cache
);
6949 xpm_color_cache
= NULL
;
6950 free_color_table ();
6954 /* Return the bucket index for color named COLOR_NAME in the color
6958 xpm_color_bucket (color_name
)
6964 for (s
= color_name
; *s
; ++s
)
6966 return h
%= XPM_COLOR_CACHE_BUCKETS
;
6970 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6971 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6974 static struct xpm_cached_color
*
6975 xpm_cache_color (f
, color_name
, color
, bucket
)
6982 struct xpm_cached_color
*p
;
6985 bucket
= xpm_color_bucket (color_name
);
6987 nbytes
= sizeof *p
+ strlen (color_name
);
6988 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
6989 strcpy (p
->name
, color_name
);
6991 p
->next
= xpm_color_cache
[bucket
];
6992 xpm_color_cache
[bucket
] = p
;
6997 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6998 return the cached definition in *COLOR. Otherwise, make a new
6999 entry in the cache and allocate the color. Value is zero if color
7000 allocation failed. */
7003 xpm_lookup_color (f
, color_name
, color
)
7008 struct xpm_cached_color
*p
;
7009 int h
= xpm_color_bucket (color_name
);
7011 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
7012 if (strcmp (p
->name
, color_name
) == 0)
7017 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7020 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
7022 p
= xpm_cache_color (f
, color_name
, color
, h
);
7029 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7030 CLOSURE is a pointer to the frame on which we allocate the
7031 color. Return in *COLOR the allocated color. Value is non-zero
7035 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
7042 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
7046 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7047 is a pointer to the frame on which we allocate the color. Value is
7048 non-zero if successful. */
7051 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
7061 #endif /* ALLOC_XPM_COLORS */
7064 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7065 for XPM images. Such a list must consist of conses whose car and
7069 xpm_valid_color_symbols_p (color_symbols
)
7070 Lisp_Object color_symbols
;
7072 while (CONSP (color_symbols
))
7074 Lisp_Object sym
= XCAR (color_symbols
);
7076 || !STRINGP (XCAR (sym
))
7077 || !STRINGP (XCDR (sym
)))
7079 color_symbols
= XCDR (color_symbols
);
7082 return NILP (color_symbols
);
7086 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7089 xpm_image_p (object
)
7092 struct image_keyword fmt
[XPM_LAST
];
7093 bcopy (xpm_format
, fmt
, sizeof fmt
);
7094 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7095 /* Either `:file' or `:data' must be present. */
7096 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7097 /* Either no `:color-symbols' or it's a list of conses
7098 whose car and cdr are strings. */
7099 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7100 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
7104 /* Load image IMG which will be displayed on frame F. Value is
7105 non-zero if successful. */
7113 XpmAttributes attrs
;
7114 Lisp_Object specified_file
, color_symbols
;
7116 /* Configure the XPM lib. Use the visual of frame F. Allocate
7117 close colors. Return colors allocated. */
7118 bzero (&attrs
, sizeof attrs
);
7119 attrs
.visual
= FRAME_X_VISUAL (f
);
7120 attrs
.colormap
= FRAME_X_COLORMAP (f
);
7121 attrs
.valuemask
|= XpmVisual
;
7122 attrs
.valuemask
|= XpmColormap
;
7124 #ifdef ALLOC_XPM_COLORS
7125 /* Allocate colors with our own functions which handle
7126 failing color allocation more gracefully. */
7127 attrs
.color_closure
= f
;
7128 attrs
.alloc_color
= xpm_alloc_color
;
7129 attrs
.free_colors
= xpm_free_colors
;
7130 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
7131 #else /* not ALLOC_XPM_COLORS */
7132 /* Let the XPM lib allocate colors. */
7133 attrs
.valuemask
|= XpmReturnAllocPixels
;
7134 #ifdef XpmAllocCloseColors
7135 attrs
.alloc_close_colors
= 1;
7136 attrs
.valuemask
|= XpmAllocCloseColors
;
7137 #else /* not XpmAllocCloseColors */
7138 attrs
.closeness
= 600;
7139 attrs
.valuemask
|= XpmCloseness
;
7140 #endif /* not XpmAllocCloseColors */
7141 #endif /* ALLOC_XPM_COLORS */
7143 /* If image specification contains symbolic color definitions, add
7144 these to `attrs'. */
7145 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7146 if (CONSP (color_symbols
))
7149 XpmColorSymbol
*xpm_syms
;
7152 attrs
.valuemask
|= XpmColorSymbols
;
7154 /* Count number of symbols. */
7155 attrs
.numsymbols
= 0;
7156 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7159 /* Allocate an XpmColorSymbol array. */
7160 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7161 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7162 bzero (xpm_syms
, size
);
7163 attrs
.colorsymbols
= xpm_syms
;
7165 /* Fill the color symbol array. */
7166 for (tail
= color_symbols
, i
= 0;
7168 ++i
, tail
= XCDR (tail
))
7170 Lisp_Object name
= XCAR (XCAR (tail
));
7171 Lisp_Object color
= XCDR (XCAR (tail
));
7172 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7173 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7174 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7175 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7179 /* Create a pixmap for the image, either from a file, or from a
7180 string buffer containing data in the same format as an XPM file. */
7181 #ifdef ALLOC_XPM_COLORS
7182 xpm_init_color_cache (f
, &attrs
);
7185 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7186 if (STRINGP (specified_file
))
7188 Lisp_Object file
= x_find_image_file (specified_file
);
7189 if (!STRINGP (file
))
7191 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7195 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7196 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7201 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7202 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7203 XSTRING (buffer
)->data
,
7204 &img
->pixmap
, &img
->mask
,
7208 if (rc
== XpmSuccess
)
7210 #ifdef ALLOC_XPM_COLORS
7211 img
->colors
= colors_in_color_table (&img
->ncolors
);
7212 #else /* not ALLOC_XPM_COLORS */
7213 img
->ncolors
= attrs
.nalloc_pixels
;
7214 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7215 * sizeof *img
->colors
);
7216 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7218 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7219 #ifdef DEBUG_X_COLORS
7220 register_color (img
->colors
[i
]);
7223 #endif /* not ALLOC_XPM_COLORS */
7225 img
->width
= attrs
.width
;
7226 img
->height
= attrs
.height
;
7227 xassert (img
->width
> 0 && img
->height
> 0);
7229 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7230 XpmFreeAttributes (&attrs
);
7237 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7240 case XpmFileInvalid
:
7241 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7245 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7248 case XpmColorFailed
:
7249 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7253 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7258 #ifdef ALLOC_XPM_COLORS
7259 xpm_free_color_cache ();
7261 return rc
== XpmSuccess
;
7264 #endif /* HAVE_XPM != 0 */
7267 /***********************************************************************
7269 ***********************************************************************/
7271 /* An entry in the color table mapping an RGB color to a pixel color. */
7276 unsigned long pixel
;
7278 /* Next in color table collision list. */
7279 struct ct_color
*next
;
7282 /* The bucket vector size to use. Must be prime. */
7286 /* Value is a hash of the RGB color given by R, G, and B. */
7288 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7290 /* The color hash table. */
7292 struct ct_color
**ct_table
;
7294 /* Number of entries in the color table. */
7296 int ct_colors_allocated
;
7298 /* Initialize the color table. */
7303 int size
= CT_SIZE
* sizeof (*ct_table
);
7304 ct_table
= (struct ct_color
**) xmalloc (size
);
7305 bzero (ct_table
, size
);
7306 ct_colors_allocated
= 0;
7310 /* Free memory associated with the color table. */
7316 struct ct_color
*p
, *next
;
7318 for (i
= 0; i
< CT_SIZE
; ++i
)
7319 for (p
= ct_table
[i
]; p
; p
= next
)
7330 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7331 entry for that color already is in the color table, return the
7332 pixel color of that entry. Otherwise, allocate a new color for R,
7333 G, B, and make an entry in the color table. */
7335 static unsigned long
7336 lookup_rgb_color (f
, r
, g
, b
)
7340 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7341 int i
= hash
% CT_SIZE
;
7344 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7345 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7358 cmap
= FRAME_X_COLORMAP (f
);
7359 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7363 ++ct_colors_allocated
;
7365 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7369 p
->pixel
= color
.pixel
;
7370 p
->next
= ct_table
[i
];
7374 return FRAME_FOREGROUND_PIXEL (f
);
7381 /* Look up pixel color PIXEL which is used on frame F in the color
7382 table. If not already present, allocate it. Value is PIXEL. */
7384 static unsigned long
7385 lookup_pixel_color (f
, pixel
)
7387 unsigned long pixel
;
7389 int i
= pixel
% CT_SIZE
;
7392 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7393 if (p
->pixel
== pixel
)
7402 cmap
= FRAME_X_COLORMAP (f
);
7403 color
.pixel
= pixel
;
7404 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7405 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7409 ++ct_colors_allocated
;
7411 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7416 p
->next
= ct_table
[i
];
7420 return FRAME_FOREGROUND_PIXEL (f
);
7427 /* Value is a vector of all pixel colors contained in the color table,
7428 allocated via xmalloc. Set *N to the number of colors. */
7430 static unsigned long *
7431 colors_in_color_table (n
)
7436 unsigned long *colors
;
7438 if (ct_colors_allocated
== 0)
7445 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7447 *n
= ct_colors_allocated
;
7449 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7450 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7451 colors
[j
++] = p
->pixel
;
7459 /***********************************************************************
7461 ***********************************************************************/
7463 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7464 int, XImage
*, int));
7465 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7466 XColor
*, int, XImage
*, int));
7467 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
7468 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
7469 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
7471 /* Non-zero means draw a cross on images having `:algorithm
7474 int cross_disabled_images
;
7476 /* Edge detection matrices for different edge-detection
7479 static int emboss_matrix
[9] = {
7481 2, -1, 0, /* y - 1 */
7483 0, 1, -2 /* y + 1 */
7486 static int laplace_matrix
[9] = {
7488 1, 0, 0, /* y - 1 */
7490 0, 0, -1 /* y + 1 */
7493 /* Value is the intensity of the color whose red/green/blue values
7496 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7499 /* On frame F, return an array of XColor structures describing image
7500 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7501 non-zero means also fill the red/green/blue members of the XColor
7502 structures. Value is a pointer to the array of XColors structures,
7503 allocated with xmalloc; it must be freed by the caller. */
7506 x_to_xcolors (f
, img
, rgb_p
)
7515 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
7517 /* Get the X image IMG->pixmap. */
7518 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7519 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7521 /* Fill the `pixel' members of the XColor array. I wished there
7522 were an easy and portable way to circumvent XGetPixel. */
7524 for (y
= 0; y
< img
->height
; ++y
)
7528 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7529 p
->pixel
= XGetPixel (ximg
, x
, y
);
7532 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
7536 XDestroyImage (ximg
);
7541 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7542 RGB members are set. F is the frame on which this all happens.
7543 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7546 x_from_xcolors (f
, img
, colors
)
7556 init_color_table ();
7558 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7561 for (y
= 0; y
< img
->height
; ++y
)
7562 for (x
= 0; x
< img
->width
; ++x
, ++p
)
7564 unsigned long pixel
;
7565 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
7566 XPutPixel (oimg
, x
, y
, pixel
);
7570 x_clear_image_1 (f
, img
, 1, 0, 1);
7572 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7573 x_destroy_x_image (oimg
);
7574 img
->pixmap
= pixmap
;
7575 img
->colors
= colors_in_color_table (&img
->ncolors
);
7576 free_color_table ();
7580 /* On frame F, perform edge-detection on image IMG.
7582 MATRIX is a nine-element array specifying the transformation
7583 matrix. See emboss_matrix for an example.
7585 COLOR_ADJUST is a color adjustment added to each pixel of the
7589 x_detect_edges (f
, img
, matrix
, color_adjust
)
7592 int matrix
[9], color_adjust
;
7594 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7598 for (i
= sum
= 0; i
< 9; ++i
)
7599 sum
+= abs (matrix
[i
]);
7601 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7603 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
7605 for (y
= 0; y
< img
->height
; ++y
)
7607 p
= COLOR (new, 0, y
);
7608 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7609 p
= COLOR (new, img
->width
- 1, y
);
7610 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7613 for (x
= 1; x
< img
->width
- 1; ++x
)
7615 p
= COLOR (new, x
, 0);
7616 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7617 p
= COLOR (new, x
, img
->height
- 1);
7618 p
->red
= p
->green
= p
->blue
= 0xffff/2;
7621 for (y
= 1; y
< img
->height
- 1; ++y
)
7623 p
= COLOR (new, 1, y
);
7625 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
7627 int r
, g
, b
, y1
, x1
;
7630 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
7631 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
7634 XColor
*t
= COLOR (colors
, x1
, y1
);
7635 r
+= matrix
[i
] * t
->red
;
7636 g
+= matrix
[i
] * t
->green
;
7637 b
+= matrix
[i
] * t
->blue
;
7640 r
= (r
/ sum
+ color_adjust
) & 0xffff;
7641 g
= (g
/ sum
+ color_adjust
) & 0xffff;
7642 b
= (b
/ sum
+ color_adjust
) & 0xffff;
7643 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
7648 x_from_xcolors (f
, img
, new);
7654 /* Perform the pre-defined `emboss' edge-detection on image IMG
7662 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
7666 /* Perform the pre-defined `laplace' edge-detection on image IMG
7674 x_detect_edges (f
, img
, laplace_matrix
, 45000);
7678 /* Perform edge-detection on image IMG on frame F, with specified
7679 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7681 MATRIX must be either
7683 - a list of at least 9 numbers in row-major form
7684 - a vector of at least 9 numbers
7686 COLOR_ADJUST nil means use a default; otherwise it must be a
7690 x_edge_detection (f
, img
, matrix
, color_adjust
)
7693 Lisp_Object matrix
, color_adjust
;
7701 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
7702 ++i
, matrix
= XCDR (matrix
))
7703 trans
[i
] = XFLOATINT (XCAR (matrix
));
7705 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
7707 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
7708 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
7711 if (NILP (color_adjust
))
7712 color_adjust
= make_number (0xffff / 2);
7714 if (i
== 9 && NUMBERP (color_adjust
))
7715 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
7719 /* Transform image IMG on frame F so that it looks disabled. */
7722 x_disable_image (f
, img
)
7726 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7728 if (dpyinfo
->n_planes
>= 2)
7730 /* Color (or grayscale). Convert to gray, and equalize. Just
7731 drawing such images with a stipple can look very odd, so
7732 we're using this method instead. */
7733 XColor
*colors
= x_to_xcolors (f
, img
, 1);
7735 const int h
= 15000;
7736 const int l
= 30000;
7738 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
7742 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
7743 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
7744 p
->red
= p
->green
= p
->blue
= i2
;
7747 x_from_xcolors (f
, img
, colors
);
7750 /* Draw a cross over the disabled image, if we must or if we
7752 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
7754 Display
*dpy
= FRAME_X_DISPLAY (f
);
7757 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
7758 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
7759 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
7760 img
->width
- 1, img
->height
- 1);
7761 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
7767 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
7768 XSetForeground (dpy
, gc
, WHITE_PIX_DEFAULT (f
));
7769 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
7770 img
->width
- 1, img
->height
- 1);
7771 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
7779 /* Build a mask for image IMG which is used on frame F. FILE is the
7780 name of an image file, for error messages. HOW determines how to
7781 determine the background color of IMG. If it is a list '(R G B)',
7782 with R, G, and B being integers >= 0, take that as the color of the
7783 background. Otherwise, determine the background color of IMG
7784 heuristically. Value is non-zero if successful. */
7787 x_build_heuristic_mask (f
, img
, how
)
7792 Display
*dpy
= FRAME_X_DISPLAY (f
);
7793 XImage
*ximg
, *mask_img
;
7794 int x
, y
, rc
, look_at_corners_p
;
7795 unsigned long bg
= 0;
7799 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
7803 /* Create an image and pixmap serving as mask. */
7804 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
7805 &mask_img
, &img
->mask
);
7809 /* Get the X image of IMG->pixmap. */
7810 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7813 /* Determine the background color of ximg. If HOW is `(R G B)'
7814 take that as color. Otherwise, try to determine the color
7816 look_at_corners_p
= 1;
7824 && NATNUMP (XCAR (how
)))
7826 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
7830 if (i
== 3 && NILP (how
))
7832 char color_name
[30];
7833 XColor exact
, color
;
7836 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
7838 cmap
= FRAME_X_COLORMAP (f
);
7839 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
7842 look_at_corners_p
= 0;
7847 if (look_at_corners_p
)
7849 unsigned long corners
[4];
7852 /* Get the colors at the corners of ximg. */
7853 corners
[0] = XGetPixel (ximg
, 0, 0);
7854 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7855 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7856 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7858 /* Choose the most frequently found color as background. */
7859 for (i
= best_count
= 0; i
< 4; ++i
)
7863 for (j
= n
= 0; j
< 4; ++j
)
7864 if (corners
[i
] == corners
[j
])
7868 bg
= corners
[i
], best_count
= n
;
7872 /* Set all bits in mask_img to 1 whose color in ximg is different
7873 from the background color bg. */
7874 for (y
= 0; y
< img
->height
; ++y
)
7875 for (x
= 0; x
< img
->width
; ++x
)
7876 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7878 /* Put mask_img into img->mask. */
7879 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7880 x_destroy_x_image (mask_img
);
7881 XDestroyImage (ximg
);
7888 /***********************************************************************
7889 PBM (mono, gray, color)
7890 ***********************************************************************/
7892 static int pbm_image_p
P_ ((Lisp_Object object
));
7893 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7894 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
7896 /* The symbol `pbm' identifying images of this type. */
7900 /* Indices of image specification fields in gs_format, below. */
7902 enum pbm_keyword_index
7916 /* Vector of image_keyword structures describing the format
7917 of valid user-defined image specifications. */
7919 static struct image_keyword pbm_format
[PBM_LAST
] =
7921 {":type", IMAGE_SYMBOL_VALUE
, 1},
7922 {":file", IMAGE_STRING_VALUE
, 0},
7923 {":data", IMAGE_STRING_VALUE
, 0},
7924 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7925 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7926 {":relief", IMAGE_INTEGER_VALUE
, 0},
7927 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7928 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7929 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7932 /* Structure describing the image type `pbm'. */
7934 static struct image_type pbm_type
=
7944 /* Return non-zero if OBJECT is a valid PBM image specification. */
7947 pbm_image_p (object
)
7950 struct image_keyword fmt
[PBM_LAST
];
7952 bcopy (pbm_format
, fmt
, sizeof fmt
);
7954 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
7957 /* Must specify either :data or :file. */
7958 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
7962 /* Scan a decimal number from *S and return it. Advance *S while
7963 reading the number. END is the end of the string. Value is -1 at
7967 pbm_scan_number (s
, end
)
7968 unsigned char **s
, *end
;
7970 int c
= 0, val
= -1;
7974 /* Skip white-space. */
7975 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
7980 /* Skip comment to end of line. */
7981 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
7984 else if (isdigit (c
))
7986 /* Read decimal number. */
7988 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
7989 val
= 10 * val
+ c
- '0';
8000 /* Load PBM image IMG for use on frame F. */
8008 int width
, height
, max_color_idx
= 0;
8010 Lisp_Object file
, specified_file
;
8011 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
8012 struct gcpro gcpro1
;
8013 unsigned char *contents
= NULL
;
8014 unsigned char *end
, *p
;
8017 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8021 if (STRINGP (specified_file
))
8023 file
= x_find_image_file (specified_file
);
8024 if (!STRINGP (file
))
8026 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8031 contents
= slurp_file (XSTRING (file
)->data
, &size
);
8032 if (contents
== NULL
)
8034 image_error ("Error reading `%s'", file
, Qnil
);
8040 end
= contents
+ size
;
8045 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8046 p
= XSTRING (data
)->data
;
8047 end
= p
+ STRING_BYTES (XSTRING (data
));
8050 /* Check magic number. */
8051 if (end
- p
< 2 || *p
++ != 'P')
8053 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8063 raw_p
= 0, type
= PBM_MONO
;
8067 raw_p
= 0, type
= PBM_GRAY
;
8071 raw_p
= 0, type
= PBM_COLOR
;
8075 raw_p
= 1, type
= PBM_MONO
;
8079 raw_p
= 1, type
= PBM_GRAY
;
8083 raw_p
= 1, type
= PBM_COLOR
;
8087 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8091 /* Read width, height, maximum color-component. Characters
8092 starting with `#' up to the end of a line are ignored. */
8093 width
= pbm_scan_number (&p
, end
);
8094 height
= pbm_scan_number (&p
, end
);
8096 if (type
!= PBM_MONO
)
8098 max_color_idx
= pbm_scan_number (&p
, end
);
8099 if (raw_p
&& max_color_idx
> 255)
8100 max_color_idx
= 255;
8105 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8108 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8109 &ximg
, &img
->pixmap
))
8112 /* Initialize the color hash table. */
8113 init_color_table ();
8115 if (type
== PBM_MONO
)
8119 for (y
= 0; y
< height
; ++y
)
8120 for (x
= 0; x
< width
; ++x
)
8130 g
= pbm_scan_number (&p
, end
);
8132 XPutPixel (ximg
, x
, y
, (g
8133 ? FRAME_FOREGROUND_PIXEL (f
)
8134 : FRAME_BACKGROUND_PIXEL (f
)));
8139 for (y
= 0; y
< height
; ++y
)
8140 for (x
= 0; x
< width
; ++x
)
8144 if (type
== PBM_GRAY
)
8145 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8154 r
= pbm_scan_number (&p
, end
);
8155 g
= pbm_scan_number (&p
, end
);
8156 b
= pbm_scan_number (&p
, end
);
8159 if (r
< 0 || g
< 0 || b
< 0)
8163 XDestroyImage (ximg
);
8164 image_error ("Invalid pixel value in image `%s'",
8169 /* RGB values are now in the range 0..max_color_idx.
8170 Scale this to the range 0..0xffff supported by X. */
8171 r
= (double) r
* 65535 / max_color_idx
;
8172 g
= (double) g
* 65535 / max_color_idx
;
8173 b
= (double) b
* 65535 / max_color_idx
;
8174 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8178 /* Store in IMG->colors the colors allocated for the image, and
8179 free the color table. */
8180 img
->colors
= colors_in_color_table (&img
->ncolors
);
8181 free_color_table ();
8183 /* Put the image into a pixmap. */
8184 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8185 x_destroy_x_image (ximg
);
8188 img
->height
= height
;
8197 /***********************************************************************
8199 ***********************************************************************/
8205 /* Function prototypes. */
8207 static int png_image_p
P_ ((Lisp_Object object
));
8208 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8210 /* The symbol `png' identifying images of this type. */
8214 /* Indices of image specification fields in png_format, below. */
8216 enum png_keyword_index
8230 /* Vector of image_keyword structures describing the format
8231 of valid user-defined image specifications. */
8233 static struct image_keyword png_format
[PNG_LAST
] =
8235 {":type", IMAGE_SYMBOL_VALUE
, 1},
8236 {":data", IMAGE_STRING_VALUE
, 0},
8237 {":file", IMAGE_STRING_VALUE
, 0},
8238 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8239 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8240 {":relief", IMAGE_INTEGER_VALUE
, 0},
8241 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8242 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8243 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8246 /* Structure describing the image type `png'. */
8248 static struct image_type png_type
=
8258 /* Return non-zero if OBJECT is a valid PNG image specification. */
8261 png_image_p (object
)
8264 struct image_keyword fmt
[PNG_LAST
];
8265 bcopy (png_format
, fmt
, sizeof fmt
);
8267 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
8270 /* Must specify either the :data or :file keyword. */
8271 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8275 /* Error and warning handlers installed when the PNG library
8279 my_png_error (png_ptr
, msg
)
8280 png_struct
*png_ptr
;
8283 xassert (png_ptr
!= NULL
);
8284 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8285 longjmp (png_ptr
->jmpbuf
, 1);
8290 my_png_warning (png_ptr
, msg
)
8291 png_struct
*png_ptr
;
8294 xassert (png_ptr
!= NULL
);
8295 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8298 /* Memory source for PNG decoding. */
8300 struct png_memory_storage
8302 unsigned char *bytes
; /* The data */
8303 size_t len
; /* How big is it? */
8304 int index
; /* Where are we? */
8308 /* Function set as reader function when reading PNG image from memory.
8309 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8310 bytes from the input to DATA. */
8313 png_read_from_memory (png_ptr
, data
, length
)
8314 png_structp png_ptr
;
8318 struct png_memory_storage
*tbr
8319 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8321 if (length
> tbr
->len
- tbr
->index
)
8322 png_error (png_ptr
, "Read error");
8324 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8325 tbr
->index
= tbr
->index
+ length
;
8328 /* Load PNG image IMG for use on frame F. Value is non-zero if
8336 Lisp_Object file
, specified_file
;
8337 Lisp_Object specified_data
;
8339 XImage
*ximg
, *mask_img
= NULL
;
8340 struct gcpro gcpro1
;
8341 png_struct
*png_ptr
= NULL
;
8342 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8343 FILE *volatile fp
= NULL
;
8345 png_byte
* volatile pixels
= NULL
;
8346 png_byte
** volatile rows
= NULL
;
8347 png_uint_32 width
, height
;
8348 int bit_depth
, color_type
, interlace_type
;
8350 png_uint_32 row_bytes
;
8353 double screen_gamma
, image_gamma
;
8355 struct png_memory_storage tbr
; /* Data to be read */
8357 /* Find out what file to load. */
8358 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8359 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8363 if (NILP (specified_data
))
8365 file
= x_find_image_file (specified_file
);
8366 if (!STRINGP (file
))
8368 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8373 /* Open the image file. */
8374 fp
= fopen (XSTRING (file
)->data
, "rb");
8377 image_error ("Cannot open image file `%s'", file
, Qnil
);
8383 /* Check PNG signature. */
8384 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8385 || !png_check_sig (sig
, sizeof sig
))
8387 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8395 /* Read from memory. */
8396 tbr
.bytes
= XSTRING (specified_data
)->data
;
8397 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8400 /* Check PNG signature. */
8401 if (tbr
.len
< sizeof sig
8402 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8404 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8409 /* Need to skip past the signature. */
8410 tbr
.bytes
+= sizeof (sig
);
8413 /* Initialize read and info structs for PNG lib. */
8414 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8415 my_png_error
, my_png_warning
);
8418 if (fp
) fclose (fp
);
8423 info_ptr
= png_create_info_struct (png_ptr
);
8426 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8427 if (fp
) fclose (fp
);
8432 end_info
= png_create_info_struct (png_ptr
);
8435 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8436 if (fp
) fclose (fp
);
8441 /* Set error jump-back. We come back here when the PNG library
8442 detects an error. */
8443 if (setjmp (png_ptr
->jmpbuf
))
8447 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8450 if (fp
) fclose (fp
);
8455 /* Read image info. */
8456 if (!NILP (specified_data
))
8457 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8459 png_init_io (png_ptr
, fp
);
8461 png_set_sig_bytes (png_ptr
, sizeof sig
);
8462 png_read_info (png_ptr
, info_ptr
);
8463 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8464 &interlace_type
, NULL
, NULL
);
8466 /* If image contains simply transparency data, we prefer to
8467 construct a clipping mask. */
8468 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8473 /* This function is easier to write if we only have to handle
8474 one data format: RGB or RGBA with 8 bits per channel. Let's
8475 transform other formats into that format. */
8477 /* Strip more than 8 bits per channel. */
8478 if (bit_depth
== 16)
8479 png_set_strip_16 (png_ptr
);
8481 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8483 png_set_expand (png_ptr
);
8485 /* Convert grayscale images to RGB. */
8486 if (color_type
== PNG_COLOR_TYPE_GRAY
8487 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8488 png_set_gray_to_rgb (png_ptr
);
8490 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8491 gamma_str
= getenv ("SCREEN_GAMMA");
8492 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8494 /* Tell the PNG lib to handle gamma correction for us. */
8496 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8497 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8498 /* There is a special chunk in the image specifying the gamma. */
8499 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8502 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8503 /* Image contains gamma information. */
8504 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8506 /* Use a default of 0.5 for the image gamma. */
8507 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8509 /* Handle alpha channel by combining the image with a background
8510 color. Do this only if a real alpha channel is supplied. For
8511 simple transparency, we prefer a clipping mask. */
8514 png_color_16
*image_background
;
8516 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8517 /* Image contains a background color with which to
8518 combine the image. */
8519 png_set_background (png_ptr
, image_background
,
8520 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8523 /* Image does not contain a background color with which
8524 to combine the image data via an alpha channel. Use
8525 the frame's background instead. */
8528 png_color_16 frame_background
;
8530 cmap
= FRAME_X_COLORMAP (f
);
8531 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8532 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
8534 bzero (&frame_background
, sizeof frame_background
);
8535 frame_background
.red
= color
.red
;
8536 frame_background
.green
= color
.green
;
8537 frame_background
.blue
= color
.blue
;
8539 png_set_background (png_ptr
, &frame_background
,
8540 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8544 /* Update info structure. */
8545 png_read_update_info (png_ptr
, info_ptr
);
8547 /* Get number of channels. Valid values are 1 for grayscale images
8548 and images with a palette, 2 for grayscale images with transparency
8549 information (alpha channel), 3 for RGB images, and 4 for RGB
8550 images with alpha channel, i.e. RGBA. If conversions above were
8551 sufficient we should only have 3 or 4 channels here. */
8552 channels
= png_get_channels (png_ptr
, info_ptr
);
8553 xassert (channels
== 3 || channels
== 4);
8555 /* Number of bytes needed for one row of the image. */
8556 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8558 /* Allocate memory for the image. */
8559 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8560 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8561 for (i
= 0; i
< height
; ++i
)
8562 rows
[i
] = pixels
+ i
* row_bytes
;
8564 /* Read the entire image. */
8565 png_read_image (png_ptr
, rows
);
8566 png_read_end (png_ptr
, info_ptr
);
8573 /* Create the X image and pixmap. */
8574 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8578 /* Create an image and pixmap serving as mask if the PNG image
8579 contains an alpha channel. */
8582 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8583 &mask_img
, &img
->mask
))
8585 x_destroy_x_image (ximg
);
8586 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8591 /* Fill the X image and mask from PNG data. */
8592 init_color_table ();
8594 for (y
= 0; y
< height
; ++y
)
8596 png_byte
*p
= rows
[y
];
8598 for (x
= 0; x
< width
; ++x
)
8605 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8607 /* An alpha channel, aka mask channel, associates variable
8608 transparency with an image. Where other image formats
8609 support binary transparency---fully transparent or fully
8610 opaque---PNG allows up to 254 levels of partial transparency.
8611 The PNG library implements partial transparency by combining
8612 the image with a specified background color.
8614 I'm not sure how to handle this here nicely: because the
8615 background on which the image is displayed may change, for
8616 real alpha channel support, it would be necessary to create
8617 a new image for each possible background.
8619 What I'm doing now is that a mask is created if we have
8620 boolean transparency information. Otherwise I'm using
8621 the frame's background color to combine the image with. */
8626 XPutPixel (mask_img
, x
, y
, *p
> 0);
8632 /* Remember colors allocated for this image. */
8633 img
->colors
= colors_in_color_table (&img
->ncolors
);
8634 free_color_table ();
8637 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8642 img
->height
= height
;
8644 /* Put the image into the pixmap, then free the X image and its buffer. */
8645 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8646 x_destroy_x_image (ximg
);
8648 /* Same for the mask. */
8651 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8652 x_destroy_x_image (mask_img
);
8659 #endif /* HAVE_PNG != 0 */
8663 /***********************************************************************
8665 ***********************************************************************/
8669 /* Work around a warning about HAVE_STDLIB_H being redefined in
8671 #ifdef HAVE_STDLIB_H
8672 #define HAVE_STDLIB_H_1
8673 #undef HAVE_STDLIB_H
8674 #endif /* HAVE_STLIB_H */
8676 #include <jpeglib.h>
8680 #ifdef HAVE_STLIB_H_1
8681 #define HAVE_STDLIB_H 1
8684 static int jpeg_image_p
P_ ((Lisp_Object object
));
8685 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8687 /* The symbol `jpeg' identifying images of this type. */
8691 /* Indices of image specification fields in gs_format, below. */
8693 enum jpeg_keyword_index
8702 JPEG_HEURISTIC_MASK
,
8707 /* Vector of image_keyword structures describing the format
8708 of valid user-defined image specifications. */
8710 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8712 {":type", IMAGE_SYMBOL_VALUE
, 1},
8713 {":data", IMAGE_STRING_VALUE
, 0},
8714 {":file", IMAGE_STRING_VALUE
, 0},
8715 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8716 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8717 {":relief", IMAGE_INTEGER_VALUE
, 0},
8718 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8719 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8720 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8723 /* Structure describing the image type `jpeg'. */
8725 static struct image_type jpeg_type
=
8735 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8738 jpeg_image_p (object
)
8741 struct image_keyword fmt
[JPEG_LAST
];
8743 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8745 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
8748 /* Must specify either the :data or :file keyword. */
8749 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
8753 struct my_jpeg_error_mgr
8755 struct jpeg_error_mgr pub
;
8756 jmp_buf setjmp_buffer
;
8761 my_error_exit (cinfo
)
8764 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8765 longjmp (mgr
->setjmp_buffer
, 1);
8769 /* Init source method for JPEG data source manager. Called by
8770 jpeg_read_header() before any data is actually read. See
8771 libjpeg.doc from the JPEG lib distribution. */
8774 our_init_source (cinfo
)
8775 j_decompress_ptr cinfo
;
8780 /* Fill input buffer method for JPEG data source manager. Called
8781 whenever more data is needed. We read the whole image in one step,
8782 so this only adds a fake end of input marker at the end. */
8785 our_fill_input_buffer (cinfo
)
8786 j_decompress_ptr cinfo
;
8788 /* Insert a fake EOI marker. */
8789 struct jpeg_source_mgr
*src
= cinfo
->src
;
8790 static JOCTET buffer
[2];
8792 buffer
[0] = (JOCTET
) 0xFF;
8793 buffer
[1] = (JOCTET
) JPEG_EOI
;
8795 src
->next_input_byte
= buffer
;
8796 src
->bytes_in_buffer
= 2;
8801 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8802 is the JPEG data source manager. */
8805 our_skip_input_data (cinfo
, num_bytes
)
8806 j_decompress_ptr cinfo
;
8809 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8813 if (num_bytes
> src
->bytes_in_buffer
)
8814 ERREXIT (cinfo
, JERR_INPUT_EOF
);
8816 src
->bytes_in_buffer
-= num_bytes
;
8817 src
->next_input_byte
+= num_bytes
;
8822 /* Method to terminate data source. Called by
8823 jpeg_finish_decompress() after all data has been processed. */
8826 our_term_source (cinfo
)
8827 j_decompress_ptr cinfo
;
8832 /* Set up the JPEG lib for reading an image from DATA which contains
8833 LEN bytes. CINFO is the decompression info structure created for
8834 reading the image. */
8837 jpeg_memory_src (cinfo
, data
, len
)
8838 j_decompress_ptr cinfo
;
8842 struct jpeg_source_mgr
*src
;
8844 if (cinfo
->src
== NULL
)
8846 /* First time for this JPEG object? */
8847 cinfo
->src
= (struct jpeg_source_mgr
*)
8848 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
8849 sizeof (struct jpeg_source_mgr
));
8850 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8851 src
->next_input_byte
= data
;
8854 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8855 src
->init_source
= our_init_source
;
8856 src
->fill_input_buffer
= our_fill_input_buffer
;
8857 src
->skip_input_data
= our_skip_input_data
;
8858 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
8859 src
->term_source
= our_term_source
;
8860 src
->bytes_in_buffer
= len
;
8861 src
->next_input_byte
= data
;
8865 /* Load image IMG for use on frame F. Patterned after example.c
8866 from the JPEG lib. */
8873 struct jpeg_decompress_struct cinfo
;
8874 struct my_jpeg_error_mgr mgr
;
8875 Lisp_Object file
, specified_file
;
8876 Lisp_Object specified_data
;
8877 FILE * volatile fp
= NULL
;
8879 int row_stride
, x
, y
;
8880 XImage
*ximg
= NULL
;
8882 unsigned long *colors
;
8884 struct gcpro gcpro1
;
8886 /* Open the JPEG file. */
8887 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8888 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8892 if (NILP (specified_data
))
8894 file
= x_find_image_file (specified_file
);
8895 if (!STRINGP (file
))
8897 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8902 fp
= fopen (XSTRING (file
)->data
, "r");
8905 image_error ("Cannot open `%s'", file
, Qnil
);
8911 /* Customize libjpeg's error handling to call my_error_exit when an
8912 error is detected. This function will perform a longjmp. */
8913 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8914 mgr
.pub
.error_exit
= my_error_exit
;
8916 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8920 /* Called from my_error_exit. Display a JPEG error. */
8921 char buffer
[JMSG_LENGTH_MAX
];
8922 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8923 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
8924 build_string (buffer
));
8927 /* Close the input file and destroy the JPEG object. */
8929 fclose ((FILE *) fp
);
8930 jpeg_destroy_decompress (&cinfo
);
8932 /* If we already have an XImage, free that. */
8933 x_destroy_x_image (ximg
);
8935 /* Free pixmap and colors. */
8936 x_clear_image (f
, img
);
8942 /* Create the JPEG decompression object. Let it read from fp.
8943 Read the JPEG image header. */
8944 jpeg_create_decompress (&cinfo
);
8946 if (NILP (specified_data
))
8947 jpeg_stdio_src (&cinfo
, (FILE *) fp
);
8949 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
8950 STRING_BYTES (XSTRING (specified_data
)));
8952 jpeg_read_header (&cinfo
, TRUE
);
8954 /* Customize decompression so that color quantization will be used.
8955 Start decompression. */
8956 cinfo
.quantize_colors
= TRUE
;
8957 jpeg_start_decompress (&cinfo
);
8958 width
= img
->width
= cinfo
.output_width
;
8959 height
= img
->height
= cinfo
.output_height
;
8961 /* Create X image and pixmap. */
8962 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8963 longjmp (mgr
.setjmp_buffer
, 2);
8965 /* Allocate colors. When color quantization is used,
8966 cinfo.actual_number_of_colors has been set with the number of
8967 colors generated, and cinfo.colormap is a two-dimensional array
8968 of color indices in the range 0..cinfo.actual_number_of_colors.
8969 No more than 255 colors will be generated. */
8973 if (cinfo
.out_color_components
> 2)
8974 ir
= 0, ig
= 1, ib
= 2;
8975 else if (cinfo
.out_color_components
> 1)
8976 ir
= 0, ig
= 1, ib
= 0;
8978 ir
= 0, ig
= 0, ib
= 0;
8980 /* Use the color table mechanism because it handles colors that
8981 cannot be allocated nicely. Such colors will be replaced with
8982 a default color, and we don't have to care about which colors
8983 can be freed safely, and which can't. */
8984 init_color_table ();
8985 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8988 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8990 /* Multiply RGB values with 255 because X expects RGB values
8991 in the range 0..0xffff. */
8992 int r
= cinfo
.colormap
[ir
][i
] << 8;
8993 int g
= cinfo
.colormap
[ig
][i
] << 8;
8994 int b
= cinfo
.colormap
[ib
][i
] << 8;
8995 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8998 /* Remember those colors actually allocated. */
8999 img
->colors
= colors_in_color_table (&img
->ncolors
);
9000 free_color_table ();
9004 row_stride
= width
* cinfo
.output_components
;
9005 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9007 for (y
= 0; y
< height
; ++y
)
9009 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9010 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9011 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9015 jpeg_finish_decompress (&cinfo
);
9016 jpeg_destroy_decompress (&cinfo
);
9018 fclose ((FILE *) fp
);
9020 /* Put the image into the pixmap. */
9021 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9022 x_destroy_x_image (ximg
);
9027 #endif /* HAVE_JPEG */
9031 /***********************************************************************
9033 ***********************************************************************/
9039 static int tiff_image_p
P_ ((Lisp_Object object
));
9040 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9042 /* The symbol `tiff' identifying images of this type. */
9046 /* Indices of image specification fields in tiff_format, below. */
9048 enum tiff_keyword_index
9057 TIFF_HEURISTIC_MASK
,
9062 /* Vector of image_keyword structures describing the format
9063 of valid user-defined image specifications. */
9065 static struct image_keyword tiff_format
[TIFF_LAST
] =
9067 {":type", IMAGE_SYMBOL_VALUE
, 1},
9068 {":data", IMAGE_STRING_VALUE
, 0},
9069 {":file", IMAGE_STRING_VALUE
, 0},
9070 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9071 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9072 {":relief", IMAGE_INTEGER_VALUE
, 0},
9073 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9074 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9075 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9078 /* Structure describing the image type `tiff'. */
9080 static struct image_type tiff_type
=
9090 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9093 tiff_image_p (object
)
9096 struct image_keyword fmt
[TIFF_LAST
];
9097 bcopy (tiff_format
, fmt
, sizeof fmt
);
9099 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
9102 /* Must specify either the :data or :file keyword. */
9103 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9107 /* Reading from a memory buffer for TIFF images Based on the PNG
9108 memory source, but we have to provide a lot of extra functions.
9111 We really only need to implement read and seek, but I am not
9112 convinced that the TIFF library is smart enough not to destroy
9113 itself if we only hand it the function pointers we need to
9118 unsigned char *bytes
;
9126 tiff_read_from_memory (data
, buf
, size
)
9131 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9133 if (size
> src
->len
- src
->index
)
9135 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9142 tiff_write_from_memory (data
, buf
, size
)
9152 tiff_seek_in_memory (data
, off
, whence
)
9157 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9162 case SEEK_SET
: /* Go from beginning of source. */
9166 case SEEK_END
: /* Go from end of source. */
9167 idx
= src
->len
+ off
;
9170 case SEEK_CUR
: /* Go from current position. */
9171 idx
= src
->index
+ off
;
9174 default: /* Invalid `whence'. */
9178 if (idx
> src
->len
|| idx
< 0)
9187 tiff_close_memory (data
)
9196 tiff_mmap_memory (data
, pbase
, psize
)
9201 /* It is already _IN_ memory. */
9207 tiff_unmap_memory (data
, base
, size
)
9212 /* We don't need to do this. */
9217 tiff_size_of_memory (data
)
9220 return ((tiff_memory_source
*) data
)->len
;
9224 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9232 Lisp_Object file
, specified_file
;
9233 Lisp_Object specified_data
;
9235 int width
, height
, x
, y
;
9239 struct gcpro gcpro1
;
9240 tiff_memory_source memsrc
;
9242 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9243 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9247 if (NILP (specified_data
))
9249 /* Read from a file */
9250 file
= x_find_image_file (specified_file
);
9251 if (!STRINGP (file
))
9253 image_error ("Cannot find image file `%s'", file
, Qnil
);
9258 /* Try to open the image file. */
9259 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9262 image_error ("Cannot open `%s'", file
, Qnil
);
9269 /* Memory source! */
9270 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9271 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9274 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9275 (TIFFReadWriteProc
) tiff_read_from_memory
,
9276 (TIFFReadWriteProc
) tiff_write_from_memory
,
9277 tiff_seek_in_memory
,
9279 tiff_size_of_memory
,
9285 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9291 /* Get width and height of the image, and allocate a raster buffer
9292 of width x height 32-bit values. */
9293 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9294 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9295 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9297 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9301 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9307 /* Create the X image and pixmap. */
9308 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9315 /* Initialize the color table. */
9316 init_color_table ();
9318 /* Process the pixel raster. Origin is in the lower-left corner. */
9319 for (y
= 0; y
< height
; ++y
)
9321 uint32
*row
= buf
+ y
* width
;
9323 for (x
= 0; x
< width
; ++x
)
9325 uint32 abgr
= row
[x
];
9326 int r
= TIFFGetR (abgr
) << 8;
9327 int g
= TIFFGetG (abgr
) << 8;
9328 int b
= TIFFGetB (abgr
) << 8;
9329 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9333 /* Remember the colors allocated for the image. Free the color table. */
9334 img
->colors
= colors_in_color_table (&img
->ncolors
);
9335 free_color_table ();
9337 /* Put the image into the pixmap, then free the X image and its buffer. */
9338 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9339 x_destroy_x_image (ximg
);
9343 img
->height
= height
;
9349 #endif /* HAVE_TIFF != 0 */
9353 /***********************************************************************
9355 ***********************************************************************/
9359 #include <gif_lib.h>
9361 static int gif_image_p
P_ ((Lisp_Object object
));
9362 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9364 /* The symbol `gif' identifying images of this type. */
9368 /* Indices of image specification fields in gif_format, below. */
9370 enum gif_keyword_index
9385 /* Vector of image_keyword structures describing the format
9386 of valid user-defined image specifications. */
9388 static struct image_keyword gif_format
[GIF_LAST
] =
9390 {":type", IMAGE_SYMBOL_VALUE
, 1},
9391 {":data", IMAGE_STRING_VALUE
, 0},
9392 {":file", IMAGE_STRING_VALUE
, 0},
9393 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9394 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9395 {":relief", IMAGE_INTEGER_VALUE
, 0},
9396 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9397 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9398 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9399 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
9402 /* Structure describing the image type `gif'. */
9404 static struct image_type gif_type
=
9414 /* Return non-zero if OBJECT is a valid GIF image specification. */
9417 gif_image_p (object
)
9420 struct image_keyword fmt
[GIF_LAST
];
9421 bcopy (gif_format
, fmt
, sizeof fmt
);
9423 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
9426 /* Must specify either the :data or :file keyword. */
9427 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9431 /* Reading a GIF image from memory
9432 Based on the PNG memory stuff to a certain extent. */
9436 unsigned char *bytes
;
9443 /* Make the current memory source available to gif_read_from_memory.
9444 It's done this way because not all versions of libungif support
9445 a UserData field in the GifFileType structure. */
9446 static gif_memory_source
*current_gif_memory_src
;
9449 gif_read_from_memory (file
, buf
, len
)
9454 gif_memory_source
*src
= current_gif_memory_src
;
9456 if (len
> src
->len
- src
->index
)
9459 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9465 /* Load GIF image IMG for use on frame F. Value is non-zero if
9473 Lisp_Object file
, specified_file
;
9474 Lisp_Object specified_data
;
9475 int rc
, width
, height
, x
, y
, i
;
9477 ColorMapObject
*gif_color_map
;
9478 unsigned long pixel_colors
[256];
9480 struct gcpro gcpro1
;
9482 int ino
, image_left
, image_top
, image_width
, image_height
;
9483 gif_memory_source memsrc
;
9484 unsigned char *raster
;
9486 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9487 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9491 if (NILP (specified_data
))
9493 file
= x_find_image_file (specified_file
);
9494 if (!STRINGP (file
))
9496 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9501 /* Open the GIF file. */
9502 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9505 image_error ("Cannot open `%s'", file
, Qnil
);
9512 /* Read from memory! */
9513 current_gif_memory_src
= &memsrc
;
9514 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9515 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9518 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
9521 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
9527 /* Read entire contents. */
9528 rc
= DGifSlurp (gif
);
9529 if (rc
== GIF_ERROR
)
9531 image_error ("Error reading `%s'", img
->spec
, Qnil
);
9532 DGifCloseFile (gif
);
9537 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
9538 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
9539 if (ino
>= gif
->ImageCount
)
9541 image_error ("Invalid image number `%s' in image `%s'",
9543 DGifCloseFile (gif
);
9548 width
= img
->width
= gif
->SWidth
;
9549 height
= img
->height
= gif
->SHeight
;
9551 /* Create the X image and pixmap. */
9552 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9554 DGifCloseFile (gif
);
9559 /* Allocate colors. */
9560 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
9562 gif_color_map
= gif
->SColorMap
;
9563 init_color_table ();
9564 bzero (pixel_colors
, sizeof pixel_colors
);
9566 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9568 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9569 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9570 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9571 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9574 img
->colors
= colors_in_color_table (&img
->ncolors
);
9575 free_color_table ();
9577 /* Clear the part of the screen image that are not covered by
9578 the image from the GIF file. Full animated GIF support
9579 requires more than can be done here (see the gif89 spec,
9580 disposal methods). Let's simply assume that the part
9581 not covered by a sub-image is in the frame's background color. */
9582 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9583 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9584 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9585 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9587 for (y
= 0; y
< image_top
; ++y
)
9588 for (x
= 0; x
< width
; ++x
)
9589 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9591 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9592 for (x
= 0; x
< width
; ++x
)
9593 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9595 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9597 for (x
= 0; x
< image_left
; ++x
)
9598 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9599 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9600 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9603 /* Read the GIF image into the X image. We use a local variable
9604 `raster' here because RasterBits below is a char *, and invites
9605 problems with bytes >= 0x80. */
9606 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9608 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9610 static int interlace_start
[] = {0, 4, 2, 1};
9611 static int interlace_increment
[] = {8, 8, 4, 2};
9613 int row
= interlace_start
[0];
9617 for (y
= 0; y
< image_height
; y
++)
9619 if (row
>= image_height
)
9621 row
= interlace_start
[++pass
];
9622 while (row
>= image_height
)
9623 row
= interlace_start
[++pass
];
9626 for (x
= 0; x
< image_width
; x
++)
9628 int i
= raster
[(y
* image_width
) + x
];
9629 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9633 row
+= interlace_increment
[pass
];
9638 for (y
= 0; y
< image_height
; ++y
)
9639 for (x
= 0; x
< image_width
; ++x
)
9641 int i
= raster
[y
* image_width
+ x
];
9642 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9646 DGifCloseFile (gif
);
9648 /* Put the image into the pixmap, then free the X image and its buffer. */
9649 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9650 x_destroy_x_image (ximg
);
9656 #endif /* HAVE_GIF != 0 */
9660 /***********************************************************************
9662 ***********************************************************************/
9664 static int gs_image_p
P_ ((Lisp_Object object
));
9665 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9666 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9668 /* The symbol `postscript' identifying images of this type. */
9670 Lisp_Object Qpostscript
;
9672 /* Keyword symbols. */
9674 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9676 /* Indices of image specification fields in gs_format, below. */
9678 enum gs_keyword_index
9695 /* Vector of image_keyword structures describing the format
9696 of valid user-defined image specifications. */
9698 static struct image_keyword gs_format
[GS_LAST
] =
9700 {":type", IMAGE_SYMBOL_VALUE
, 1},
9701 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9702 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9703 {":file", IMAGE_STRING_VALUE
, 1},
9704 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9705 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9706 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9707 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9708 {":relief", IMAGE_INTEGER_VALUE
, 0},
9709 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9710 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9711 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9714 /* Structure describing the image type `ghostscript'. */
9716 static struct image_type gs_type
=
9726 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9729 gs_clear_image (f
, img
)
9733 /* IMG->data.ptr_val may contain a recorded colormap. */
9734 xfree (img
->data
.ptr_val
);
9735 x_clear_image (f
, img
);
9739 /* Return non-zero if OBJECT is a valid Ghostscript image
9746 struct image_keyword fmt
[GS_LAST
];
9750 bcopy (gs_format
, fmt
, sizeof fmt
);
9752 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9755 /* Bounding box must be a list or vector containing 4 integers. */
9756 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9759 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9760 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9765 else if (VECTORP (tem
))
9767 if (XVECTOR (tem
)->size
!= 4)
9769 for (i
= 0; i
< 4; ++i
)
9770 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9780 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9789 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9790 struct gcpro gcpro1
, gcpro2
;
9792 double in_width
, in_height
;
9793 Lisp_Object pixel_colors
= Qnil
;
9795 /* Compute pixel size of pixmap needed from the given size in the
9796 image specification. Sizes in the specification are in pt. 1 pt
9797 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9799 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9800 in_width
= XFASTINT (pt_width
) / 72.0;
9801 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9802 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9803 in_height
= XFASTINT (pt_height
) / 72.0;
9804 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9806 /* Create the pixmap. */
9807 xassert (img
->pixmap
== None
);
9808 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9809 img
->width
, img
->height
,
9810 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9814 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9818 /* Call the loader to fill the pixmap. It returns a process object
9819 if successful. We do not record_unwind_protect here because
9820 other places in redisplay like calling window scroll functions
9821 don't either. Let the Lisp loader use `unwind-protect' instead. */
9822 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9824 sprintf (buffer
, "%lu %lu",
9825 (unsigned long) FRAME_X_WINDOW (f
),
9826 (unsigned long) img
->pixmap
);
9827 window_and_pixmap_id
= build_string (buffer
);
9829 sprintf (buffer
, "%lu %lu",
9830 FRAME_FOREGROUND_PIXEL (f
),
9831 FRAME_BACKGROUND_PIXEL (f
));
9832 pixel_colors
= build_string (buffer
);
9834 XSETFRAME (frame
, f
);
9835 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9837 loader
= intern ("gs-load-image");
9839 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9840 make_number (img
->width
),
9841 make_number (img
->height
),
9842 window_and_pixmap_id
,
9845 return PROCESSP (img
->data
.lisp_val
);
9849 /* Kill the Ghostscript process that was started to fill PIXMAP on
9850 frame F. Called from XTread_socket when receiving an event
9851 telling Emacs that Ghostscript has finished drawing. */
9854 x_kill_gs_process (pixmap
, f
)
9858 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9862 /* Find the image containing PIXMAP. */
9863 for (i
= 0; i
< c
->used
; ++i
)
9864 if (c
->images
[i
]->pixmap
== pixmap
)
9867 /* Kill the GS process. We should have found PIXMAP in the image
9868 cache and its image should contain a process object. */
9869 xassert (i
< c
->used
);
9871 xassert (PROCESSP (img
->data
.lisp_val
));
9872 Fkill_process (img
->data
.lisp_val
, Qnil
);
9873 img
->data
.lisp_val
= Qnil
;
9875 /* On displays with a mutable colormap, figure out the colors
9876 allocated for the image by looking at the pixels of an XImage for
9878 class = FRAME_X_VISUAL (f
)->class;
9879 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9885 /* Try to get an XImage for img->pixmep. */
9886 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9887 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9892 /* Initialize the color table. */
9893 init_color_table ();
9895 /* For each pixel of the image, look its color up in the
9896 color table. After having done so, the color table will
9897 contain an entry for each color used by the image. */
9898 for (y
= 0; y
< img
->height
; ++y
)
9899 for (x
= 0; x
< img
->width
; ++x
)
9901 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9902 lookup_pixel_color (f
, pixel
);
9905 /* Record colors in the image. Free color table and XImage. */
9906 img
->colors
= colors_in_color_table (&img
->ncolors
);
9907 free_color_table ();
9908 XDestroyImage (ximg
);
9910 #if 0 /* This doesn't seem to be the case. If we free the colors
9911 here, we get a BadAccess later in x_clear_image when
9912 freeing the colors. */
9913 /* We have allocated colors once, but Ghostscript has also
9914 allocated colors on behalf of us. So, to get the
9915 reference counts right, free them once. */
9917 x_free_colors (f
, img
->colors
, img
->ncolors
);
9921 image_error ("Cannot get X image of `%s'; colors will not be freed",
9930 /***********************************************************************
9932 ***********************************************************************/
9934 DEFUN ("x-change-window-property", Fx_change_window_property
,
9935 Sx_change_window_property
, 2, 3, 0,
9936 "Change window property PROP to VALUE on the X window of FRAME.\n\
9937 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9938 selected frame. Value is VALUE.")
9939 (prop
, value
, frame
)
9940 Lisp_Object frame
, prop
, value
;
9942 struct frame
*f
= check_x_frame (frame
);
9945 CHECK_STRING (prop
, 1);
9946 CHECK_STRING (value
, 2);
9949 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9950 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9951 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9952 XSTRING (value
)->data
, XSTRING (value
)->size
);
9954 /* Make sure the property is set when we return. */
9955 XFlush (FRAME_X_DISPLAY (f
));
9962 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9963 Sx_delete_window_property
, 1, 2, 0,
9964 "Remove window property PROP from X window of FRAME.\n\
9965 FRAME nil or omitted means use the selected frame. Value is PROP.")
9967 Lisp_Object prop
, frame
;
9969 struct frame
*f
= check_x_frame (frame
);
9972 CHECK_STRING (prop
, 1);
9974 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9975 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9977 /* Make sure the property is removed when we return. */
9978 XFlush (FRAME_X_DISPLAY (f
));
9985 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9987 "Value is the value of window property PROP on FRAME.\n\
9988 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9989 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9992 Lisp_Object prop
, frame
;
9994 struct frame
*f
= check_x_frame (frame
);
9997 Lisp_Object prop_value
= Qnil
;
9998 char *tmp_data
= NULL
;
10001 unsigned long actual_size
, bytes_remaining
;
10003 CHECK_STRING (prop
, 1);
10005 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10006 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10007 prop_atom
, 0, 0, False
, XA_STRING
,
10008 &actual_type
, &actual_format
, &actual_size
,
10009 &bytes_remaining
, (unsigned char **) &tmp_data
);
10012 int size
= bytes_remaining
;
10017 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10018 prop_atom
, 0, bytes_remaining
,
10020 &actual_type
, &actual_format
,
10021 &actual_size
, &bytes_remaining
,
10022 (unsigned char **) &tmp_data
);
10024 prop_value
= make_string (tmp_data
, size
);
10035 /***********************************************************************
10037 ***********************************************************************/
10039 /* If non-null, an asynchronous timer that, when it expires, displays
10040 a busy cursor on all frames. */
10042 static struct atimer
*busy_cursor_atimer
;
10044 /* Non-zero means a busy cursor is currently shown. */
10046 static int busy_cursor_shown_p
;
10048 /* Number of seconds to wait before displaying a busy cursor. */
10050 static Lisp_Object Vbusy_cursor_delay
;
10052 /* Default number of seconds to wait before displaying a busy
10055 #define DEFAULT_BUSY_CURSOR_DELAY 1
10057 /* Function prototypes. */
10059 static void show_busy_cursor
P_ ((struct atimer
*));
10060 static void hide_busy_cursor
P_ ((void));
10063 /* Cancel a currently active busy-cursor timer, and start a new one. */
10066 start_busy_cursor ()
10069 int secs
, usecs
= 0;
10071 cancel_busy_cursor ();
10073 if (INTEGERP (Vbusy_cursor_delay
)
10074 && XINT (Vbusy_cursor_delay
) > 0)
10075 secs
= XFASTINT (Vbusy_cursor_delay
);
10076 else if (FLOATP (Vbusy_cursor_delay
)
10077 && XFLOAT_DATA (Vbusy_cursor_delay
) > 0)
10080 tem
= Ftruncate (Vbusy_cursor_delay
, Qnil
);
10081 secs
= XFASTINT (tem
);
10082 usecs
= (XFLOAT_DATA (Vbusy_cursor_delay
) - secs
) * 1000000;
10085 secs
= DEFAULT_BUSY_CURSOR_DELAY
;
10087 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
10088 busy_cursor_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
10089 show_busy_cursor
, NULL
);
10093 /* Cancel the busy cursor timer if active, hide a busy cursor if
10097 cancel_busy_cursor ()
10099 if (busy_cursor_atimer
)
10101 cancel_atimer (busy_cursor_atimer
);
10102 busy_cursor_atimer
= NULL
;
10105 if (busy_cursor_shown_p
)
10106 hide_busy_cursor ();
10110 /* Timer function of busy_cursor_atimer. TIMER is equal to
10111 busy_cursor_atimer.
10113 Display a busy cursor on all frames by mapping the frames'
10114 busy_window. Set the busy_p flag in the frames' output_data.x
10115 structure to indicate that a busy cursor is shown on the
10119 show_busy_cursor (timer
)
10120 struct atimer
*timer
;
10122 /* The timer implementation will cancel this timer automatically
10123 after this function has run. Set busy_cursor_atimer to null
10124 so that we know the timer doesn't have to be canceled. */
10125 busy_cursor_atimer
= NULL
;
10127 if (!busy_cursor_shown_p
)
10129 Lisp_Object rest
, frame
;
10133 FOR_EACH_FRAME (rest
, frame
)
10134 if (FRAME_X_P (XFRAME (frame
)))
10136 struct frame
*f
= XFRAME (frame
);
10138 f
->output_data
.x
->busy_p
= 1;
10140 if (!f
->output_data
.x
->busy_window
)
10142 unsigned long mask
= CWCursor
;
10143 XSetWindowAttributes attrs
;
10145 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
10147 f
->output_data
.x
->busy_window
10148 = XCreateWindow (FRAME_X_DISPLAY (f
),
10149 FRAME_OUTER_WINDOW (f
),
10150 0, 0, 32000, 32000, 0, 0,
10156 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10157 XFlush (FRAME_X_DISPLAY (f
));
10160 busy_cursor_shown_p
= 1;
10166 /* Hide the busy cursor on all frames, if it is currently shown. */
10169 hide_busy_cursor ()
10171 if (busy_cursor_shown_p
)
10173 Lisp_Object rest
, frame
;
10176 FOR_EACH_FRAME (rest
, frame
)
10178 struct frame
*f
= XFRAME (frame
);
10181 /* Watch out for newly created frames. */
10182 && f
->output_data
.x
->busy_window
)
10184 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10185 /* Sync here because XTread_socket looks at the busy_p flag
10186 that is reset to zero below. */
10187 XSync (FRAME_X_DISPLAY (f
), False
);
10188 f
->output_data
.x
->busy_p
= 0;
10192 busy_cursor_shown_p
= 0;
10199 /***********************************************************************
10201 ***********************************************************************/
10203 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10206 /* The frame of a currently visible tooltip, or null. */
10208 struct frame
*tip_frame
;
10210 /* If non-nil, a timer started that hides the last tooltip when it
10213 Lisp_Object tip_timer
;
10216 /* Create a frame for a tooltip on the display described by DPYINFO.
10217 PARMS is a list of frame parameters. Value is the frame. */
10220 x_create_tip_frame (dpyinfo
, parms
)
10221 struct x_display_info
*dpyinfo
;
10225 Lisp_Object frame
, tem
;
10227 long window_prompting
= 0;
10229 int count
= specpdl_ptr
- specpdl
;
10230 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10235 /* Use this general default value to start with until we know if
10236 this frame has a specified name. */
10237 Vx_resource_name
= Vinvocation_name
;
10239 #ifdef MULTI_KBOARD
10240 kb
= dpyinfo
->kboard
;
10242 kb
= &the_only_kboard
;
10245 /* Get the name of the frame to use for resource lookup. */
10246 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10247 if (!STRINGP (name
)
10248 && !EQ (name
, Qunbound
)
10250 error ("Invalid frame name--not a string or nil");
10251 Vx_resource_name
= name
;
10254 GCPRO3 (parms
, name
, frame
);
10255 tip_frame
= f
= make_frame (1);
10256 XSETFRAME (frame
, f
);
10257 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10259 f
->output_method
= output_x_window
;
10260 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10261 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10262 f
->output_data
.x
->icon_bitmap
= -1;
10263 f
->output_data
.x
->fontset
= -1;
10264 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
10265 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
10266 f
->icon_name
= Qnil
;
10267 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10268 #ifdef MULTI_KBOARD
10269 FRAME_KBOARD (f
) = kb
;
10271 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10272 f
->output_data
.x
->explicit_parent
= 0;
10274 /* These colors will be set anyway later, but it's important
10275 to get the color reference counts right, so initialize them! */
10278 struct gcpro gcpro1
;
10280 black
= build_string ("black");
10282 f
->output_data
.x
->foreground_pixel
10283 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10284 f
->output_data
.x
->background_pixel
10285 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10286 f
->output_data
.x
->cursor_pixel
10287 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10288 f
->output_data
.x
->cursor_foreground_pixel
10289 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10290 f
->output_data
.x
->border_pixel
10291 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10292 f
->output_data
.x
->mouse_pixel
10293 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
10297 /* Set the name; the functions to which we pass f expect the name to
10299 if (EQ (name
, Qunbound
) || NILP (name
))
10301 f
->name
= build_string (dpyinfo
->x_id_name
);
10302 f
->explicit_name
= 0;
10307 f
->explicit_name
= 1;
10308 /* use the frame's title when getting resources for this frame. */
10309 specbind (Qx_resource_name
, name
);
10312 /* Extract the window parameters from the supplied values
10313 that are needed to determine window geometry. */
10317 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10320 /* First, try whatever font the caller has specified. */
10321 if (STRINGP (font
))
10323 tem
= Fquery_fontset (font
, Qnil
);
10325 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10327 font
= x_new_font (f
, XSTRING (font
)->data
);
10330 /* Try out a font which we hope has bold and italic variations. */
10331 if (!STRINGP (font
))
10332 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10333 if (!STRINGP (font
))
10334 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10335 if (! STRINGP (font
))
10336 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10337 if (! STRINGP (font
))
10338 /* This was formerly the first thing tried, but it finds too many fonts
10339 and takes too long. */
10340 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10341 /* If those didn't work, look for something which will at least work. */
10342 if (! STRINGP (font
))
10343 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10345 if (! STRINGP (font
))
10346 font
= build_string ("fixed");
10348 x_default_parameter (f
, parms
, Qfont
, font
,
10349 "font", "Font", RES_TYPE_STRING
);
10352 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10353 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10355 /* This defaults to 2 in order to match xterm. We recognize either
10356 internalBorderWidth or internalBorder (which is what xterm calls
10358 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10362 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10363 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10364 if (! EQ (value
, Qunbound
))
10365 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10369 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10370 "internalBorderWidth", "internalBorderWidth",
10373 /* Also do the stuff which must be set before the window exists. */
10374 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10375 "foreground", "Foreground", RES_TYPE_STRING
);
10376 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10377 "background", "Background", RES_TYPE_STRING
);
10378 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10379 "pointerColor", "Foreground", RES_TYPE_STRING
);
10380 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10381 "cursorColor", "Foreground", RES_TYPE_STRING
);
10382 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10383 "borderColor", "BorderColor", RES_TYPE_STRING
);
10385 /* Init faces before x_default_parameter is called for scroll-bar
10386 parameters because that function calls x_set_scroll_bar_width,
10387 which calls change_frame_size, which calls Fset_window_buffer,
10388 which runs hooks, which call Fvertical_motion. At the end, we
10389 end up in init_iterator with a null face cache, which should not
10391 init_frame_faces (f
);
10393 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10394 window_prompting
= x_figure_window_size (f
, parms
);
10396 if (window_prompting
& XNegative
)
10398 if (window_prompting
& YNegative
)
10399 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10401 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10405 if (window_prompting
& YNegative
)
10406 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10408 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10411 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10413 XSetWindowAttributes attrs
;
10414 unsigned long mask
;
10417 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
10418 /* Window managers look at the override-redirect flag to determine
10419 whether or net to give windows a decoration (Xlib spec, chapter
10421 attrs
.override_redirect
= True
;
10422 attrs
.save_under
= True
;
10423 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
10424 /* Arrange for getting MapNotify and UnmapNotify events. */
10425 attrs
.event_mask
= StructureNotifyMask
;
10427 = FRAME_X_WINDOW (f
)
10428 = XCreateWindow (FRAME_X_DISPLAY (f
),
10429 FRAME_X_DISPLAY_INFO (f
)->root_window
,
10430 /* x, y, width, height */
10434 CopyFromParent
, InputOutput
, CopyFromParent
,
10441 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
10442 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10443 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
10444 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10445 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
10446 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
10448 /* Dimensions, especially f->height, must be done via change_frame_size.
10449 Change will not be effected unless different from the current
10452 height
= f
->height
;
10454 SET_FRAME_WIDTH (f
, 0);
10455 change_frame_size (f
, height
, width
, 1, 0, 0);
10461 /* It is now ok to make the frame official even if we get an error
10462 below. And the frame needs to be on Vframe_list or making it
10463 visible won't work. */
10464 Vframe_list
= Fcons (frame
, Vframe_list
);
10466 /* Now that the frame is official, it counts as a reference to
10468 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
10470 return unbind_to (count
, frame
);
10474 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
10475 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10476 A tooltip window is a small X window displaying a string.\n\
10478 FRAME nil or omitted means use the selected frame.\n\
10480 PARMS is an optional list of frame parameters which can be\n\
10481 used to change the tooltip's appearance.\n\
10483 Automatically hide the tooltip after TIMEOUT seconds.\n\
10484 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10486 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10487 the tooltip is displayed at that x-position. Otherwise it is\n\
10488 displayed at the mouse position, with offset DX added (default is 5 if\n\
10489 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10490 parameter is specified, it determines the y-position of the tooltip\n\
10491 window, otherwise it is displayed at the mouse position, with offset\n\
10492 DY added (default is -5).")
10493 (string
, frame
, parms
, timeout
, dx
, dy
)
10494 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
10498 Window root
, child
;
10499 Lisp_Object buffer
, top
, left
;
10500 struct buffer
*old_buffer
;
10501 struct text_pos pos
;
10502 int i
, width
, height
;
10503 int root_x
, root_y
, win_x
, win_y
;
10505 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
10506 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
10507 int count
= specpdl_ptr
- specpdl
;
10509 specbind (Qinhibit_redisplay
, Qt
);
10511 GCPRO4 (string
, parms
, frame
, timeout
);
10513 CHECK_STRING (string
, 0);
10514 f
= check_x_frame (frame
);
10515 if (NILP (timeout
))
10516 timeout
= make_number (5);
10518 CHECK_NATNUM (timeout
, 2);
10521 dx
= make_number (5);
10523 CHECK_NUMBER (dx
, 5);
10526 dy
= make_number (-5);
10528 CHECK_NUMBER (dy
, 6);
10530 /* Hide a previous tip, if any. */
10533 /* Add default values to frame parameters. */
10534 if (NILP (Fassq (Qname
, parms
)))
10535 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
10536 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10537 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
10538 if (NILP (Fassq (Qborder_width
, parms
)))
10539 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
10540 if (NILP (Fassq (Qborder_color
, parms
)))
10541 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
10542 if (NILP (Fassq (Qbackground_color
, parms
)))
10543 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
10546 /* Create a frame for the tooltip, and record it in the global
10547 variable tip_frame. */
10548 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
10549 tip_frame
= f
= XFRAME (frame
);
10551 /* Set up the frame's root window. Currently we use a size of 80
10552 columns x 40 lines. If someone wants to show a larger tip, he
10553 will loose. I don't think this is a realistic case. */
10554 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
10555 w
->left
= w
->top
= make_number (0);
10556 w
->width
= make_number (80);
10557 w
->height
= make_number (40);
10559 w
->pseudo_window_p
= 1;
10561 /* Display the tooltip text in a temporary buffer. */
10562 buffer
= Fget_buffer_create (build_string (" *tip*"));
10563 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10564 old_buffer
= current_buffer
;
10565 set_buffer_internal_1 (XBUFFER (buffer
));
10567 Finsert (1, &string
);
10568 clear_glyph_matrix (w
->desired_matrix
);
10569 clear_glyph_matrix (w
->current_matrix
);
10570 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
10571 try_window (FRAME_ROOT_WINDOW (f
), pos
);
10573 /* Compute width and height of the tooltip. */
10574 width
= height
= 0;
10575 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
10577 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
10578 struct glyph
*last
;
10581 /* Stop at the first empty row at the end. */
10582 if (!row
->enabled_p
|| !row
->displays_text_p
)
10585 /* Let the row go over the full width of the frame. */
10586 row
->full_width_p
= 1;
10588 /* There's a glyph at the end of rows that is used to place
10589 the cursor there. Don't include the width of this glyph. */
10590 if (row
->used
[TEXT_AREA
])
10592 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
10593 row_width
= row
->pixel_width
- last
->pixel_width
;
10596 row_width
= row
->pixel_width
;
10598 height
+= row
->height
;
10599 width
= max (width
, row_width
);
10602 /* Add the frame's internal border to the width and height the X
10603 window should have. */
10604 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10605 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10607 /* User-specified position? */
10608 left
= Fcdr (Fassq (Qleft
, parms
));
10609 top
= Fcdr (Fassq (Qtop
, parms
));
10611 /* Move the tooltip window where the mouse pointer is. Resize and
10614 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10615 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
10618 root_x
+= XINT (dx
);
10619 root_y
+= XINT (dy
);
10621 if (INTEGERP (left
))
10622 root_x
= XINT (left
);
10623 if (INTEGERP (top
))
10624 root_y
= XINT (top
);
10627 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10628 root_x
, root_y
- height
, width
, height
);
10629 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10632 /* Draw into the window. */
10633 w
->must_be_updated_p
= 1;
10634 update_single_window (w
, 1);
10636 /* Restore original current buffer. */
10637 set_buffer_internal_1 (old_buffer
);
10638 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
10640 /* Let the tip disappear after timeout seconds. */
10641 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
10642 intern ("x-hide-tip"));
10645 return unbind_to (count
, Qnil
);
10649 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
10650 "Hide the current tooltip window, if there is any.\n\
10651 Value is t is tooltip was open, nil otherwise.")
10654 int count
= specpdl_ptr
- specpdl
;
10657 specbind (Qinhibit_redisplay
, Qt
);
10659 if (!NILP (tip_timer
))
10661 call1 (intern ("cancel-timer"), tip_timer
);
10669 XSETFRAME (frame
, tip_frame
);
10670 Fdelete_frame (frame
, Qt
);
10675 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
10680 /***********************************************************************
10681 File selection dialog
10682 ***********************************************************************/
10686 /* Callback for "OK" and "Cancel" on file selection dialog. */
10689 file_dialog_cb (widget
, client_data
, call_data
)
10691 XtPointer call_data
, client_data
;
10693 int *result
= (int *) client_data
;
10694 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
10695 *result
= cb
->reason
;
10699 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
10700 "Read file name, prompting with PROMPT in directory DIR.\n\
10701 Use a file selection dialog.\n\
10702 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10703 specified. Don't let the user enter a file name in the file\n\
10704 selection dialog's entry field, if MUSTMATCH is non-nil.")
10705 (prompt
, dir
, default_filename
, mustmatch
)
10706 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
10709 struct frame
*f
= SELECTED_FRAME ();
10710 Lisp_Object file
= Qnil
;
10711 Widget dialog
, text
, list
, help
;
10714 extern XtAppContext Xt_app_con
;
10716 XmString dir_xmstring
, pattern_xmstring
;
10717 int popup_activated_flag
;
10718 int count
= specpdl_ptr
- specpdl
;
10719 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
10721 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
10722 CHECK_STRING (prompt
, 0);
10723 CHECK_STRING (dir
, 1);
10725 /* Prevent redisplay. */
10726 specbind (Qinhibit_redisplay
, Qt
);
10730 /* Create the dialog with PROMPT as title, using DIR as initial
10731 directory and using "*" as pattern. */
10732 dir
= Fexpand_file_name (dir
, Qnil
);
10733 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
10734 pattern_xmstring
= XmStringCreateLocalized ("*");
10736 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
10737 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
10738 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
10739 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
10740 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
10741 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
10743 XmStringFree (dir_xmstring
);
10744 XmStringFree (pattern_xmstring
);
10746 /* Add callbacks for OK and Cancel. */
10747 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
10748 (XtPointer
) &result
);
10749 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
10750 (XtPointer
) &result
);
10752 /* Disable the help button since we can't display help. */
10753 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
10754 XtSetSensitive (help
, False
);
10756 /* Mark OK button as default. */
10757 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
10758 XmNshowAsDefault
, True
, NULL
);
10760 /* If MUSTMATCH is non-nil, disable the file entry field of the
10761 dialog, so that the user must select a file from the files list
10762 box. We can't remove it because we wouldn't have a way to get at
10763 the result file name, then. */
10764 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
10765 if (!NILP (mustmatch
))
10768 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
10769 XtSetSensitive (text
, False
);
10770 XtSetSensitive (label
, False
);
10773 /* Manage the dialog, so that list boxes get filled. */
10774 XtManageChild (dialog
);
10776 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10777 must include the path for this to work. */
10778 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
10779 if (STRINGP (default_filename
))
10781 XmString default_xmstring
;
10785 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
10787 if (!XmListItemExists (list
, default_xmstring
))
10789 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10790 XmListAddItem (list
, default_xmstring
, 0);
10794 item_pos
= XmListItemPos (list
, default_xmstring
);
10795 XmStringFree (default_xmstring
);
10797 /* Select the item and scroll it into view. */
10798 XmListSelectPos (list
, item_pos
, True
);
10799 XmListSetPos (list
, item_pos
);
10802 #ifdef HAVE_MOTIF_2_1
10804 /* Process events until the user presses Cancel or OK. */
10806 while (result
== 0 || XtAppPending (Xt_app_con
))
10807 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
10809 #else /* not HAVE_MOTIF_2_1 */
10811 /* Process all events until the user presses Cancel or OK. */
10812 for (result
= 0; result
== 0;)
10815 Widget widget
, parent
;
10817 XtAppNextEvent (Xt_app_con
, &event
);
10819 /* See if the receiver of the event is one of the widgets of
10820 the file selection dialog. If so, dispatch it. If not,
10822 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
10824 while (parent
&& parent
!= dialog
)
10825 parent
= XtParent (parent
);
10827 if (parent
== dialog
10828 || (event
.type
== Expose
10829 && !process_expose_from_menu (event
)))
10830 XtDispatchEvent (&event
);
10833 #endif /* not HAVE_MOTIF_2_1 */
10835 /* Get the result. */
10836 if (result
== XmCR_OK
)
10841 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
10842 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
10843 XmStringFree (text
);
10844 file
= build_string (data
);
10851 XtUnmanageChild (dialog
);
10852 XtDestroyWidget (dialog
);
10856 /* Make "Cancel" equivalent to C-g. */
10858 Fsignal (Qquit
, Qnil
);
10860 return unbind_to (count
, file
);
10863 #endif /* USE_MOTIF */
10867 /***********************************************************************
10869 ***********************************************************************/
10874 /* This is zero if not using X windows. */
10877 /* The section below is built by the lisp expression at the top of the file,
10878 just above where these variables are declared. */
10879 /*&&& init symbols here &&&*/
10880 Qauto_raise
= intern ("auto-raise");
10881 staticpro (&Qauto_raise
);
10882 Qauto_lower
= intern ("auto-lower");
10883 staticpro (&Qauto_lower
);
10884 Qbar
= intern ("bar");
10886 Qborder_color
= intern ("border-color");
10887 staticpro (&Qborder_color
);
10888 Qborder_width
= intern ("border-width");
10889 staticpro (&Qborder_width
);
10890 Qbox
= intern ("box");
10892 Qcursor_color
= intern ("cursor-color");
10893 staticpro (&Qcursor_color
);
10894 Qcursor_type
= intern ("cursor-type");
10895 staticpro (&Qcursor_type
);
10896 Qgeometry
= intern ("geometry");
10897 staticpro (&Qgeometry
);
10898 Qicon_left
= intern ("icon-left");
10899 staticpro (&Qicon_left
);
10900 Qicon_top
= intern ("icon-top");
10901 staticpro (&Qicon_top
);
10902 Qicon_type
= intern ("icon-type");
10903 staticpro (&Qicon_type
);
10904 Qicon_name
= intern ("icon-name");
10905 staticpro (&Qicon_name
);
10906 Qinternal_border_width
= intern ("internal-border-width");
10907 staticpro (&Qinternal_border_width
);
10908 Qleft
= intern ("left");
10909 staticpro (&Qleft
);
10910 Qright
= intern ("right");
10911 staticpro (&Qright
);
10912 Qmouse_color
= intern ("mouse-color");
10913 staticpro (&Qmouse_color
);
10914 Qnone
= intern ("none");
10915 staticpro (&Qnone
);
10916 Qparent_id
= intern ("parent-id");
10917 staticpro (&Qparent_id
);
10918 Qscroll_bar_width
= intern ("scroll-bar-width");
10919 staticpro (&Qscroll_bar_width
);
10920 Qsuppress_icon
= intern ("suppress-icon");
10921 staticpro (&Qsuppress_icon
);
10922 Qundefined_color
= intern ("undefined-color");
10923 staticpro (&Qundefined_color
);
10924 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10925 staticpro (&Qvertical_scroll_bars
);
10926 Qvisibility
= intern ("visibility");
10927 staticpro (&Qvisibility
);
10928 Qwindow_id
= intern ("window-id");
10929 staticpro (&Qwindow_id
);
10930 Qouter_window_id
= intern ("outer-window-id");
10931 staticpro (&Qouter_window_id
);
10932 Qx_frame_parameter
= intern ("x-frame-parameter");
10933 staticpro (&Qx_frame_parameter
);
10934 Qx_resource_name
= intern ("x-resource-name");
10935 staticpro (&Qx_resource_name
);
10936 Quser_position
= intern ("user-position");
10937 staticpro (&Quser_position
);
10938 Quser_size
= intern ("user-size");
10939 staticpro (&Quser_size
);
10940 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10941 staticpro (&Qscroll_bar_foreground
);
10942 Qscroll_bar_background
= intern ("scroll-bar-background");
10943 staticpro (&Qscroll_bar_background
);
10944 Qscreen_gamma
= intern ("screen-gamma");
10945 staticpro (&Qscreen_gamma
);
10946 Qline_spacing
= intern ("line-spacing");
10947 staticpro (&Qline_spacing
);
10948 Qcenter
= intern ("center");
10949 staticpro (&Qcenter
);
10950 Qcompound_text
= intern ("compound-text");
10951 staticpro (&Qcompound_text
);
10952 /* This is the end of symbol initialization. */
10954 /* Text property `display' should be nonsticky by default. */
10955 Vtext_property_default_nonsticky
10956 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
10959 Qlaplace
= intern ("laplace");
10960 staticpro (&Qlaplace
);
10961 Qemboss
= intern ("emboss");
10962 staticpro (&Qemboss
);
10963 Qedge_detection
= intern ("edge-detection");
10964 staticpro (&Qedge_detection
);
10965 Qheuristic
= intern ("heuristic");
10966 staticpro (&Qheuristic
);
10967 QCmatrix
= intern (":matrix");
10968 staticpro (&QCmatrix
);
10969 QCcolor_adjustment
= intern (":color-adjustment");
10970 staticpro (&QCcolor_adjustment
);
10971 QCmask
= intern (":mask");
10972 staticpro (&QCmask
);
10974 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10975 staticpro (&Qface_set_after_frame_default
);
10977 Fput (Qundefined_color
, Qerror_conditions
,
10978 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10979 Fput (Qundefined_color
, Qerror_message
,
10980 build_string ("Undefined color"));
10982 init_x_parm_symbols ();
10984 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
10985 "Non-nil means always draw a cross over disabled images.\n\
10986 Disabled images are those having an `:algorithm disabled' property.\n\
10987 A cross is always drawn on black & white displays.");
10988 cross_disabled_images
= 0;
10990 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10991 "List of directories to search for bitmap files for X.");
10992 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
10994 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10995 "The shape of the pointer when over text.\n\
10996 Changing the value does not affect existing frames\n\
10997 unless you set the mouse color.");
10998 Vx_pointer_shape
= Qnil
;
11000 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
11001 "The name Emacs uses to look up X resources.\n\
11002 `x-get-resource' uses this as the first component of the instance name\n\
11003 when requesting resource values.\n\
11004 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11005 was invoked, or to the value specified with the `-name' or `-rn'\n\
11006 switches, if present.\n\
11008 It may be useful to bind this variable locally around a call\n\
11009 to `x-get-resource'. See also the variable `x-resource-class'.");
11010 Vx_resource_name
= Qnil
;
11012 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
11013 "The class Emacs uses to look up X resources.\n\
11014 `x-get-resource' uses this as the first component of the instance class\n\
11015 when requesting resource values.\n\
11016 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11018 Setting this variable permanently is not a reasonable thing to do,\n\
11019 but binding this variable locally around a call to `x-get-resource'\n\
11020 is a reasonable practice. See also the variable `x-resource-name'.");
11021 Vx_resource_class
= build_string (EMACS_CLASS
);
11023 #if 0 /* This doesn't really do anything. */
11024 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
11025 "The shape of the pointer when not over text.\n\
11026 This variable takes effect when you create a new frame\n\
11027 or when you set the mouse color.");
11029 Vx_nontext_pointer_shape
= Qnil
;
11031 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
11032 "The shape of the pointer when Emacs is busy.\n\
11033 This variable takes effect when you create a new frame\n\
11034 or when you set the mouse color.");
11035 Vx_busy_pointer_shape
= Qnil
;
11037 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
11038 "Non-zero means Emacs displays a busy cursor on window systems.");
11039 display_busy_cursor_p
= 1;
11041 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay
,
11042 "*Seconds to wait before displaying a busy-cursor.\n\
11043 Value must be an integer or float.");
11044 Vbusy_cursor_delay
= make_number (DEFAULT_BUSY_CURSOR_DELAY
);
11046 #if 0 /* This doesn't really do anything. */
11047 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
11048 "The shape of the pointer when over the mode line.\n\
11049 This variable takes effect when you create a new frame\n\
11050 or when you set the mouse color.");
11052 Vx_mode_pointer_shape
= Qnil
;
11054 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11055 &Vx_sensitive_text_pointer_shape
,
11056 "The shape of the pointer when over mouse-sensitive text.\n\
11057 This variable takes effect when you create a new frame\n\
11058 or when you set the mouse color.");
11059 Vx_sensitive_text_pointer_shape
= Qnil
;
11061 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
11062 "A string indicating the foreground color of the cursor box.");
11063 Vx_cursor_fore_pixel
= Qnil
;
11065 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
11066 "Non-nil if no X window manager is in use.\n\
11067 Emacs doesn't try to figure this out; this is always nil\n\
11068 unless you set it to something else.");
11069 /* We don't have any way to find this out, so set it to nil
11070 and maybe the user would like to set it to t. */
11071 Vx_no_window_manager
= Qnil
;
11073 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11074 &Vx_pixel_size_width_font_regexp
,
11075 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11077 Since Emacs gets width of a font matching with this regexp from\n\
11078 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11079 such a font. This is especially effective for such large fonts as\n\
11080 Chinese, Japanese, and Korean.");
11081 Vx_pixel_size_width_font_regexp
= Qnil
;
11083 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
11084 "Time after which cached images are removed from the cache.\n\
11085 When an image has not been displayed this many seconds, remove it\n\
11086 from the image cache. Value must be an integer or nil with nil\n\
11087 meaning don't clear the cache.");
11088 Vimage_cache_eviction_delay
= make_number (30 * 60);
11090 #ifdef USE_X_TOOLKIT
11091 Fprovide (intern ("x-toolkit"));
11094 Fprovide (intern ("motif"));
11097 defsubr (&Sx_get_resource
);
11099 /* X window properties. */
11100 defsubr (&Sx_change_window_property
);
11101 defsubr (&Sx_delete_window_property
);
11102 defsubr (&Sx_window_property
);
11104 defsubr (&Sxw_display_color_p
);
11105 defsubr (&Sx_display_grayscale_p
);
11106 defsubr (&Sxw_color_defined_p
);
11107 defsubr (&Sxw_color_values
);
11108 defsubr (&Sx_server_max_request_size
);
11109 defsubr (&Sx_server_vendor
);
11110 defsubr (&Sx_server_version
);
11111 defsubr (&Sx_display_pixel_width
);
11112 defsubr (&Sx_display_pixel_height
);
11113 defsubr (&Sx_display_mm_width
);
11114 defsubr (&Sx_display_mm_height
);
11115 defsubr (&Sx_display_screens
);
11116 defsubr (&Sx_display_planes
);
11117 defsubr (&Sx_display_color_cells
);
11118 defsubr (&Sx_display_visual_class
);
11119 defsubr (&Sx_display_backing_store
);
11120 defsubr (&Sx_display_save_under
);
11121 defsubr (&Sx_parse_geometry
);
11122 defsubr (&Sx_create_frame
);
11123 defsubr (&Sx_open_connection
);
11124 defsubr (&Sx_close_connection
);
11125 defsubr (&Sx_display_list
);
11126 defsubr (&Sx_synchronize
);
11127 defsubr (&Sx_focus_frame
);
11129 /* Setting callback functions for fontset handler. */
11130 get_font_info_func
= x_get_font_info
;
11132 #if 0 /* This function pointer doesn't seem to be used anywhere.
11133 And the pointer assigned has the wrong type, anyway. */
11134 list_fonts_func
= x_list_fonts
;
11137 load_font_func
= x_load_font
;
11138 find_ccl_program_func
= x_find_ccl_program
;
11139 query_font_func
= x_query_font
;
11140 set_frame_fontset_func
= x_set_font
;
11141 check_window_system_func
= check_x
;
11144 Qxbm
= intern ("xbm");
11146 QCtype
= intern (":type");
11147 staticpro (&QCtype
);
11148 QCalgorithm
= intern (":algorithm");
11149 staticpro (&QCalgorithm
);
11150 QCheuristic_mask
= intern (":heuristic-mask");
11151 staticpro (&QCheuristic_mask
);
11152 QCcolor_symbols
= intern (":color-symbols");
11153 staticpro (&QCcolor_symbols
);
11154 QCascent
= intern (":ascent");
11155 staticpro (&QCascent
);
11156 QCmargin
= intern (":margin");
11157 staticpro (&QCmargin
);
11158 QCrelief
= intern (":relief");
11159 staticpro (&QCrelief
);
11160 Qpostscript
= intern ("postscript");
11161 staticpro (&Qpostscript
);
11162 QCloader
= intern (":loader");
11163 staticpro (&QCloader
);
11164 QCbounding_box
= intern (":bounding-box");
11165 staticpro (&QCbounding_box
);
11166 QCpt_width
= intern (":pt-width");
11167 staticpro (&QCpt_width
);
11168 QCpt_height
= intern (":pt-height");
11169 staticpro (&QCpt_height
);
11170 QCindex
= intern (":index");
11171 staticpro (&QCindex
);
11172 Qpbm
= intern ("pbm");
11176 Qxpm
= intern ("xpm");
11181 Qjpeg
= intern ("jpeg");
11182 staticpro (&Qjpeg
);
11186 Qtiff
= intern ("tiff");
11187 staticpro (&Qtiff
);
11191 Qgif
= intern ("gif");
11196 Qpng
= intern ("png");
11200 defsubr (&Sclear_image_cache
);
11201 defsubr (&Simage_size
);
11202 defsubr (&Simage_mask_p
);
11204 busy_cursor_atimer
= NULL
;
11205 busy_cursor_shown_p
= 0;
11207 defsubr (&Sx_show_tip
);
11208 defsubr (&Sx_hide_tip
);
11209 staticpro (&tip_timer
);
11213 defsubr (&Sx_file_dialog
);
11221 image_types
= NULL
;
11222 Vimage_types
= Qnil
;
11224 define_image_type (&xbm_type
);
11225 define_image_type (&gs_type
);
11226 define_image_type (&pbm_type
);
11229 define_image_type (&xpm_type
);
11233 define_image_type (&jpeg_type
);
11237 define_image_type (&tiff_type
);
11241 define_image_type (&gif_type
);
11245 define_image_type (&png_type
);
11249 #endif /* HAVE_X_WINDOWS */