1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
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. */
22 /* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
23 toolbars, busy-cursor, file selection dialog added by Gerd
24 Moellmann <gerd@gnu.org>. */
26 /* Completely rewritten by Richard Stallman. */
28 /* Rewritten for X11 by Joseph Arceneaux */
34 /* This makes the fields of a Display accessible, in Xlib header files. */
36 #define XLIB_ILLEGAL_ACCESS
43 #include "dispextern.h"
45 #include "blockinput.h"
50 #include "termhooks.h"
55 /* On some systems, the character-composition stuff is broken in X11R5. */
57 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
58 #ifdef X11R5_INHIBIT_I18N
59 #define X_I18N_INHIBITED
64 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
65 #include "bitmaps/gray.xbm"
67 #include <X11/bitmaps/gray>
70 #include "[.bitmaps]gray.xbm"
74 #include <X11/Shell.h>
77 #include <X11/Xaw/Paned.h>
78 #include <X11/Xaw/Label.h>
79 #endif /* USE_MOTIF */
82 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
91 #include "../lwlib/lwlib.h"
95 #include <Xm/DialogS.h>
96 #include <Xm/FileSB.h>
99 /* Do the EDITRES protocol if running X11R5
100 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
102 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
104 extern void _XEditResCheckMessages ();
105 #endif /* R5 + Athena */
107 /* Unique id counter for widgets created by the Lucid Widget Library. */
109 extern LWLIB_ID widget_id_tick
;
112 /* This is part of a kludge--see lwlib/xlwmenu.c. */
113 extern XFontStruct
*xlwmenu_default_font
;
116 extern void free_frame_menubar ();
118 #endif /* USE_X_TOOLKIT */
120 #define min(a,b) ((a) < (b) ? (a) : (b))
121 #define max(a,b) ((a) > (b) ? (a) : (b))
124 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
126 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
129 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
130 it, and including `bitmaps/gray' more than once is a problem when
131 config.h defines `static' as an empty replacement string. */
133 int gray_bitmap_width
= gray_width
;
134 int gray_bitmap_height
= gray_height
;
135 unsigned char *gray_bitmap_bits
= gray_bits
;
137 /* The name we're using in resource queries. Most often "emacs". */
139 Lisp_Object Vx_resource_name
;
141 /* The application class we're using in resource queries.
144 Lisp_Object Vx_resource_class
;
146 /* Non-zero means we're allowed to display a busy cursor. */
148 int display_busy_cursor_p
;
150 /* The background and shape of the mouse pointer, and shape when not
151 over text or in the modeline. */
153 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
154 Lisp_Object Vx_busy_pointer_shape
;
156 /* The shape when over mouse-sensitive text. */
158 Lisp_Object Vx_sensitive_text_pointer_shape
;
160 /* Color of chars displayed in cursor box. */
162 Lisp_Object Vx_cursor_fore_pixel
;
164 /* Nonzero if using X. */
168 /* Non nil if no window manager is in use. */
170 Lisp_Object Vx_no_window_manager
;
172 /* Search path for bitmap files. */
174 Lisp_Object Vx_bitmap_file_path
;
176 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
178 Lisp_Object Vx_pixel_size_width_font_regexp
;
180 /* Evaluate this expression to rebuild the section of syms_of_xfns
181 that initializes and staticpros the symbols declared below. Note
182 that Emacs 18 has a bug that keeps C-x C-e from being able to
183 evaluate this expression.
186 ;; Accumulate a list of the symbols we want to initialize from the
187 ;; declarations at the top of the file.
188 (goto-char (point-min))
189 (search-forward "/\*&&& symbols declared here &&&*\/\n")
191 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
193 (cons (buffer-substring (match-beginning 1) (match-end 1))
196 (setq symbol-list (nreverse symbol-list))
197 ;; Delete the section of syms_of_... where we initialize the symbols.
198 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
199 (let ((start (point)))
200 (while (looking-at "^ Q")
202 (kill-region start (point)))
203 ;; Write a new symbol initialization section.
205 (insert (format " %s = intern (\"" (car symbol-list)))
206 (let ((start (point)))
207 (insert (substring (car symbol-list) 1))
208 (subst-char-in-region start (point) ?_ ?-))
209 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
210 (setq symbol-list (cdr symbol-list)))))
214 /*&&& symbols declared here &&&*/
215 Lisp_Object Qauto_raise
;
216 Lisp_Object Qauto_lower
;
218 Lisp_Object Qborder_color
;
219 Lisp_Object Qborder_width
;
221 Lisp_Object Qcursor_color
;
222 Lisp_Object Qcursor_type
;
223 Lisp_Object Qgeometry
;
224 Lisp_Object Qicon_left
;
225 Lisp_Object Qicon_top
;
226 Lisp_Object Qicon_type
;
227 Lisp_Object Qicon_name
;
228 Lisp_Object Qinternal_border_width
;
231 Lisp_Object Qmouse_color
;
233 Lisp_Object Qouter_window_id
;
234 Lisp_Object Qparent_id
;
235 Lisp_Object Qscroll_bar_width
;
236 Lisp_Object Qsuppress_icon
;
237 extern Lisp_Object Qtop
;
238 Lisp_Object Qundefined_color
;
239 Lisp_Object Qvertical_scroll_bars
;
240 Lisp_Object Qvisibility
;
241 Lisp_Object Qwindow_id
;
242 Lisp_Object Qx_frame_parameter
;
243 Lisp_Object Qx_resource_name
;
244 Lisp_Object Quser_position
;
245 Lisp_Object Quser_size
;
246 Lisp_Object Qdisplay
;
247 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
249 /* The below are defined in frame.c. */
251 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
252 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
253 extern Lisp_Object Qtoolbar_lines
;
255 extern Lisp_Object Vwindow_system_version
;
257 Lisp_Object Qface_set_after_frame_default
;
260 /* Error if we are not connected to X. */
266 error ("X windows are not in use or not initialized");
269 /* Nonzero if we can use mouse menus.
270 You should not call this unless HAVE_MENUS is defined. */
278 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
279 and checking validity for X. */
282 check_x_frame (frame
)
291 CHECK_LIVE_FRAME (frame
, 0);
295 error ("Non-X frame used");
299 /* Let the user specify an X display with a frame.
300 nil stands for the selected frame--or, if that is not an X frame,
301 the first X display on the list. */
303 static struct x_display_info
*
304 check_x_display_info (frame
)
309 if (FRAME_X_P (selected_frame
)
310 && FRAME_LIVE_P (selected_frame
))
311 return FRAME_X_DISPLAY_INFO (selected_frame
);
312 else if (x_display_list
!= 0)
313 return x_display_list
;
315 error ("X windows are not in use or not initialized");
317 else if (STRINGP (frame
))
318 return x_display_info_for_name (frame
);
323 CHECK_LIVE_FRAME (frame
, 0);
326 error ("Non-X frame used");
327 return FRAME_X_DISPLAY_INFO (f
);
332 /* Return the Emacs frame-object corresponding to an X window.
333 It could be the frame's main window or an icon window. */
335 /* This function can be called during GC, so use GC_xxx type test macros. */
338 x_window_to_frame (dpyinfo
, wdesc
)
339 struct x_display_info
*dpyinfo
;
342 Lisp_Object tail
, frame
;
345 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
347 frame
= XCONS (tail
)->car
;
348 if (!GC_FRAMEP (frame
))
351 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
354 if ((f
->output_data
.x
->edit_widget
355 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
356 /* A tooltip frame? */
357 || (!f
->output_data
.x
->edit_widget
358 && FRAME_X_WINDOW (f
) == wdesc
)
359 || f
->output_data
.x
->icon_desc
== wdesc
)
361 #else /* not USE_X_TOOLKIT */
362 if (FRAME_X_WINDOW (f
) == wdesc
363 || f
->output_data
.x
->icon_desc
== wdesc
)
365 #endif /* not USE_X_TOOLKIT */
371 /* Like x_window_to_frame but also compares the window with the widget's
375 x_any_window_to_frame (dpyinfo
, wdesc
)
376 struct x_display_info
*dpyinfo
;
379 Lisp_Object tail
, frame
;
383 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
385 frame
= XCONS (tail
)->car
;
386 if (!GC_FRAMEP (frame
))
389 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
391 x
= f
->output_data
.x
;
392 /* This frame matches if the window is any of its widgets. */
395 if (wdesc
== XtWindow (x
->widget
)
396 || wdesc
== XtWindow (x
->column_widget
)
397 || wdesc
== XtWindow (x
->edit_widget
))
399 /* Match if the window is this frame's menubar. */
400 if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
403 else if (FRAME_X_WINDOW (f
) == wdesc
)
404 /* A tooltip frame. */
410 /* Likewise, but exclude the menu bar widget. */
413 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
414 struct x_display_info
*dpyinfo
;
417 Lisp_Object tail
, frame
;
421 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
423 frame
= XCONS (tail
)->car
;
424 if (!GC_FRAMEP (frame
))
427 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
429 x
= f
->output_data
.x
;
430 /* This frame matches if the window is any of its widgets. */
433 if (wdesc
== XtWindow (x
->widget
)
434 || wdesc
== XtWindow (x
->column_widget
)
435 || wdesc
== XtWindow (x
->edit_widget
))
438 else if (FRAME_X_WINDOW (f
) == wdesc
)
439 /* A tooltip frame. */
445 /* Likewise, but consider only the menu bar widget. */
448 x_menubar_window_to_frame (dpyinfo
, wdesc
)
449 struct x_display_info
*dpyinfo
;
452 Lisp_Object tail
, frame
;
456 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
458 frame
= XCONS (tail
)->car
;
459 if (!GC_FRAMEP (frame
))
462 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
464 x
= f
->output_data
.x
;
465 /* Match if the window is this frame's menubar. */
466 if (x
->menubar_widget
467 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
473 /* Return the frame whose principal (outermost) window is WDESC.
474 If WDESC is some other (smaller) window, we return 0. */
477 x_top_window_to_frame (dpyinfo
, wdesc
)
478 struct x_display_info
*dpyinfo
;
481 Lisp_Object tail
, frame
;
485 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
487 frame
= XCONS (tail
)->car
;
488 if (!GC_FRAMEP (frame
))
491 if (f
->output_data
.nothing
== 1 || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
493 x
= f
->output_data
.x
;
497 /* This frame matches if the window is its topmost widget. */
498 if (wdesc
== XtWindow (x
->widget
))
500 #if 0 /* I don't know why it did this,
501 but it seems logically wrong,
502 and it causes trouble for MapNotify events. */
503 /* Match if the window is this frame's menubar. */
504 if (x
->menubar_widget
505 && wdesc
== XtWindow (x
->menubar_widget
))
509 else if (FRAME_X_WINDOW (f
) == wdesc
)
515 #endif /* USE_X_TOOLKIT */
519 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
520 id, which is just an int that this section returns. Bitmaps are
521 reference counted so they can be shared among frames.
523 Bitmap indices are guaranteed to be > 0, so a negative number can
524 be used to indicate no bitmap.
526 If you use x_create_bitmap_from_data, then you must keep track of
527 the bitmaps yourself. That is, creating a bitmap from the same
528 data more than once will not be caught. */
531 /* Functions to access the contents of a bitmap, given an id. */
534 x_bitmap_height (f
, id
)
538 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
542 x_bitmap_width (f
, id
)
546 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
550 x_bitmap_pixmap (f
, id
)
554 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
558 /* Allocate a new bitmap record. Returns index of new record. */
561 x_allocate_bitmap_record (f
)
564 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
567 if (dpyinfo
->bitmaps
== NULL
)
569 dpyinfo
->bitmaps_size
= 10;
571 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
572 dpyinfo
->bitmaps_last
= 1;
576 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
577 return ++dpyinfo
->bitmaps_last
;
579 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
580 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
583 dpyinfo
->bitmaps_size
*= 2;
585 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
586 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
587 return ++dpyinfo
->bitmaps_last
;
590 /* Add one reference to the reference count of the bitmap with id ID. */
593 x_reference_bitmap (f
, id
)
597 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
600 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
603 x_create_bitmap_from_data (f
, bits
, width
, height
)
606 unsigned int width
, height
;
608 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
612 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
613 bits
, width
, height
);
618 id
= x_allocate_bitmap_record (f
);
619 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
620 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
621 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
622 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
623 dpyinfo
->bitmaps
[id
- 1].height
= height
;
624 dpyinfo
->bitmaps
[id
- 1].width
= width
;
629 /* Create bitmap from file FILE for frame F. */
632 x_create_bitmap_from_file (f
, file
)
636 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
637 unsigned int width
, height
;
639 int xhot
, yhot
, result
, id
;
644 /* Look for an existing bitmap with the same name. */
645 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
647 if (dpyinfo
->bitmaps
[id
].refcount
648 && dpyinfo
->bitmaps
[id
].file
649 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
651 ++dpyinfo
->bitmaps
[id
].refcount
;
656 /* Search bitmap-file-path for the file, if appropriate. */
657 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
660 /* XReadBitmapFile won't handle magic file names. */
665 filename
= (char *) XSTRING (found
)->data
;
667 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
668 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
669 if (result
!= BitmapSuccess
)
672 id
= x_allocate_bitmap_record (f
);
673 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
674 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
675 dpyinfo
->bitmaps
[id
- 1].file
676 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
677 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
678 dpyinfo
->bitmaps
[id
- 1].height
= height
;
679 dpyinfo
->bitmaps
[id
- 1].width
= width
;
680 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
685 /* Remove reference to bitmap with id number ID. */
688 x_destroy_bitmap (f
, id
)
692 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
696 --dpyinfo
->bitmaps
[id
- 1].refcount
;
697 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
700 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
701 if (dpyinfo
->bitmaps
[id
- 1].file
)
703 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
704 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
711 /* Free all the bitmaps for the display specified by DPYINFO. */
714 x_destroy_all_bitmaps (dpyinfo
)
715 struct x_display_info
*dpyinfo
;
718 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
719 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
721 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
722 if (dpyinfo
->bitmaps
[i
].file
)
723 xfree (dpyinfo
->bitmaps
[i
].file
);
725 dpyinfo
->bitmaps_last
= 0;
728 /* Connect the frame-parameter names for X frames
729 to the ways of passing the parameter values to the window system.
731 The name of a parameter, as a Lisp symbol,
732 has an `x-frame-parameter' property which is an integer in Lisp
733 that is an index in this table. */
735 struct x_frame_parm_table
738 void (*setter
)( /* struct frame *frame, Lisp_Object val, oldval */ );
741 void x_set_foreground_color ();
742 void x_set_background_color ();
743 void x_set_mouse_color ();
744 void x_set_cursor_color ();
745 void x_set_border_color ();
746 void x_set_cursor_type ();
747 void x_set_icon_type ();
748 void x_set_icon_name ();
750 void x_set_border_width ();
751 void x_set_internal_border_width ();
752 void x_explicitly_set_name ();
753 void x_set_autoraise ();
754 void x_set_autolower ();
755 void x_set_vertical_scroll_bars ();
756 void x_set_visibility ();
757 void x_set_menu_bar_lines ();
758 void x_set_scroll_bar_width ();
760 void x_set_unsplittable ();
761 void x_set_toolbar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
762 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
764 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
766 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
772 static struct x_frame_parm_table x_frame_parms
[] =
774 "auto-raise", x_set_autoraise
,
775 "auto-lower", x_set_autolower
,
776 "background-color", x_set_background_color
,
777 "border-color", x_set_border_color
,
778 "border-width", x_set_border_width
,
779 "cursor-color", x_set_cursor_color
,
780 "cursor-type", x_set_cursor_type
,
782 "foreground-color", x_set_foreground_color
,
783 "icon-name", x_set_icon_name
,
784 "icon-type", x_set_icon_type
,
785 "internal-border-width", x_set_internal_border_width
,
786 "menu-bar-lines", x_set_menu_bar_lines
,
787 "mouse-color", x_set_mouse_color
,
788 "name", x_explicitly_set_name
,
789 "scroll-bar-width", x_set_scroll_bar_width
,
790 "title", x_set_title
,
791 "unsplittable", x_set_unsplittable
,
792 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
793 "visibility", x_set_visibility
,
794 "toolbar-lines", x_set_toolbar_lines
,
795 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
796 "scroll-bar-background", x_set_scroll_bar_background
,
799 /* Attach the `x-frame-parameter' properties to
800 the Lisp symbol names of parameters relevant to X. */
803 init_x_parm_symbols ()
807 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
808 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
812 /* Change the parameters of frame F as specified by ALIST.
813 If a parameter is not specially recognized, do nothing;
814 otherwise call the `x_set_...' function for that parameter. */
817 x_set_frame_parameters (f
, alist
)
823 /* If both of these parameters are present, it's more efficient to
824 set them both at once. So we wait until we've looked at the
825 entire list before we set them. */
829 Lisp_Object left
, top
;
831 /* Same with these. */
832 Lisp_Object icon_left
, icon_top
;
834 /* Record in these vectors all the parms specified. */
838 int left_no_change
= 0, top_no_change
= 0;
839 int icon_left_no_change
= 0, icon_top_no_change
= 0;
841 struct gcpro gcpro1
, gcpro2
;
844 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
847 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
848 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
850 /* Extract parm names and values into those vectors. */
853 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
858 parms
[i
] = Fcar (elt
);
859 values
[i
] = Fcdr (elt
);
862 /* TAIL and ALIST are not used again below here. */
865 GCPRO2 (*parms
, *values
);
869 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
870 because their values appear in VALUES and strings are not valid. */
871 top
= left
= Qunbound
;
872 icon_left
= icon_top
= Qunbound
;
874 /* Provide default values for HEIGHT and WIDTH. */
875 if (FRAME_NEW_WIDTH (f
))
876 width
= FRAME_NEW_WIDTH (f
);
878 width
= FRAME_WIDTH (f
);
880 if (FRAME_NEW_HEIGHT (f
))
881 height
= FRAME_NEW_HEIGHT (f
);
883 height
= FRAME_HEIGHT (f
);
885 /* Process foreground_color and background_color before anything else.
886 They are independent of other properties, but other properties (e.g.,
887 cursor_color) are dependent upon them. */
888 for (p
= 0; p
< i
; p
++)
890 Lisp_Object prop
, val
;
894 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
896 register Lisp_Object param_index
, old_value
;
898 param_index
= Fget (prop
, Qx_frame_parameter
);
899 old_value
= get_frame_param (f
, prop
);
900 store_frame_param (f
, prop
, val
);
901 if (NATNUMP (param_index
)
902 && (XFASTINT (param_index
)
903 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
904 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
908 /* Now process them in reverse of specified order. */
909 for (i
--; i
>= 0; i
--)
911 Lisp_Object prop
, val
;
916 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
917 width
= XFASTINT (val
);
918 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
919 height
= XFASTINT (val
);
920 else if (EQ (prop
, Qtop
))
922 else if (EQ (prop
, Qleft
))
924 else if (EQ (prop
, Qicon_top
))
926 else if (EQ (prop
, Qicon_left
))
928 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
929 /* Processed above. */
933 register Lisp_Object param_index
, old_value
;
935 param_index
= Fget (prop
, Qx_frame_parameter
);
936 old_value
= get_frame_param (f
, prop
);
937 store_frame_param (f
, prop
, val
);
938 if (NATNUMP (param_index
)
939 && (XFASTINT (param_index
)
940 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
941 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
945 /* Don't die if just one of these was set. */
946 if (EQ (left
, Qunbound
))
949 if (f
->output_data
.x
->left_pos
< 0)
950 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
952 XSETINT (left
, f
->output_data
.x
->left_pos
);
954 if (EQ (top
, Qunbound
))
957 if (f
->output_data
.x
->top_pos
< 0)
958 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
960 XSETINT (top
, f
->output_data
.x
->top_pos
);
963 /* If one of the icon positions was not set, preserve or default it. */
964 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
966 icon_left_no_change
= 1;
967 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
968 if (NILP (icon_left
))
969 XSETINT (icon_left
, 0);
971 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
973 icon_top_no_change
= 1;
974 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
976 XSETINT (icon_top
, 0);
979 /* Don't set these parameters unless they've been explicitly
980 specified. The window might be mapped or resized while we're in
981 this function, and we don't want to override that unless the lisp
982 code has asked for it.
984 Don't set these parameters unless they actually differ from the
985 window's current parameters; the window may not actually exist
990 check_frame_size (f
, &height
, &width
);
992 XSETFRAME (frame
, f
);
994 if (width
!= FRAME_WIDTH (f
)
995 || height
!= FRAME_HEIGHT (f
)
996 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
997 Fset_frame_size (frame
, make_number (width
), make_number (height
));
999 if ((!NILP (left
) || !NILP (top
))
1000 && ! (left_no_change
&& top_no_change
)
1001 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1002 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1007 /* Record the signs. */
1008 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1009 if (EQ (left
, Qminus
))
1010 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1011 else if (INTEGERP (left
))
1013 leftpos
= XINT (left
);
1015 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1017 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
1018 && CONSP (XCONS (left
)->cdr
)
1019 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
1021 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
1022 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1024 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
1025 && CONSP (XCONS (left
)->cdr
)
1026 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
1028 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
1031 if (EQ (top
, Qminus
))
1032 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1033 else if (INTEGERP (top
))
1035 toppos
= XINT (top
);
1037 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1039 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
1040 && CONSP (XCONS (top
)->cdr
)
1041 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
1043 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
1044 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1046 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
1047 && CONSP (XCONS (top
)->cdr
)
1048 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
1050 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
1054 /* Store the numeric value of the position. */
1055 f
->output_data
.x
->top_pos
= toppos
;
1056 f
->output_data
.x
->left_pos
= leftpos
;
1058 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1060 /* Actually set that position, and convert to absolute. */
1061 x_set_offset (f
, leftpos
, toppos
, -1);
1064 if ((!NILP (icon_left
) || !NILP (icon_top
))
1065 && ! (icon_left_no_change
&& icon_top_no_change
))
1066 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1072 /* Store the screen positions of frame F into XPTR and YPTR.
1073 These are the positions of the containing window manager window,
1074 not Emacs's own window. */
1077 x_real_positions (f
, xptr
, yptr
)
1084 /* This is pretty gross, but seems to be the easiest way out of
1085 the problem that arises when restarting window-managers. */
1087 #ifdef USE_X_TOOLKIT
1088 Window outer
= (f
->output_data
.x
->widget
1089 ? XtWindow (f
->output_data
.x
->widget
)
1090 : FRAME_X_WINDOW (f
));
1092 Window outer
= f
->output_data
.x
->window_desc
;
1094 Window tmp_root_window
;
1095 Window
*tmp_children
;
1100 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1101 Window outer_window
;
1103 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1104 &f
->output_data
.x
->parent_desc
,
1105 &tmp_children
, &tmp_nchildren
);
1106 XFree ((char *) tmp_children
);
1110 /* Find the position of the outside upper-left corner of
1111 the inner window, with respect to the outer window. */
1112 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1113 outer_window
= f
->output_data
.x
->parent_desc
;
1115 outer_window
= outer
;
1117 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1119 /* From-window, to-window. */
1121 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1123 /* From-position, to-position. */
1124 0, 0, &win_x
, &win_y
,
1129 /* It is possible for the window returned by the XQueryNotify
1130 to become invalid by the time we call XTranslateCoordinates.
1131 That can happen when you restart some window managers.
1132 If so, we get an error in XTranslateCoordinates.
1133 Detect that and try the whole thing over. */
1134 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1136 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1140 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1147 /* Insert a description of internally-recorded parameters of frame X
1148 into the parameter alist *ALISTPTR that is to be given to the user.
1149 Only parameters that are specific to the X window system
1150 and whose values are not correctly recorded in the frame's
1151 param_alist need to be considered here. */
1154 x_report_frame_params (f
, alistptr
)
1156 Lisp_Object
*alistptr
;
1161 /* Represent negative positions (off the top or left screen edge)
1162 in a way that Fmodify_frame_parameters will understand correctly. */
1163 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1164 if (f
->output_data
.x
->left_pos
>= 0)
1165 store_in_alist (alistptr
, Qleft
, tem
);
1167 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1169 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1170 if (f
->output_data
.x
->top_pos
>= 0)
1171 store_in_alist (alistptr
, Qtop
, tem
);
1173 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1175 store_in_alist (alistptr
, Qborder_width
,
1176 make_number (f
->output_data
.x
->border_width
));
1177 store_in_alist (alistptr
, Qinternal_border_width
,
1178 make_number (f
->output_data
.x
->internal_border_width
));
1179 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1180 store_in_alist (alistptr
, Qwindow_id
,
1181 build_string (buf
));
1182 #ifdef USE_X_TOOLKIT
1183 /* Tooltip frame may not have this widget. */
1184 if (f
->output_data
.x
->widget
)
1186 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1187 store_in_alist (alistptr
, Qouter_window_id
,
1188 build_string (buf
));
1189 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1190 FRAME_SAMPLE_VISIBILITY (f
);
1191 store_in_alist (alistptr
, Qvisibility
,
1192 (FRAME_VISIBLE_P (f
) ? Qt
1193 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1194 store_in_alist (alistptr
, Qdisplay
,
1195 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->car
);
1197 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1200 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1201 store_in_alist (alistptr
, Qparent_id
, tem
);
1205 /* Decide if color named COLOR is valid for the display associated with
1206 the selected frame; if so, return the rgb values in COLOR_DEF.
1207 If ALLOC is nonzero, allocate a new colormap cell. */
1210 defined_color (f
, color
, color_def
, alloc
)
1216 register int status
;
1217 Colormap screen_colormap
;
1218 Display
*display
= FRAME_X_DISPLAY (f
);
1221 screen_colormap
= DefaultColormap (display
, XDefaultScreen (display
));
1223 status
= XParseColor (display
, screen_colormap
, color
, color_def
);
1224 if (status
&& alloc
)
1226 status
= XAllocColor (display
, screen_colormap
, color_def
);
1229 /* If we got to this point, the colormap is full, so we're
1230 going to try and get the next closest color.
1231 The algorithm used is a least-squares matching, which is
1232 what X uses for closest color matching with StaticColor visuals. */
1237 long nearest_delta
, trial_delta
;
1240 no_cells
= XDisplayCells (display
, XDefaultScreen (display
));
1241 cells
= (XColor
*) alloca (sizeof (XColor
) * no_cells
);
1243 for (x
= 0; x
< no_cells
; x
++)
1246 XQueryColors (display
, screen_colormap
, cells
, no_cells
);
1248 /* I'm assuming CSE so I'm not going to condense this. */
1249 nearest_delta
= ((((color_def
->red
>> 8) - (cells
[0].red
>> 8))
1250 * ((color_def
->red
>> 8) - (cells
[0].red
>> 8)))
1252 (((color_def
->green
>> 8) - (cells
[0].green
>> 8))
1253 * ((color_def
->green
>> 8) - (cells
[0].green
>> 8)))
1255 (((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))
1256 * ((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))));
1257 for (x
= 1; x
< no_cells
; x
++)
1259 trial_delta
= ((((color_def
->red
>> 8) - (cells
[x
].red
>> 8))
1260 * ((color_def
->red
>> 8) - (cells
[x
].red
>> 8)))
1262 (((color_def
->green
>> 8) - (cells
[x
].green
>> 8))
1263 * ((color_def
->green
>> 8) - (cells
[x
].green
>> 8)))
1265 (((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))
1266 * ((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))));
1267 if (trial_delta
< nearest_delta
)
1270 temp
.red
= cells
[x
].red
;
1271 temp
.green
= cells
[x
].green
;
1272 temp
.blue
= cells
[x
].blue
;
1273 status
= XAllocColor (display
, screen_colormap
, &temp
);
1277 nearest_delta
= trial_delta
;
1281 color_def
->red
= cells
[nearest
].red
;
1282 color_def
->green
= cells
[nearest
].green
;
1283 color_def
->blue
= cells
[nearest
].blue
;
1284 status
= XAllocColor (display
, screen_colormap
, color_def
);
1295 /* Given a string ARG naming a color, compute a pixel value from it
1296 suitable for screen F.
1297 If F is not a color screen, return DEF (default) regardless of what
1301 x_decode_color (f
, arg
, def
)
1308 CHECK_STRING (arg
, 0);
1310 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1311 return BLACK_PIX_DEFAULT (f
);
1312 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1313 return WHITE_PIX_DEFAULT (f
);
1315 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1318 /* defined_color is responsible for coping with failures
1319 by looking for a near-miss. */
1320 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1323 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
1324 Fcons (arg
, Qnil
)));
1327 /* Functions called only from `x_set_frame_param'
1328 to set individual parameters.
1330 If FRAME_X_WINDOW (f) is 0,
1331 the frame is being created and its X-window does not exist yet.
1332 In that case, just record the parameter's new value
1333 in the standard place; do not attempt to change the window. */
1336 x_set_foreground_color (f
, arg
, oldval
)
1338 Lisp_Object arg
, oldval
;
1341 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1343 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
1344 f
->output_data
.x
->foreground_pixel
= pixel
;
1346 if (FRAME_X_WINDOW (f
) != 0)
1349 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1350 f
->output_data
.x
->foreground_pixel
);
1351 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1352 f
->output_data
.x
->foreground_pixel
);
1354 recompute_basic_faces (f
);
1355 if (FRAME_VISIBLE_P (f
))
1361 x_set_background_color (f
, arg
, oldval
)
1363 Lisp_Object arg
, oldval
;
1369 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1371 unload_color (f
, f
->output_data
.x
->background_pixel
);
1372 f
->output_data
.x
->background_pixel
= pixel
;
1374 if (FRAME_X_WINDOW (f
) != 0)
1377 /* The main frame area. */
1378 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1379 f
->output_data
.x
->background_pixel
);
1380 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1381 f
->output_data
.x
->background_pixel
);
1382 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1383 f
->output_data
.x
->background_pixel
);
1384 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1385 f
->output_data
.x
->background_pixel
);
1388 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1389 bar
= XSCROLL_BAR (bar
)->next
)
1390 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1391 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1392 f
->output_data
.x
->background_pixel
);
1396 recompute_basic_faces (f
);
1398 if (FRAME_VISIBLE_P (f
))
1404 x_set_mouse_color (f
, arg
, oldval
)
1406 Lisp_Object arg
, oldval
;
1408 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1411 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1412 unsigned long mask_color
= f
->output_data
.x
->background_pixel
;
1414 /* Don't let pointers be invisible. */
1415 if (mask_color
== pixel
1416 && mask_color
== f
->output_data
.x
->background_pixel
)
1417 pixel
= f
->output_data
.x
->foreground_pixel
;
1419 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
1420 f
->output_data
.x
->mouse_pixel
= pixel
;
1424 /* It's not okay to crash if the user selects a screwy cursor. */
1425 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1427 if (!EQ (Qnil
, Vx_pointer_shape
))
1429 CHECK_NUMBER (Vx_pointer_shape
, 0);
1430 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1433 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1434 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1436 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1438 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1439 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1440 XINT (Vx_nontext_pointer_shape
));
1443 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1444 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1446 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
1448 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
1449 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1450 XINT (Vx_busy_pointer_shape
));
1453 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_watch
);
1454 x_check_errors (FRAME_X_DISPLAY (f
), "bad busy pointer cursor: %s");
1456 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1457 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1459 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1460 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1461 XINT (Vx_mode_pointer_shape
));
1464 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1465 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1467 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1469 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1471 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1472 XINT (Vx_sensitive_text_pointer_shape
));
1475 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1477 /* Check and report errors with the above calls. */
1478 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1479 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1482 XColor fore_color
, back_color
;
1484 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1485 back_color
.pixel
= mask_color
;
1486 XQueryColor (FRAME_X_DISPLAY (f
),
1487 DefaultColormap (FRAME_X_DISPLAY (f
),
1488 DefaultScreen (FRAME_X_DISPLAY (f
))),
1490 XQueryColor (FRAME_X_DISPLAY (f
),
1491 DefaultColormap (FRAME_X_DISPLAY (f
),
1492 DefaultScreen (FRAME_X_DISPLAY (f
))),
1494 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1495 &fore_color
, &back_color
);
1496 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1497 &fore_color
, &back_color
);
1498 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1499 &fore_color
, &back_color
);
1500 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1501 &fore_color
, &back_color
);
1502 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1503 &fore_color
, &back_color
);
1506 if (FRAME_X_WINDOW (f
) != 0)
1507 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1509 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1510 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1511 f
->output_data
.x
->text_cursor
= cursor
;
1513 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1514 && f
->output_data
.x
->nontext_cursor
!= 0)
1515 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1516 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1518 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1519 && f
->output_data
.x
->busy_cursor
!= 0)
1520 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1521 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1523 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1524 && f
->output_data
.x
->modeline_cursor
!= 0)
1525 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1526 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1528 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1529 && f
->output_data
.x
->cross_cursor
!= 0)
1530 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1531 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1533 XFlush (FRAME_X_DISPLAY (f
));
1538 x_set_cursor_color (f
, arg
, oldval
)
1540 Lisp_Object arg
, oldval
;
1542 unsigned long fore_pixel
, pixel
;
1544 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1545 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1546 WHITE_PIX_DEFAULT (f
));
1548 fore_pixel
= f
->output_data
.x
->background_pixel
;
1549 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1551 /* Make sure that the cursor color differs from the background color. */
1552 if (pixel
== f
->output_data
.x
->background_pixel
)
1554 pixel
= f
->output_data
.x
->mouse_pixel
;
1555 if (pixel
== fore_pixel
)
1556 fore_pixel
= f
->output_data
.x
->background_pixel
;
1559 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1560 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1562 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1563 f
->output_data
.x
->cursor_pixel
= pixel
;
1565 if (FRAME_X_WINDOW (f
) != 0)
1568 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1569 f
->output_data
.x
->cursor_pixel
);
1570 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1574 if (FRAME_VISIBLE_P (f
))
1576 x_update_cursor (f
, 0);
1577 x_update_cursor (f
, 1);
1582 /* Set the border-color of frame F to value described by ARG.
1583 ARG can be a string naming a color.
1584 The border-color is used for the border that is drawn by the X server.
1585 Note that this does not fully take effect if done before
1586 F has an x-window; it must be redone when the window is created.
1588 Note: this is done in two routines because of the way X10 works.
1590 Note: under X11, this is normally the province of the window manager,
1591 and so emacs' border colors may be overridden. */
1594 x_set_border_color (f
, arg
, oldval
)
1596 Lisp_Object arg
, oldval
;
1601 CHECK_STRING (arg
, 0);
1602 str
= XSTRING (arg
)->data
;
1604 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1606 x_set_border_pixel (f
, pix
);
1609 /* Set the border-color of frame F to pixel value PIX.
1610 Note that this does not fully take effect if done before
1611 F has an x-window. */
1614 x_set_border_pixel (f
, pix
)
1618 unload_color (f
, f
->output_data
.x
->border_pixel
);
1619 f
->output_data
.x
->border_pixel
= pix
;
1621 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1627 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1628 (unsigned long)pix
);
1631 if (FRAME_VISIBLE_P (f
))
1637 x_set_cursor_type (f
, arg
, oldval
)
1639 Lisp_Object arg
, oldval
;
1643 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1644 f
->output_data
.x
->cursor_width
= 2;
1646 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
1647 && INTEGERP (XCONS (arg
)->cdr
))
1649 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1650 f
->output_data
.x
->cursor_width
= XINT (XCONS (arg
)->cdr
);
1653 /* Treat anything unknown as "box cursor".
1654 It was bad to signal an error; people have trouble fixing
1655 .Xdefaults with Emacs, when it has something bad in it. */
1656 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
1658 /* Make sure the cursor gets redrawn. This is overkill, but how
1659 often do people change cursor types? */
1660 update_mode_lines
++;
1664 x_set_icon_type (f
, arg
, oldval
)
1666 Lisp_Object arg
, oldval
;
1672 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1675 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1680 result
= x_text_icon (f
,
1681 (char *) XSTRING ((!NILP (f
->icon_name
)
1685 result
= x_bitmap_icon (f
, arg
);
1690 error ("No icon window available");
1693 XFlush (FRAME_X_DISPLAY (f
));
1697 /* Return non-nil if frame F wants a bitmap icon. */
1705 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1707 return XCONS (tem
)->cdr
;
1713 x_set_icon_name (f
, arg
, oldval
)
1715 Lisp_Object arg
, oldval
;
1721 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1724 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1729 if (f
->output_data
.x
->icon_bitmap
!= 0)
1734 result
= x_text_icon (f
,
1735 (char *) XSTRING ((!NILP (f
->icon_name
)
1744 error ("No icon window available");
1747 XFlush (FRAME_X_DISPLAY (f
));
1752 x_set_font (f
, arg
, oldval
)
1754 Lisp_Object arg
, oldval
;
1757 Lisp_Object fontset_name
;
1760 CHECK_STRING (arg
, 1);
1762 fontset_name
= Fquery_fontset (arg
, Qnil
);
1765 result
= (STRINGP (fontset_name
)
1766 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1767 : x_new_font (f
, XSTRING (arg
)->data
));
1770 if (EQ (result
, Qnil
))
1771 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1772 else if (EQ (result
, Qt
))
1773 error ("The characters of the given font have varying widths");
1774 else if (STRINGP (result
))
1776 store_frame_param (f
, Qfont
, result
);
1777 recompute_basic_faces (f
);
1782 do_pending_window_change ();
1784 /* Don't call `face-set-after-frame-default' when faces haven't been
1785 initialized yet. This is the case when called from
1786 Fx_create_frame. In that case, the X widget or window doesn't
1787 exist either, and we can end up in x_report_frame_params with a
1788 null widget which gives a segfault. */
1789 if (FRAME_FACE_CACHE (f
))
1791 XSETFRAME (frame
, f
);
1792 call1 (Qface_set_after_frame_default
, frame
);
1797 x_set_border_width (f
, arg
, oldval
)
1799 Lisp_Object arg
, oldval
;
1801 CHECK_NUMBER (arg
, 0);
1803 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1806 if (FRAME_X_WINDOW (f
) != 0)
1807 error ("Cannot change the border width of a window");
1809 f
->output_data
.x
->border_width
= XINT (arg
);
1813 x_set_internal_border_width (f
, arg
, oldval
)
1815 Lisp_Object arg
, oldval
;
1817 int old
= f
->output_data
.x
->internal_border_width
;
1819 CHECK_NUMBER (arg
, 0);
1820 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1821 if (f
->output_data
.x
->internal_border_width
< 0)
1822 f
->output_data
.x
->internal_border_width
= 0;
1824 #ifdef USE_X_TOOLKIT
1825 if (f
->output_data
.x
->edit_widget
)
1826 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1829 if (f
->output_data
.x
->internal_border_width
== old
)
1832 if (FRAME_X_WINDOW (f
) != 0)
1834 x_set_window_size (f
, 0, f
->width
, f
->height
);
1835 SET_FRAME_GARBAGED (f
);
1836 do_pending_window_change ();
1841 x_set_visibility (f
, value
, oldval
)
1843 Lisp_Object value
, oldval
;
1846 XSETFRAME (frame
, f
);
1849 Fmake_frame_invisible (frame
, Qt
);
1850 else if (EQ (value
, Qicon
))
1851 Ficonify_frame (frame
);
1853 Fmake_frame_visible (frame
);
1857 x_set_menu_bar_lines_1 (window
, n
)
1861 struct window
*w
= XWINDOW (window
);
1863 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1864 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1866 /* Handle just the top child in a vertical split. */
1867 if (!NILP (w
->vchild
))
1868 x_set_menu_bar_lines_1 (w
->vchild
, n
);
1870 /* Adjust all children in a horizontal split. */
1871 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1873 w
= XWINDOW (window
);
1874 x_set_menu_bar_lines_1 (window
, n
);
1879 x_set_menu_bar_lines (f
, value
, oldval
)
1881 Lisp_Object value
, oldval
;
1884 int olines
= FRAME_MENU_BAR_LINES (f
);
1886 /* Right now, menu bars don't work properly in minibuf-only frames;
1887 most of the commands try to apply themselves to the minibuffer
1888 frame itself, and get an error because you can't switch buffers
1889 in or split the minibuffer window. */
1890 if (FRAME_MINIBUF_ONLY_P (f
))
1893 if (INTEGERP (value
))
1894 nlines
= XINT (value
);
1898 /* Make sure we redisplay all windows in this frame. */
1899 windows_or_buffers_changed
++;
1901 #ifdef USE_X_TOOLKIT
1902 FRAME_MENU_BAR_LINES (f
) = 0;
1905 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1906 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1907 /* Make sure next redisplay shows the menu bar. */
1908 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1912 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1913 free_frame_menubar (f
);
1914 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1916 f
->output_data
.x
->menubar_widget
= 0;
1918 #else /* not USE_X_TOOLKIT */
1919 FRAME_MENU_BAR_LINES (f
) = nlines
;
1920 x_set_menu_bar_lines_1 (f
->root_window
, nlines
- olines
);
1921 #endif /* not USE_X_TOOLKIT */
1926 /* Set the number of lines used for the tool bar of frame F to VALUE.
1927 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1928 is the old number of tool bar lines. This function changes the
1929 height of all windows on frame F to match the new tool bar height.
1930 The frame's height doesn't change. */
1933 x_set_toolbar_lines (f
, value
, oldval
)
1935 Lisp_Object value
, oldval
;
1939 /* Use VALUE only if an integer >= 0. */
1940 if (INTEGERP (value
) && XINT (value
) >= 0)
1941 nlines
= XFASTINT (value
);
1945 /* Make sure we redisplay all windows in this frame. */
1946 ++windows_or_buffers_changed
;
1948 delta
= nlines
- FRAME_TOOLBAR_LINES (f
);
1949 FRAME_TOOLBAR_LINES (f
) = nlines
;
1950 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f
), delta
);
1955 /* Set the foreground color for scroll bars on frame F to VALUE.
1956 VALUE should be a string, a color name. If it isn't a string or
1957 isn't a valid color name, do nothing. OLDVAL is the old value of
1958 the frame parameter. */
1961 x_set_scroll_bar_foreground (f
, value
, oldval
)
1963 Lisp_Object value
, oldval
;
1965 unsigned long pixel
;
1967 if (STRINGP (value
))
1968 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
1972 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
1973 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
1975 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
1976 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
1978 /* Remove all scroll bars because they have wrong colors. */
1979 if (condemn_scroll_bars_hook
)
1980 (*condemn_scroll_bars_hook
) (f
);
1981 if (judge_scroll_bars_hook
)
1982 (*judge_scroll_bars_hook
) (f
);
1989 /* Set the background color for scroll bars on frame F to VALUE VALUE
1990 should be a string, a color name. If it isn't a string or isn't a
1991 valid color name, do nothing. OLDVAL is the old value of the frame
1995 x_set_scroll_bar_background (f
, value
, oldval
)
1997 Lisp_Object value
, oldval
;
1999 unsigned long pixel
;
2001 if (STRINGP (value
))
2002 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2006 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2007 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2009 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2010 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2012 /* Remove all scroll bars because they have wrong colors. */
2013 if (condemn_scroll_bars_hook
)
2014 (*condemn_scroll_bars_hook
) (f
);
2015 if (judge_scroll_bars_hook
)
2016 (*judge_scroll_bars_hook
) (f
);
2023 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2026 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2027 name; if NAME is a string, set F's name to NAME and set
2028 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2030 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2031 suggesting a new name, which lisp code should override; if
2032 F->explicit_name is set, ignore the new name; otherwise, set it. */
2035 x_set_name (f
, name
, explicit)
2040 /* Make sure that requests from lisp code override requests from
2041 Emacs redisplay code. */
2044 /* If we're switching from explicit to implicit, we had better
2045 update the mode lines and thereby update the title. */
2046 if (f
->explicit_name
&& NILP (name
))
2047 update_mode_lines
= 1;
2049 f
->explicit_name
= ! NILP (name
);
2051 else if (f
->explicit_name
)
2054 /* If NAME is nil, set the name to the x_id_name. */
2057 /* Check for no change needed in this very common case
2058 before we do any consing. */
2059 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2060 XSTRING (f
->name
)->data
))
2062 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2065 CHECK_STRING (name
, 0);
2067 /* Don't change the name if it's already NAME. */
2068 if (! NILP (Fstring_equal (name
, f
->name
)))
2073 /* For setting the frame title, the title parameter should override
2074 the name parameter. */
2075 if (! NILP (f
->title
))
2078 if (FRAME_X_WINDOW (f
))
2083 XTextProperty text
, icon
;
2084 Lisp_Object icon_name
;
2086 text
.value
= XSTRING (name
)->data
;
2087 text
.encoding
= XA_STRING
;
2089 text
.nitems
= STRING_BYTES (XSTRING (name
));
2091 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2093 icon
.value
= XSTRING (icon_name
)->data
;
2094 icon
.encoding
= XA_STRING
;
2096 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2097 #ifdef USE_X_TOOLKIT
2098 XSetWMName (FRAME_X_DISPLAY (f
),
2099 XtWindow (f
->output_data
.x
->widget
), &text
);
2100 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2102 #else /* not USE_X_TOOLKIT */
2103 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2104 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2105 #endif /* not USE_X_TOOLKIT */
2107 #else /* not HAVE_X11R4 */
2108 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2109 XSTRING (name
)->data
);
2110 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2111 XSTRING (name
)->data
);
2112 #endif /* not HAVE_X11R4 */
2117 /* This function should be called when the user's lisp code has
2118 specified a name for the frame; the name will override any set by the
2121 x_explicitly_set_name (f
, arg
, oldval
)
2123 Lisp_Object arg
, oldval
;
2125 x_set_name (f
, arg
, 1);
2128 /* This function should be called by Emacs redisplay code to set the
2129 name; names set this way will never override names set by the user's
2132 x_implicitly_set_name (f
, arg
, oldval
)
2134 Lisp_Object arg
, oldval
;
2136 x_set_name (f
, arg
, 0);
2139 /* Change the title of frame F to NAME.
2140 If NAME is nil, use the frame name as the title.
2142 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2143 name; if NAME is a string, set F's name to NAME and set
2144 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2146 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2147 suggesting a new name, which lisp code should override; if
2148 F->explicit_name is set, ignore the new name; otherwise, set it. */
2151 x_set_title (f
, name
)
2155 /* Don't change the title if it's already NAME. */
2156 if (EQ (name
, f
->title
))
2159 update_mode_lines
= 1;
2166 CHECK_STRING (name
, 0);
2168 if (FRAME_X_WINDOW (f
))
2173 XTextProperty text
, icon
;
2174 Lisp_Object icon_name
;
2176 text
.value
= XSTRING (name
)->data
;
2177 text
.encoding
= XA_STRING
;
2179 text
.nitems
= STRING_BYTES (XSTRING (name
));
2181 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2183 icon
.value
= XSTRING (icon_name
)->data
;
2184 icon
.encoding
= XA_STRING
;
2186 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2187 #ifdef USE_X_TOOLKIT
2188 XSetWMName (FRAME_X_DISPLAY (f
),
2189 XtWindow (f
->output_data
.x
->widget
), &text
);
2190 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2192 #else /* not USE_X_TOOLKIT */
2193 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2194 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2195 #endif /* not USE_X_TOOLKIT */
2197 #else /* not HAVE_X11R4 */
2198 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2199 XSTRING (name
)->data
);
2200 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2201 XSTRING (name
)->data
);
2202 #endif /* not HAVE_X11R4 */
2208 x_set_autoraise (f
, arg
, oldval
)
2210 Lisp_Object arg
, oldval
;
2212 f
->auto_raise
= !EQ (Qnil
, arg
);
2216 x_set_autolower (f
, arg
, oldval
)
2218 Lisp_Object arg
, oldval
;
2220 f
->auto_lower
= !EQ (Qnil
, arg
);
2224 x_set_unsplittable (f
, arg
, oldval
)
2226 Lisp_Object arg
, oldval
;
2228 f
->no_split
= !NILP (arg
);
2232 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2234 Lisp_Object arg
, oldval
;
2236 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2237 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2238 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2239 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2241 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2243 ? vertical_scroll_bar_none
2245 ? vertical_scroll_bar_right
2246 : vertical_scroll_bar_left
);
2248 /* We set this parameter before creating the X window for the
2249 frame, so we can get the geometry right from the start.
2250 However, if the window hasn't been created yet, we shouldn't
2251 call x_set_window_size. */
2252 if (FRAME_X_WINDOW (f
))
2253 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2254 do_pending_window_change ();
2259 x_set_scroll_bar_width (f
, arg
, oldval
)
2261 Lisp_Object arg
, oldval
;
2263 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2267 #ifdef USE_X_TOOLKIT
2268 /* A too wide or narrow toolkit scroll bar doesn't look good. */
2269 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2270 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2271 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2273 /* Make the actual width at least 14 pixels and a multiple of a
2275 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2277 /* Use all of that space (aside from required margins) for the
2279 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2282 if (FRAME_X_WINDOW (f
))
2283 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2284 do_pending_window_change ();
2286 else if (INTEGERP (arg
) && XINT (arg
) > 0
2287 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2289 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2290 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2292 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2293 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2294 if (FRAME_X_WINDOW (f
))
2295 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2298 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0);
2299 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2300 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2305 /* Subroutines of creating an X frame. */
2307 /* Make sure that Vx_resource_name is set to a reasonable value.
2308 Fix it up, or set it to `emacs' if it is too hopeless. */
2311 validate_x_resource_name ()
2314 /* Number of valid characters in the resource name. */
2316 /* Number of invalid characters in the resource name. */
2321 if (!STRINGP (Vx_resource_class
))
2322 Vx_resource_class
= build_string (EMACS_CLASS
);
2324 if (STRINGP (Vx_resource_name
))
2326 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2329 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2331 /* Only letters, digits, - and _ are valid in resource names.
2332 Count the valid characters and count the invalid ones. */
2333 for (i
= 0; i
< len
; i
++)
2336 if (! ((c
>= 'a' && c
<= 'z')
2337 || (c
>= 'A' && c
<= 'Z')
2338 || (c
>= '0' && c
<= '9')
2339 || c
== '-' || c
== '_'))
2346 /* Not a string => completely invalid. */
2347 bad_count
= 5, good_count
= 0;
2349 /* If name is valid already, return. */
2353 /* If name is entirely invalid, or nearly so, use `emacs'. */
2355 || (good_count
== 1 && bad_count
> 0))
2357 Vx_resource_name
= build_string ("emacs");
2361 /* Name is partly valid. Copy it and replace the invalid characters
2362 with underscores. */
2364 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2366 for (i
= 0; i
< len
; i
++)
2368 int c
= XSTRING (new)->data
[i
];
2369 if (! ((c
>= 'a' && c
<= 'z')
2370 || (c
>= 'A' && c
<= 'Z')
2371 || (c
>= '0' && c
<= '9')
2372 || c
== '-' || c
== '_'))
2373 XSTRING (new)->data
[i
] = '_';
2378 extern char *x_get_string_resource ();
2380 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2381 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2382 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2383 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2384 the name specified by the `-name' or `-rn' command-line arguments.\n\
2386 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2387 class, respectively. You must specify both of them or neither.\n\
2388 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2389 and the class is `Emacs.CLASS.SUBCLASS'.")
2390 (attribute
, class, component
, subclass
)
2391 Lisp_Object attribute
, class, component
, subclass
;
2393 register char *value
;
2399 CHECK_STRING (attribute
, 0);
2400 CHECK_STRING (class, 0);
2402 if (!NILP (component
))
2403 CHECK_STRING (component
, 1);
2404 if (!NILP (subclass
))
2405 CHECK_STRING (subclass
, 2);
2406 if (NILP (component
) != NILP (subclass
))
2407 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2409 validate_x_resource_name ();
2411 /* Allocate space for the components, the dots which separate them,
2412 and the final '\0'. Make them big enough for the worst case. */
2413 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2414 + (STRINGP (component
)
2415 ? STRING_BYTES (XSTRING (component
)) : 0)
2416 + STRING_BYTES (XSTRING (attribute
))
2419 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2420 + STRING_BYTES (XSTRING (class))
2421 + (STRINGP (subclass
)
2422 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2425 /* Start with emacs.FRAMENAME for the name (the specific one)
2426 and with `Emacs' for the class key (the general one). */
2427 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2428 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2430 strcat (class_key
, ".");
2431 strcat (class_key
, XSTRING (class)->data
);
2433 if (!NILP (component
))
2435 strcat (class_key
, ".");
2436 strcat (class_key
, XSTRING (subclass
)->data
);
2438 strcat (name_key
, ".");
2439 strcat (name_key
, XSTRING (component
)->data
);
2442 strcat (name_key
, ".");
2443 strcat (name_key
, XSTRING (attribute
)->data
);
2445 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2446 name_key
, class_key
);
2448 if (value
!= (char *) 0)
2449 return build_string (value
);
2454 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2457 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2458 struct x_display_info
*dpyinfo
;
2459 Lisp_Object attribute
, class, component
, subclass
;
2461 register char *value
;
2467 CHECK_STRING (attribute
, 0);
2468 CHECK_STRING (class, 0);
2470 if (!NILP (component
))
2471 CHECK_STRING (component
, 1);
2472 if (!NILP (subclass
))
2473 CHECK_STRING (subclass
, 2);
2474 if (NILP (component
) != NILP (subclass
))
2475 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2477 validate_x_resource_name ();
2479 /* Allocate space for the components, the dots which separate them,
2480 and the final '\0'. Make them big enough for the worst case. */
2481 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2482 + (STRINGP (component
)
2483 ? STRING_BYTES (XSTRING (component
)) : 0)
2484 + STRING_BYTES (XSTRING (attribute
))
2487 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2488 + STRING_BYTES (XSTRING (class))
2489 + (STRINGP (subclass
)
2490 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2493 /* Start with emacs.FRAMENAME for the name (the specific one)
2494 and with `Emacs' for the class key (the general one). */
2495 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2496 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2498 strcat (class_key
, ".");
2499 strcat (class_key
, XSTRING (class)->data
);
2501 if (!NILP (component
))
2503 strcat (class_key
, ".");
2504 strcat (class_key
, XSTRING (subclass
)->data
);
2506 strcat (name_key
, ".");
2507 strcat (name_key
, XSTRING (component
)->data
);
2510 strcat (name_key
, ".");
2511 strcat (name_key
, XSTRING (attribute
)->data
);
2513 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2515 if (value
!= (char *) 0)
2516 return build_string (value
);
2521 /* Used when C code wants a resource value. */
2524 x_get_resource_string (attribute
, class)
2525 char *attribute
, *class;
2530 /* Allocate space for the components, the dots which separate them,
2531 and the final '\0'. */
2532 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2533 + strlen (attribute
) + 2);
2534 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2535 + strlen (class) + 2);
2537 sprintf (name_key
, "%s.%s",
2538 XSTRING (Vinvocation_name
)->data
,
2540 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2542 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame
)->xrdb
,
2543 name_key
, class_key
);
2546 /* Types we might convert a resource string into. */
2555 /* Return the value of parameter PARAM.
2557 First search ALIST, then Vdefault_frame_alist, then the X defaults
2558 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2560 Convert the resource to the type specified by desired_type.
2562 If no default is specified, return Qunbound. If you call
2563 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2564 and don't let it get stored in any Lisp-visible variables! */
2567 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2568 struct x_display_info
*dpyinfo
;
2569 Lisp_Object alist
, param
;
2572 enum resource_types type
;
2574 register Lisp_Object tem
;
2576 tem
= Fassq (param
, alist
);
2578 tem
= Fassq (param
, Vdefault_frame_alist
);
2584 tem
= display_x_get_resource (dpyinfo
,
2585 build_string (attribute
),
2586 build_string (class),
2594 case RES_TYPE_NUMBER
:
2595 return make_number (atoi (XSTRING (tem
)->data
));
2597 case RES_TYPE_BOOLEAN
:
2598 tem
= Fdowncase (tem
);
2599 if (!strcmp (XSTRING (tem
)->data
, "on")
2600 || !strcmp (XSTRING (tem
)->data
, "true"))
2605 case RES_TYPE_STRING
:
2608 case RES_TYPE_SYMBOL
:
2609 /* As a special case, we map the values `true' and `on'
2610 to Qt, and `false' and `off' to Qnil. */
2613 lower
= Fdowncase (tem
);
2614 if (!strcmp (XSTRING (lower
)->data
, "on")
2615 || !strcmp (XSTRING (lower
)->data
, "true"))
2617 else if (!strcmp (XSTRING (lower
)->data
, "off")
2618 || !strcmp (XSTRING (lower
)->data
, "false"))
2621 return Fintern (tem
, Qnil
);
2634 /* Like x_get_arg, but also record the value in f->param_alist. */
2637 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2639 Lisp_Object alist
, param
;
2642 enum resource_types type
;
2646 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2647 attribute
, class, type
);
2649 store_frame_param (f
, param
, value
);
2654 /* Record in frame F the specified or default value according to ALIST
2655 of the parameter named PROP (a Lisp symbol).
2656 If no value is specified for PROP, look for an X default for XPROP
2657 on the frame named NAME.
2658 If that is not found either, use the value DEFLT. */
2661 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2668 enum resource_types type
;
2672 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2673 if (EQ (tem
, Qunbound
))
2675 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2680 /* Record in frame F the specified or default value according to ALIST
2681 of the parameter named PROP (a Lisp symbol). If no value is
2682 specified for PROP, look for an X default for XPROP on the frame
2683 named NAME. If that is not found either, use the value DEFLT. */
2686 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2695 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2698 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2699 if (EQ (tem
, Qunbound
))
2701 #ifdef USE_TOOLKIT_SCROLL_BARS
2703 /* See if an X resource for the scroll bar color has been
2705 tem
= display_x_get_resource (dpyinfo
,
2706 build_string (foreground_p
2710 build_string ("verticalScrollBar"),
2714 /* If nothing has been specified, scroll bars will use a
2715 toolkit-dependent default. Because these defaults are
2716 difficult to get at without actually creating a scroll
2717 bar, use nil to indicate that no color has been
2722 #else /* not USE_TOOLKIT_SCROLL_BARS */
2726 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2729 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2735 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2736 "Parse an X-style geometry string STRING.\n\
2737 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2738 The properties returned may include `top', `left', `height', and `width'.\n\
2739 The value of `left' or `top' may be an integer,\n\
2740 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2741 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2746 unsigned int width
, height
;
2749 CHECK_STRING (string
, 0);
2751 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2752 &x
, &y
, &width
, &height
);
2755 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2756 error ("Must specify both x and y position, or neither");
2760 if (geometry
& XValue
)
2762 Lisp_Object element
;
2764 if (x
>= 0 && (geometry
& XNegative
))
2765 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2766 else if (x
< 0 && ! (geometry
& XNegative
))
2767 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2769 element
= Fcons (Qleft
, make_number (x
));
2770 result
= Fcons (element
, result
);
2773 if (geometry
& YValue
)
2775 Lisp_Object element
;
2777 if (y
>= 0 && (geometry
& YNegative
))
2778 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2779 else if (y
< 0 && ! (geometry
& YNegative
))
2780 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2782 element
= Fcons (Qtop
, make_number (y
));
2783 result
= Fcons (element
, result
);
2786 if (geometry
& WidthValue
)
2787 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2788 if (geometry
& HeightValue
)
2789 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2794 /* Calculate the desired size and position of this window,
2795 and return the flags saying which aspects were specified.
2797 This function does not make the coordinates positive. */
2799 #define DEFAULT_ROWS 40
2800 #define DEFAULT_COLS 80
2803 x_figure_window_size (f
, parms
)
2807 register Lisp_Object tem0
, tem1
, tem2
;
2808 int height
, width
, left
, top
;
2809 register int geometry
;
2810 long window_prompting
= 0;
2811 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2813 /* Default values if we fall through.
2814 Actually, if that happens we should get
2815 window manager prompting. */
2816 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2817 f
->height
= DEFAULT_ROWS
;
2818 /* Window managers expect that if program-specified
2819 positions are not (0,0), they're intentional, not defaults. */
2820 f
->output_data
.x
->top_pos
= 0;
2821 f
->output_data
.x
->left_pos
= 0;
2823 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
2824 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
2825 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
2826 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2828 if (!EQ (tem0
, Qunbound
))
2830 CHECK_NUMBER (tem0
, 0);
2831 f
->height
= XINT (tem0
);
2833 if (!EQ (tem1
, Qunbound
))
2835 CHECK_NUMBER (tem1
, 0);
2836 SET_FRAME_WIDTH (f
, XINT (tem1
));
2838 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2839 window_prompting
|= USSize
;
2841 window_prompting
|= PSize
;
2844 f
->output_data
.x
->vertical_scroll_bar_extra
2845 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2847 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2848 f
->output_data
.x
->flags_areas_extra
2849 = 2 * FRAME_FLAGS_AREA_WIDTH (f
);
2850 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2851 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2853 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
2854 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
2855 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
2856 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2858 if (EQ (tem0
, Qminus
))
2860 f
->output_data
.x
->top_pos
= 0;
2861 window_prompting
|= YNegative
;
2863 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2864 && CONSP (XCONS (tem0
)->cdr
)
2865 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2867 f
->output_data
.x
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2868 window_prompting
|= YNegative
;
2870 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2871 && CONSP (XCONS (tem0
)->cdr
)
2872 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2874 f
->output_data
.x
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2876 else if (EQ (tem0
, Qunbound
))
2877 f
->output_data
.x
->top_pos
= 0;
2880 CHECK_NUMBER (tem0
, 0);
2881 f
->output_data
.x
->top_pos
= XINT (tem0
);
2882 if (f
->output_data
.x
->top_pos
< 0)
2883 window_prompting
|= YNegative
;
2886 if (EQ (tem1
, Qminus
))
2888 f
->output_data
.x
->left_pos
= 0;
2889 window_prompting
|= XNegative
;
2891 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2892 && CONSP (XCONS (tem1
)->cdr
)
2893 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2895 f
->output_data
.x
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2896 window_prompting
|= XNegative
;
2898 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2899 && CONSP (XCONS (tem1
)->cdr
)
2900 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2902 f
->output_data
.x
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2904 else if (EQ (tem1
, Qunbound
))
2905 f
->output_data
.x
->left_pos
= 0;
2908 CHECK_NUMBER (tem1
, 0);
2909 f
->output_data
.x
->left_pos
= XINT (tem1
);
2910 if (f
->output_data
.x
->left_pos
< 0)
2911 window_prompting
|= XNegative
;
2914 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2915 window_prompting
|= USPosition
;
2917 window_prompting
|= PPosition
;
2920 return window_prompting
;
2923 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2926 XSetWMProtocols (dpy
, w
, protocols
, count
)
2933 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
2934 if (prop
== None
) return False
;
2935 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
2936 (unsigned char *) protocols
, count
);
2939 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2941 #ifdef USE_X_TOOLKIT
2943 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2944 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2945 already be present because of the toolkit (Motif adds some of them,
2946 for example, but Xt doesn't). */
2949 hack_wm_protocols (f
, widget
)
2953 Display
*dpy
= XtDisplay (widget
);
2954 Window w
= XtWindow (widget
);
2955 int need_delete
= 1;
2961 Atom type
, *atoms
= 0;
2963 unsigned long nitems
= 0;
2964 unsigned long bytes_after
;
2966 if ((XGetWindowProperty (dpy
, w
,
2967 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2968 (long)0, (long)100, False
, XA_ATOM
,
2969 &type
, &format
, &nitems
, &bytes_after
,
2970 (unsigned char **) &atoms
)
2972 && format
== 32 && type
== XA_ATOM
)
2976 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
2978 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
2980 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
2983 if (atoms
) XFree ((char *) atoms
);
2989 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
2991 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
2993 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
2995 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2996 XA_ATOM
, 32, PropModeAppend
,
2997 (unsigned char *) props
, count
);
3003 #ifdef USE_X_TOOLKIT
3005 /* Create and set up the X widget for frame F. */
3008 x_window (f
, window_prompting
, minibuffer_only
)
3010 long window_prompting
;
3011 int minibuffer_only
;
3013 XClassHint class_hints
;
3014 XSetWindowAttributes attributes
;
3015 unsigned long attribute_mask
;
3017 Widget shell_widget
;
3019 Widget frame_widget
;
3025 /* Use the resource name as the top-level widget name
3026 for looking up resources. Make a non-Lisp copy
3027 for the window manager, so GC relocation won't bother it.
3029 Elsewhere we specify the window name for the window manager. */
3032 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3033 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3034 strcpy (f
->namebuf
, str
);
3038 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3039 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3040 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3041 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3042 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3043 applicationShellWidgetClass
,
3044 FRAME_X_DISPLAY (f
), al
, ac
);
3046 f
->output_data
.x
->widget
= shell_widget
;
3047 /* maybe_set_screen_title_format (shell_widget); */
3049 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3050 (widget_value
*) NULL
,
3051 shell_widget
, False
,
3054 (lw_callback
) NULL
);
3056 f
->output_data
.x
->column_widget
= pane_widget
;
3058 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3059 the emacs screen when changing menubar. This reduces flickering. */
3062 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3063 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3064 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3065 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3066 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3067 frame_widget
= XtCreateWidget (f
->namebuf
,
3069 pane_widget
, al
, ac
);
3071 f
->output_data
.x
->edit_widget
= frame_widget
;
3073 XtManageChild (frame_widget
);
3075 /* Do some needed geometry management. */
3078 char *tem
, shell_position
[32];
3081 int extra_borders
= 0;
3083 = (f
->output_data
.x
->menubar_widget
3084 ? (f
->output_data
.x
->menubar_widget
->core
.height
3085 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3087 extern char *lwlib_toolkit_type
;
3089 #if 0 /* Experimentally, we now get the right results
3090 for -geometry -0-0 without this. 24 Aug 96, rms. */
3091 if (FRAME_EXTERNAL_MENU_BAR (f
))
3094 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3095 menubar_size
+= ibw
;
3099 f
->output_data
.x
->menubar_height
= menubar_size
;
3102 /* Motif seems to need this amount added to the sizes
3103 specified for the shell widget. The Athena/Lucid widgets don't.
3104 Both conclusions reached experimentally. -- rms. */
3105 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3106 &extra_borders
, NULL
);
3110 /* Convert our geometry parameters into a geometry string
3112 Note that we do not specify here whether the position
3113 is a user-specified or program-specified one.
3114 We pass that information later, in x_wm_set_size_hints. */
3116 int left
= f
->output_data
.x
->left_pos
;
3117 int xneg
= window_prompting
& XNegative
;
3118 int top
= f
->output_data
.x
->top_pos
;
3119 int yneg
= window_prompting
& YNegative
;
3125 if (window_prompting
& USPosition
)
3126 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3127 PIXEL_WIDTH (f
) + extra_borders
,
3128 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3129 (xneg
? '-' : '+'), left
,
3130 (yneg
? '-' : '+'), top
);
3132 sprintf (shell_position
, "=%dx%d",
3133 PIXEL_WIDTH (f
) + extra_borders
,
3134 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3137 len
= strlen (shell_position
) + 1;
3138 /* We don't free this because we don't know whether
3139 it is safe to free it while the frame exists.
3140 It isn't worth the trouble of arranging to free it
3141 when the frame is deleted. */
3142 tem
= (char *) xmalloc (len
);
3143 strncpy (tem
, shell_position
, len
);
3144 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3145 XtSetValues (shell_widget
, al
, ac
);
3148 XtManageChild (pane_widget
);
3149 XtRealizeWidget (shell_widget
);
3151 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3153 validate_x_resource_name ();
3155 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3156 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3157 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3160 #ifndef X_I18N_INHIBITED
3165 xim
= XOpenIM (FRAME_X_DISPLAY (f
), NULL
, NULL
, NULL
);
3169 xic
= XCreateIC (xim
,
3170 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
3171 XNClientWindow
, FRAME_X_WINDOW(f
),
3172 XNFocusWindow
, FRAME_X_WINDOW(f
),
3181 FRAME_XIM (f
) = xim
;
3182 FRAME_XIC (f
) = xic
;
3184 #else /* X_I18N_INHIBITED */
3187 #endif /* X_I18N_INHIBITED */
3188 #endif /* HAVE_X_I18N */
3190 f
->output_data
.x
->wm_hints
.input
= True
;
3191 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3192 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3193 &f
->output_data
.x
->wm_hints
);
3195 hack_wm_protocols (f
, shell_widget
);
3198 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3201 /* Do a stupid property change to force the server to generate a
3202 PropertyNotify event so that the event_stream server timestamp will
3203 be initialized to something relevant to the time we created the window.
3205 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3206 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3207 XA_ATOM
, 32, PropModeAppend
,
3208 (unsigned char*) NULL
, 0);
3210 /* Make all the standard events reach the Emacs frame. */
3211 attributes
.event_mask
= STANDARD_EVENT_SET
;
3212 attribute_mask
= CWEventMask
;
3213 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3214 attribute_mask
, &attributes
);
3216 XtMapWidget (frame_widget
);
3218 /* x_set_name normally ignores requests to set the name if the
3219 requested name is the same as the current name. This is the one
3220 place where that assumption isn't correct; f->name is set, but
3221 the X server hasn't been told. */
3224 int explicit = f
->explicit_name
;
3226 f
->explicit_name
= 0;
3229 x_set_name (f
, name
, explicit);
3232 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3233 f
->output_data
.x
->text_cursor
);
3237 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
3238 initialize_frame_menubar (f
);
3239 lw_set_main_areas (pane_widget
, f
->output_data
.x
->menubar_widget
, frame_widget
);
3241 if (FRAME_X_WINDOW (f
) == 0)
3242 error ("Unable to create window");
3245 #else /* not USE_X_TOOLKIT */
3247 /* Create and set up the X window for frame F. */
3254 XClassHint class_hints
;
3255 XSetWindowAttributes attributes
;
3256 unsigned long attribute_mask
;
3258 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3259 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3260 attributes
.bit_gravity
= StaticGravity
;
3261 attributes
.backing_store
= NotUseful
;
3262 attributes
.save_under
= True
;
3263 attributes
.event_mask
= STANDARD_EVENT_SET
;
3264 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
3266 | CWBackingStore
| CWSaveUnder
3272 = XCreateWindow (FRAME_X_DISPLAY (f
),
3273 f
->output_data
.x
->parent_desc
,
3274 f
->output_data
.x
->left_pos
,
3275 f
->output_data
.x
->top_pos
,
3276 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3277 f
->output_data
.x
->border_width
,
3278 CopyFromParent
, /* depth */
3279 InputOutput
, /* class */
3280 FRAME_X_DISPLAY_INFO (f
)->visual
,
3281 attribute_mask
, &attributes
);
3283 #ifndef X_I18N_INHIBITED
3288 xim
= XOpenIM (FRAME_X_DISPLAY(f
), NULL
, NULL
, NULL
);
3292 xic
= XCreateIC (xim
,
3293 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
3294 XNClientWindow
, FRAME_X_WINDOW(f
),
3295 XNFocusWindow
, FRAME_X_WINDOW(f
),
3305 FRAME_XIM (f
) = xim
;
3306 FRAME_XIC (f
) = xic
;
3308 #else /* X_I18N_INHIBITED */
3311 #endif /* X_I18N_INHIBITED */
3312 #endif /* HAVE_X_I18N */
3314 validate_x_resource_name ();
3316 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3317 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3318 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3320 /* The menubar is part of the ordinary display;
3321 it does not count in addition to the height of the window. */
3322 f
->output_data
.x
->menubar_height
= 0;
3324 /* This indicates that we use the "Passive Input" input model.
3325 Unless we do this, we don't get the Focus{In,Out} events that we
3326 need to draw the cursor correctly. Accursed bureaucrats.
3327 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3329 f
->output_data
.x
->wm_hints
.input
= True
;
3330 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3331 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3332 &f
->output_data
.x
->wm_hints
);
3333 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3335 /* Request "save yourself" and "delete window" commands from wm. */
3338 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3339 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3340 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3343 /* x_set_name normally ignores requests to set the name if the
3344 requested name is the same as the current name. This is the one
3345 place where that assumption isn't correct; f->name is set, but
3346 the X server hasn't been told. */
3349 int explicit = f
->explicit_name
;
3351 f
->explicit_name
= 0;
3354 x_set_name (f
, name
, explicit);
3357 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3358 f
->output_data
.x
->text_cursor
);
3362 if (FRAME_X_WINDOW (f
) == 0)
3363 error ("Unable to create window");
3366 #endif /* not USE_X_TOOLKIT */
3368 /* Handle the icon stuff for this window. Perhaps later we might
3369 want an x_set_icon_position which can be called interactively as
3377 Lisp_Object icon_x
, icon_y
;
3378 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3380 /* Set the position of the icon. Note that twm groups all
3381 icons in an icon window. */
3382 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3383 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3384 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3386 CHECK_NUMBER (icon_x
, 0);
3387 CHECK_NUMBER (icon_y
, 0);
3389 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3390 error ("Both left and top icon corners of icon must be specified");
3394 if (! EQ (icon_x
, Qunbound
))
3395 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3397 /* Start up iconic or window? */
3398 x_wm_set_window_state
3399 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3404 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3411 /* Make the GC's needed for this window, setting the
3412 background, border and mouse colors; also create the
3413 mouse cursor and the gray border tile. */
3415 static char cursor_bits
[] =
3417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3427 XGCValues gc_values
;
3431 /* Create the GC's of this frame.
3432 Note that many default values are used. */
3435 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3436 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3437 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3438 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3439 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3441 GCLineWidth
| GCFont
3442 | GCForeground
| GCBackground
,
3445 /* Reverse video style. */
3446 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3447 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3448 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3450 GCFont
| GCForeground
| GCBackground
3454 /* Cursor has cursor-color background, background-color foreground. */
3455 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3456 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3457 gc_values
.fill_style
= FillOpaqueStippled
;
3459 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3460 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3461 cursor_bits
, 16, 16);
3462 f
->output_data
.x
->cursor_gc
3463 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3464 (GCFont
| GCForeground
| GCBackground
3465 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3469 f
->output_data
.x
->white_relief
.gc
= 0;
3470 f
->output_data
.x
->black_relief
.gc
= 0;
3472 /* Create the gray border tile used when the pointer is not in
3473 the frame. Since this depends on the frame's pixel values,
3474 this must be done on a per-frame basis. */
3475 f
->output_data
.x
->border_tile
3476 = (XCreatePixmapFromBitmapData
3477 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3478 gray_bits
, gray_width
, gray_height
,
3479 f
->output_data
.x
->foreground_pixel
,
3480 f
->output_data
.x
->background_pixel
,
3481 DefaultDepth (FRAME_X_DISPLAY (f
),
3482 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3487 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3489 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3490 Returns an Emacs frame object.\n\
3491 ALIST is an alist of frame parameters.\n\
3492 If the parameters specify that the frame should not have a minibuffer,\n\
3493 and do not specify a specific minibuffer window to use,\n\
3494 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3495 be shared by the new frame.\n\
3497 This function is an internal primitive--use `make-frame' instead.")
3502 Lisp_Object frame
, tem
;
3504 int minibuffer_only
= 0;
3505 long window_prompting
= 0;
3507 int count
= specpdl_ptr
- specpdl
;
3508 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3509 Lisp_Object display
;
3510 struct x_display_info
*dpyinfo
= NULL
;
3516 /* Use this general default value to start with
3517 until we know if this frame has a specified name. */
3518 Vx_resource_name
= Vinvocation_name
;
3520 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3521 if (EQ (display
, Qunbound
))
3523 dpyinfo
= check_x_display_info (display
);
3525 kb
= dpyinfo
->kboard
;
3527 kb
= &the_only_kboard
;
3530 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3532 && ! EQ (name
, Qunbound
)
3534 error ("Invalid frame name--not a string or nil");
3537 Vx_resource_name
= name
;
3539 /* See if parent window is specified. */
3540 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
3541 if (EQ (parent
, Qunbound
))
3543 if (! NILP (parent
))
3544 CHECK_NUMBER (parent
, 0);
3546 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3547 /* No need to protect DISPLAY because that's not used after passing
3548 it to make_frame_without_minibuffer. */
3550 GCPRO4 (parms
, parent
, name
, frame
);
3551 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
3553 if (EQ (tem
, Qnone
) || NILP (tem
))
3554 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3555 else if (EQ (tem
, Qonly
))
3557 f
= make_minibuffer_frame ();
3558 minibuffer_only
= 1;
3560 else if (WINDOWP (tem
))
3561 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3565 XSETFRAME (frame
, f
);
3567 /* Note that X Windows does support scroll bars. */
3568 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3570 f
->output_method
= output_x_window
;
3571 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
3572 bzero (f
->output_data
.x
, sizeof (struct x_output
));
3573 f
->output_data
.x
->icon_bitmap
= -1;
3574 f
->output_data
.x
->fontset
= -1;
3575 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
3576 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
3579 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
3581 if (! STRINGP (f
->icon_name
))
3582 f
->icon_name
= Qnil
;
3584 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
3586 FRAME_KBOARD (f
) = kb
;
3589 /* Specify the parent under which to make this X window. */
3593 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
3594 f
->output_data
.x
->explicit_parent
= 1;
3598 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3599 f
->output_data
.x
->explicit_parent
= 0;
3602 /* Set the name; the functions to which we pass f expect the name to
3604 if (EQ (name
, Qunbound
) || NILP (name
))
3606 f
->name
= build_string (dpyinfo
->x_id_name
);
3607 f
->explicit_name
= 0;
3612 f
->explicit_name
= 1;
3613 /* use the frame's title when getting resources for this frame. */
3614 specbind (Qx_resource_name
, name
);
3617 /* Create fontsets from `global_fontset_alist' before handling fonts. */
3618 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
3619 fs_register_fontset (f
, XCONS (tem
)->car
);
3621 /* Extract the window parameters from the supplied values
3622 that are needed to determine window geometry. */
3626 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
3629 /* First, try whatever font the caller has specified. */
3632 tem
= Fquery_fontset (font
, Qnil
);
3634 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
3636 font
= x_new_font (f
, XSTRING (font
)->data
);
3639 /* Try out a font which we hope has bold and italic variations. */
3640 if (!STRINGP (font
))
3641 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3642 if (!STRINGP (font
))
3643 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3644 if (! STRINGP (font
))
3645 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3646 if (! STRINGP (font
))
3647 /* This was formerly the first thing tried, but it finds too many fonts
3648 and takes too long. */
3649 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3650 /* If those didn't work, look for something which will at least work. */
3651 if (! STRINGP (font
))
3652 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3654 if (! STRINGP (font
))
3655 font
= build_string ("fixed");
3657 x_default_parameter (f
, parms
, Qfont
, font
,
3658 "font", "Font", RES_TYPE_STRING
);
3662 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3663 whereby it fails to get any font. */
3664 xlwmenu_default_font
= f
->output_data
.x
->font
;
3667 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
3668 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
3670 /* This defaults to 2 in order to match xterm. We recognize either
3671 internalBorderWidth or internalBorder (which is what xterm calls
3673 if (NILP (Fassq (Qinternal_border_width
, parms
)))
3677 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
3678 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
3679 if (! EQ (value
, Qunbound
))
3680 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
3683 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
3684 "internalBorderWidth", "internalBorderWidth",
3686 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
3687 "verticalScrollBars", "ScrollBars",
3690 /* Also do the stuff which must be set before the window exists. */
3691 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
3692 "foreground", "Foreground", RES_TYPE_STRING
);
3693 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
3694 "background", "Background", RES_TYPE_STRING
);
3695 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
3696 "pointerColor", "Foreground", RES_TYPE_STRING
);
3697 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
3698 "cursorColor", "Foreground", RES_TYPE_STRING
);
3699 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
3700 "borderColor", "BorderColor", RES_TYPE_STRING
);
3702 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
3703 "scrollBarForeground",
3704 "ScrollBarForeground", 1);
3705 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
3706 "scrollBarBackground",
3707 "ScrollBarBackground", 0);
3709 /* Init faces before x_default_parameter is called for scroll-bar
3710 parameters because that function calls x_set_scroll_bar_width,
3711 which calls change_frame_size, which calls Fset_window_buffer,
3712 which runs hooks, which call Fvertical_motion. At the end, we
3713 end up in init_iterator with a null face cache, which should not
3715 init_frame_faces (f
);
3717 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
3718 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
3719 x_default_parameter (f
, parms
, Qtoolbar_lines
, make_number (0),
3720 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
3721 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
3722 "scrollBarWidth", "ScrollBarWidth",
3724 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
3725 "bufferPredicate", "BufferPredicate",
3727 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
3728 "title", "Title", RES_TYPE_STRING
);
3730 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3731 window_prompting
= x_figure_window_size (f
, parms
);
3733 if (window_prompting
& XNegative
)
3735 if (window_prompting
& YNegative
)
3736 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
3738 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
3742 if (window_prompting
& YNegative
)
3743 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
3745 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3748 f
->output_data
.x
->size_hint_flags
= window_prompting
;
3750 /* Create the X widget or window. Add the toolbar height to the
3751 initial frame height so that the user gets a text display area of
3752 the size he specified with -g or via .Xdefaults. Later changes
3753 of the toolbar height don't change the frame size. This is done
3754 so that users can create tall Emacs frames without having to
3755 guess how tall the toolbar will get. */
3756 f
->height
+= FRAME_TOOLBAR_LINES (f
);
3757 #ifdef USE_X_TOOLKIT
3758 x_window (f
, window_prompting
, minibuffer_only
);
3765 call1 (Qface_set_after_frame_default
, frame
);
3767 /* We need to do this after creating the X window, so that the
3768 icon-creation functions can say whose icon they're describing. */
3769 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
3770 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
3772 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
3773 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
3774 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
3775 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
3776 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
3777 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
3779 /* Dimensions, especially f->height, must be done via change_frame_size.
3780 Change will not be effected unless different from the current
3785 SET_FRAME_WIDTH (f
, 0);
3786 change_frame_size (f
, height
, width
, 1, 0);
3788 /* Tell the server what size and position, etc, we want,
3789 and how badly we want them. */
3791 x_wm_set_size_hint (f
, window_prompting
, 0);
3794 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
3795 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
3799 /* It is now ok to make the frame official
3800 even if we get an error below.
3801 And the frame needs to be on Vframe_list
3802 or making it visible won't work. */
3803 Vframe_list
= Fcons (frame
, Vframe_list
);
3805 /* Now that the frame is official, it counts as a reference to
3807 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
3809 /* Make the window appear on the frame and enable display,
3810 unless the caller says not to. However, with explicit parent,
3811 Emacs cannot control visibility, so don't try. */
3812 if (! f
->output_data
.x
->explicit_parent
)
3814 Lisp_Object visibility
;
3816 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
3818 if (EQ (visibility
, Qunbound
))
3821 if (EQ (visibility
, Qicon
))
3822 x_iconify_frame (f
);
3823 else if (! NILP (visibility
))
3824 x_make_frame_visible (f
);
3826 /* Must have been Qnil. */
3830 return unbind_to (count
, frame
);
3833 /* FRAME is used only to get a handle on the X display. We don't pass the
3834 display info directly because we're called from frame.c, which doesn't
3835 know about that structure. */
3838 x_get_focus_frame (frame
)
3839 struct frame
*frame
;
3841 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
3843 if (! dpyinfo
->x_focus_frame
)
3846 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
3851 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
3852 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3853 If FRAME is omitted or nil, use the selected frame.")
3855 Lisp_Object color
, frame
;
3858 FRAME_PTR f
= check_x_frame (frame
);
3860 CHECK_STRING (color
, 1);
3862 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3868 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
3869 "Return a description of the color named COLOR on frame FRAME.\n\
3870 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3871 These values appear to range from 0 to 65280 or 65535, depending\n\
3872 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3873 If FRAME is omitted or nil, use the selected frame.")
3875 Lisp_Object color
, frame
;
3878 FRAME_PTR f
= check_x_frame (frame
);
3880 CHECK_STRING (color
, 1);
3882 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3886 rgb
[0] = make_number (foo
.red
);
3887 rgb
[1] = make_number (foo
.green
);
3888 rgb
[2] = make_number (foo
.blue
);
3889 return Flist (3, rgb
);
3895 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
3896 "Return t if the X display supports color.\n\
3897 The optional argument DISPLAY specifies which display to ask about.\n\
3898 DISPLAY should be either a frame or a display name (a string).\n\
3899 If omitted or nil, that stands for the selected frame's display.")
3901 Lisp_Object display
;
3903 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3905 if (dpyinfo
->n_planes
<= 2)
3908 switch (dpyinfo
->visual
->class)
3921 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
3923 "Return t if the X display supports shades of gray.\n\
3924 Note that color displays do support shades of gray.\n\
3925 The optional argument DISPLAY specifies which display to ask about.\n\
3926 DISPLAY should be either a frame or a display name (a string).\n\
3927 If omitted or nil, that stands for the selected frame's display.")
3929 Lisp_Object display
;
3931 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3933 if (dpyinfo
->n_planes
<= 1)
3936 switch (dpyinfo
->visual
->class)
3951 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
3953 "Returns the width in pixels of the X display DISPLAY.\n\
3954 The optional argument DISPLAY specifies which display to ask about.\n\
3955 DISPLAY should be either a frame or a display name (a string).\n\
3956 If omitted or nil, that stands for the selected frame's display.")
3958 Lisp_Object display
;
3960 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3962 return make_number (dpyinfo
->width
);
3965 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
3966 Sx_display_pixel_height
, 0, 1, 0,
3967 "Returns the height in pixels of the X display DISPLAY.\n\
3968 The optional argument DISPLAY specifies which display to ask about.\n\
3969 DISPLAY should be either a frame or a display name (a string).\n\
3970 If omitted or nil, that stands for the selected frame's display.")
3972 Lisp_Object display
;
3974 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3976 return make_number (dpyinfo
->height
);
3979 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
3981 "Returns the number of bitplanes of the X display DISPLAY.\n\
3982 The optional argument DISPLAY specifies which display to ask about.\n\
3983 DISPLAY should be either a frame or a display name (a string).\n\
3984 If omitted or nil, that stands for the selected frame's display.")
3986 Lisp_Object display
;
3988 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3990 return make_number (dpyinfo
->n_planes
);
3993 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
3995 "Returns the number of color cells of the X display DISPLAY.\n\
3996 The optional argument DISPLAY specifies which display to ask about.\n\
3997 DISPLAY should be either a frame or a display name (a string).\n\
3998 If omitted or nil, that stands for the selected frame's display.")
4000 Lisp_Object display
;
4002 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4004 return make_number (DisplayCells (dpyinfo
->display
,
4005 XScreenNumberOfScreen (dpyinfo
->screen
)));
4008 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4009 Sx_server_max_request_size
,
4011 "Returns the maximum request size of the X server of display DISPLAY.\n\
4012 The optional argument DISPLAY specifies which display to ask about.\n\
4013 DISPLAY should be either a frame or a display name (a string).\n\
4014 If omitted or nil, that stands for the selected frame's display.")
4016 Lisp_Object display
;
4018 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4020 return make_number (MAXREQUEST (dpyinfo
->display
));
4023 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4024 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4025 The optional argument DISPLAY specifies which display to ask about.\n\
4026 DISPLAY should be either a frame or a display name (a string).\n\
4027 If omitted or nil, that stands for the selected frame's display.")
4029 Lisp_Object display
;
4031 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4032 char *vendor
= ServerVendor (dpyinfo
->display
);
4034 if (! vendor
) vendor
= "";
4035 return build_string (vendor
);
4038 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4039 "Returns the version numbers of the X server of display DISPLAY.\n\
4040 The value is a list of three integers: the major and minor\n\
4041 version numbers of the X Protocol in use, and the vendor-specific release\n\
4042 number. See also the function `x-server-vendor'.\n\n\
4043 The optional argument DISPLAY specifies which display to ask about.\n\
4044 DISPLAY should be either a frame or a display name (a string).\n\
4045 If omitted or nil, that stands for the selected frame's display.")
4047 Lisp_Object display
;
4049 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4050 Display
*dpy
= dpyinfo
->display
;
4052 return Fcons (make_number (ProtocolVersion (dpy
)),
4053 Fcons (make_number (ProtocolRevision (dpy
)),
4054 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4057 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4058 "Returns the number of screens on the X server of display DISPLAY.\n\
4059 The optional argument DISPLAY specifies which display to ask about.\n\
4060 DISPLAY should be either a frame or a display name (a string).\n\
4061 If omitted or nil, that stands for the selected frame's display.")
4063 Lisp_Object display
;
4065 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4067 return make_number (ScreenCount (dpyinfo
->display
));
4070 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4071 "Returns the height in millimeters of the X display DISPLAY.\n\
4072 The optional argument DISPLAY specifies which display to ask about.\n\
4073 DISPLAY should be either a frame or a display name (a string).\n\
4074 If omitted or nil, that stands for the selected frame's display.")
4076 Lisp_Object display
;
4078 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4080 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4083 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4084 "Returns the width in millimeters of the X display DISPLAY.\n\
4085 The optional argument DISPLAY specifies which display to ask about.\n\
4086 DISPLAY should be either a frame or a display name (a string).\n\
4087 If omitted or nil, that stands for the selected frame's display.")
4089 Lisp_Object display
;
4091 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4093 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4096 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4097 Sx_display_backing_store
, 0, 1, 0,
4098 "Returns an indication of whether X display DISPLAY does backing store.\n\
4099 The value may be `always', `when-mapped', or `not-useful'.\n\
4100 The optional argument DISPLAY specifies which display to ask about.\n\
4101 DISPLAY should be either a frame or a display name (a string).\n\
4102 If omitted or nil, that stands for the selected frame's display.")
4104 Lisp_Object display
;
4106 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4108 switch (DoesBackingStore (dpyinfo
->screen
))
4111 return intern ("always");
4114 return intern ("when-mapped");
4117 return intern ("not-useful");
4120 error ("Strange value for BackingStore parameter of screen");
4124 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4125 Sx_display_visual_class
, 0, 1, 0,
4126 "Returns the visual class of the X display DISPLAY.\n\
4127 The value is one of the symbols `static-gray', `gray-scale',\n\
4128 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4129 The optional argument DISPLAY specifies which display to ask about.\n\
4130 DISPLAY should be either a frame or a display name (a string).\n\
4131 If omitted or nil, that stands for the selected frame's display.")
4133 Lisp_Object display
;
4135 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4137 switch (dpyinfo
->visual
->class)
4139 case StaticGray
: return (intern ("static-gray"));
4140 case GrayScale
: return (intern ("gray-scale"));
4141 case StaticColor
: return (intern ("static-color"));
4142 case PseudoColor
: return (intern ("pseudo-color"));
4143 case TrueColor
: return (intern ("true-color"));
4144 case DirectColor
: return (intern ("direct-color"));
4146 error ("Display has an unknown visual class");
4150 DEFUN ("x-display-save-under", Fx_display_save_under
,
4151 Sx_display_save_under
, 0, 1, 0,
4152 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4153 The optional argument DISPLAY specifies which display to ask about.\n\
4154 DISPLAY should be either a frame or a display name (a string).\n\
4155 If omitted or nil, that stands for the selected frame's display.")
4157 Lisp_Object display
;
4159 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4161 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4169 register struct frame
*f
;
4171 return PIXEL_WIDTH (f
);
4176 register struct frame
*f
;
4178 return PIXEL_HEIGHT (f
);
4183 register struct frame
*f
;
4185 return FONT_WIDTH (f
->output_data
.x
->font
);
4190 register struct frame
*f
;
4192 return f
->output_data
.x
->line_height
;
4197 register struct frame
*f
;
4199 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4202 #if 0 /* These no longer seem like the right way to do things. */
4204 /* Draw a rectangle on the frame with left top corner including
4205 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
4206 CHARS by LINES wide and long and is the color of the cursor. */
4209 x_rectangle (f
, gc
, left_char
, top_char
, chars
, lines
)
4210 register struct frame
*f
;
4212 register int top_char
, left_char
, chars
, lines
;
4216 int left
= (left_char
* FONT_WIDTH (f
->output_data
.x
->font
)
4217 + f
->output_data
.x
->internal_border_width
);
4218 int top
= (top_char
* f
->output_data
.x
->line_height
4219 + f
->output_data
.x
->internal_border_width
);
4222 width
= FONT_WIDTH (f
->output_data
.x
->font
) / 2;
4224 width
= FONT_WIDTH (f
->output_data
.x
->font
) * chars
;
4226 height
= f
->output_data
.x
->line_height
/ 2;
4228 height
= f
->output_data
.x
->line_height
* lines
;
4230 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4231 gc
, left
, top
, width
, height
);
4234 DEFUN ("x-draw-rectangle", Fx_draw_rectangle
, Sx_draw_rectangle
, 5, 5, 0,
4235 "Draw a rectangle on FRAME between coordinates specified by\n\
4236 numbers X0, Y0, X1, Y1 in the cursor pixel.")
4237 (frame
, X0
, Y0
, X1
, Y1
)
4238 register Lisp_Object frame
, X0
, X1
, Y0
, Y1
;
4240 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4242 CHECK_LIVE_FRAME (frame
, 0);
4243 CHECK_NUMBER (X0
, 0);
4244 CHECK_NUMBER (Y0
, 1);
4245 CHECK_NUMBER (X1
, 2);
4246 CHECK_NUMBER (Y1
, 3);
4256 n_lines
= y1
- y0
+ 1;
4261 n_lines
= y0
- y1
+ 1;
4267 n_chars
= x1
- x0
+ 1;
4272 n_chars
= x0
- x1
+ 1;
4276 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->cursor_gc
,
4277 left
, top
, n_chars
, n_lines
);
4283 DEFUN ("x-erase-rectangle", Fx_erase_rectangle
, Sx_erase_rectangle
, 5, 5, 0,
4284 "Draw a rectangle drawn on FRAME between coordinates\n\
4285 X0, Y0, X1, Y1 in the regular background-pixel.")
4286 (frame
, X0
, Y0
, X1
, Y1
)
4287 register Lisp_Object frame
, X0
, Y0
, X1
, Y1
;
4289 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4291 CHECK_LIVE_FRAME (frame
, 0);
4292 CHECK_NUMBER (X0
, 0);
4293 CHECK_NUMBER (Y0
, 1);
4294 CHECK_NUMBER (X1
, 2);
4295 CHECK_NUMBER (Y1
, 3);
4305 n_lines
= y1
- y0
+ 1;
4310 n_lines
= y0
- y1
+ 1;
4316 n_chars
= x1
- x0
+ 1;
4321 n_chars
= x0
- x1
+ 1;
4325 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->reverse_gc
,
4326 left
, top
, n_chars
, n_lines
);
4332 /* Draw lines around the text region beginning at the character position
4333 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4334 pixel and line characteristics. */
4336 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4339 outline_region (f
, gc
, top_x
, top_y
, bottom_x
, bottom_y
)
4340 register struct frame
*f
;
4342 int top_x
, top_y
, bottom_x
, bottom_y
;
4344 register int ibw
= f
->output_data
.x
->internal_border_width
;
4345 register int font_w
= FONT_WIDTH (f
->output_data
.x
->font
);
4346 register int font_h
= f
->output_data
.x
->line_height
;
4348 int x
= line_len (y
);
4349 XPoint
*pixel_points
4350 = (XPoint
*) alloca (((bottom_y
- top_y
+ 2) * 4) * sizeof (XPoint
));
4351 register XPoint
*this_point
= pixel_points
;
4353 /* Do the horizontal top line/lines */
4356 this_point
->x
= ibw
;
4357 this_point
->y
= ibw
+ (font_h
* top_y
);
4360 this_point
->x
= ibw
+ (font_w
/ 2); /* Half-size for newline chars. */
4362 this_point
->x
= ibw
+ (font_w
* x
);
4363 this_point
->y
= (this_point
- 1)->y
;
4367 this_point
->x
= ibw
;
4368 this_point
->y
= ibw
+ (font_h
* (top_y
+ 1));
4370 this_point
->x
= ibw
+ (font_w
* top_x
);
4371 this_point
->y
= (this_point
- 1)->y
;
4373 this_point
->x
= (this_point
- 1)->x
;
4374 this_point
->y
= ibw
+ (font_h
* top_y
);
4376 this_point
->x
= ibw
+ (font_w
* x
);
4377 this_point
->y
= (this_point
- 1)->y
;
4380 /* Now do the right side. */
4381 while (y
< bottom_y
)
4382 { /* Right vertical edge */
4384 this_point
->x
= (this_point
- 1)->x
;
4385 this_point
->y
= ibw
+ (font_h
* (y
+ 1));
4388 y
++; /* Horizontal connection to next line */
4391 this_point
->x
= ibw
+ (font_w
/ 2);
4393 this_point
->x
= ibw
+ (font_w
* x
);
4395 this_point
->y
= (this_point
- 1)->y
;
4398 /* Now do the bottom and connect to the top left point. */
4399 this_point
->x
= ibw
+ (font_w
* (bottom_x
+ 1));
4402 this_point
->x
= (this_point
- 1)->x
;
4403 this_point
->y
= ibw
+ (font_h
* (bottom_y
+ 1));
4405 this_point
->x
= ibw
;
4406 this_point
->y
= (this_point
- 1)->y
;
4408 this_point
->x
= pixel_points
->x
;
4409 this_point
->y
= pixel_points
->y
;
4411 XDrawLines (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4413 (this_point
- pixel_points
+ 1), CoordModeOrigin
);
4416 DEFUN ("x-contour-region", Fx_contour_region
, Sx_contour_region
, 1, 1, 0,
4417 "Highlight the region between point and the character under the mouse\n\
4420 register Lisp_Object event
;
4422 register int x0
, y0
, x1
, y1
;
4423 register struct frame
*f
= selected_frame
;
4424 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4425 register int p1
, p2
;
4427 CHECK_CONS (event
, 0);
4430 x0
= XINT (Fcar (Fcar (event
)));
4431 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4433 /* If the mouse is past the end of the line, don't that area. */
4434 /* ReWrite this... */
4436 /* Where the cursor is. */
4437 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4438 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4440 if (y1
> y0
) /* point below mouse */
4441 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4443 else if (y1
< y0
) /* point above mouse */
4444 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4446 else /* same line: draw horizontal rectangle */
4449 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4450 x0
, y0
, (x1
- x0
+ 1), 1);
4452 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4453 x1
, y1
, (x0
- x1
+ 1), 1);
4456 XFlush (FRAME_X_DISPLAY (f
));
4462 DEFUN ("x-uncontour-region", Fx_uncontour_region
, Sx_uncontour_region
, 1, 1, 0,
4463 "Erase any highlighting of the region between point and the character\n\
4464 at X, Y on the selected frame.")
4466 register Lisp_Object event
;
4468 register int x0
, y0
, x1
, y1
;
4469 register struct frame
*f
= selected_frame
;
4470 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4473 x0
= XINT (Fcar (Fcar (event
)));
4474 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4475 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4476 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4478 if (y1
> y0
) /* point below mouse */
4479 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4481 else if (y1
< y0
) /* point above mouse */
4482 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4484 else /* same line: draw horizontal rectangle */
4487 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4488 x0
, y0
, (x1
- x0
+ 1), 1);
4490 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4491 x1
, y1
, (x0
- x1
+ 1), 1);
4499 int contour_begin_x
, contour_begin_y
;
4500 int contour_end_x
, contour_end_y
;
4501 int contour_npoints
;
4503 /* Clip the top part of the contour lines down (and including) line Y_POS.
4504 If X_POS is in the middle (rather than at the end) of the line, drop
4505 down a line at that character. */
4508 clip_contour_top (y_pos
, x_pos
)
4510 register XPoint
*begin
= contour_lines
[y_pos
].top_left
;
4511 register XPoint
*end
;
4512 register int npoints
;
4513 register struct display_line
*line
= selected_frame
->phys_lines
[y_pos
+ 1];
4515 if (x_pos
>= line
->len
- 1) /* Draw one, straight horizontal line. */
4517 end
= contour_lines
[y_pos
].top_right
;
4518 npoints
= (end
- begin
+ 1);
4519 XDrawLines (x_current_display
, contour_window
,
4520 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4522 bcopy (end
, begin
+ 1, contour_last_point
- end
+ 1);
4523 contour_last_point
-= (npoints
- 2);
4524 XDrawLines (x_current_display
, contour_window
,
4525 contour_erase_gc
, begin
, 2, CoordModeOrigin
);
4526 XFlush (x_current_display
);
4528 /* Now, update contour_lines structure. */
4533 register XPoint
*p
= begin
+ 1;
4534 end
= contour_lines
[y_pos
].bottom_right
;
4535 npoints
= (end
- begin
+ 1);
4536 XDrawLines (x_current_display
, contour_window
,
4537 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4540 p
->x
= ibw
+ (font_w
* (x_pos
+ 1));
4542 p
->y
= begin
->y
+ font_h
;
4544 bcopy (end
, begin
+ 3, contour_last_point
- end
+ 1);
4545 contour_last_point
-= (npoints
- 5);
4546 XDrawLines (x_current_display
, contour_window
,
4547 contour_erase_gc
, begin
, 4, CoordModeOrigin
);
4548 XFlush (x_current_display
);
4550 /* Now, update contour_lines structure. */
4554 /* Erase the top horizontal lines of the contour, and then extend
4555 the contour upwards. */
4558 extend_contour_top (line
)
4563 clip_contour_bottom (x_pos
, y_pos
)
4569 extend_contour_bottom (x_pos
, y_pos
)
4573 DEFUN ("x-select-region", Fx_select_region
, Sx_select_region
, 1, 1, "e",
4578 register struct frame
*f
= selected_frame
;
4579 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4580 register int point_x
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4581 register int point_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4582 register int mouse_below_point
;
4583 register Lisp_Object obj
;
4584 register int x_contour_x
, x_contour_y
;
4586 x_contour_x
= x_mouse_x
;
4587 x_contour_y
= x_mouse_y
;
4588 if (x_contour_y
> point_y
|| (x_contour_y
== point_y
4589 && x_contour_x
> point_x
))
4591 mouse_below_point
= 1;
4592 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4593 x_contour_x
, x_contour_y
);
4597 mouse_below_point
= 0;
4598 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_contour_x
, x_contour_y
,
4604 obj
= read_char (-1, 0, 0, Qnil
, 0);
4608 if (mouse_below_point
)
4610 if (x_mouse_y
<= point_y
) /* Flipped. */
4612 mouse_below_point
= 0;
4614 outline_region (f
, f
->output_data
.x
->reverse_gc
, point_x
, point_y
,
4615 x_contour_x
, x_contour_y
);
4616 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_mouse_x
, x_mouse_y
,
4619 else if (x_mouse_y
< x_contour_y
) /* Bottom clipped. */
4621 clip_contour_bottom (x_mouse_y
);
4623 else if (x_mouse_y
> x_contour_y
) /* Bottom extended. */
4625 extend_bottom_contour (x_mouse_y
);
4628 x_contour_x
= x_mouse_x
;
4629 x_contour_y
= x_mouse_y
;
4631 else /* mouse above or same line as point */
4633 if (x_mouse_y
>= point_y
) /* Flipped. */
4635 mouse_below_point
= 1;
4637 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4638 x_contour_x
, x_contour_y
, point_x
, point_y
);
4639 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4640 x_mouse_x
, x_mouse_y
);
4642 else if (x_mouse_y
> x_contour_y
) /* Top clipped. */
4644 clip_contour_top (x_mouse_y
);
4646 else if (x_mouse_y
< x_contour_y
) /* Top extended. */
4648 extend_contour_top (x_mouse_y
);
4653 unread_command_event
= obj
;
4654 if (mouse_below_point
)
4656 contour_begin_x
= point_x
;
4657 contour_begin_y
= point_y
;
4658 contour_end_x
= x_contour_x
;
4659 contour_end_y
= x_contour_y
;
4663 contour_begin_x
= x_contour_x
;
4664 contour_begin_y
= x_contour_y
;
4665 contour_end_x
= point_x
;
4666 contour_end_y
= point_y
;
4671 DEFUN ("x-horizontal-line", Fx_horizontal_line
, Sx_horizontal_line
, 1, 1, "e",
4676 register Lisp_Object obj
;
4677 struct frame
*f
= selected_frame
;
4678 register struct window
*w
= XWINDOW (selected_window
);
4679 register GC line_gc
= f
->output_data
.x
->cursor_gc
;
4680 register GC erase_gc
= f
->output_data
.x
->reverse_gc
;
4682 char dash_list
[] = {6, 4, 6, 4};
4684 XGCValues gc_values
;
4686 register int previous_y
;
4687 register int line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4688 + f
->output_data
.x
->internal_border_width
;
4689 register int left
= f
->output_data
.x
->internal_border_width
4690 + (WINDOW_LEFT_MARGIN (w
)
4691 * FONT_WIDTH (f
->output_data
.x
->font
));
4692 register int right
= left
+ (w
->width
4693 * FONT_WIDTH (f
->output_data
.x
->font
))
4694 - f
->output_data
.x
->internal_border_width
;
4698 gc_values
.foreground
= f
->output_data
.x
->cursor_pixel
;
4699 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4700 gc_values
.line_width
= 1;
4701 gc_values
.line_style
= LineOnOffDash
;
4702 gc_values
.cap_style
= CapRound
;
4703 gc_values
.join_style
= JoinRound
;
4705 line_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4706 GCLineStyle
| GCJoinStyle
| GCCapStyle
4707 | GCLineWidth
| GCForeground
| GCBackground
,
4709 XSetDashes (FRAME_X_DISPLAY (f
), line_gc
, 0, dash_list
, dashes
);
4710 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4711 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4712 erase_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4713 GCLineStyle
| GCJoinStyle
| GCCapStyle
4714 | GCLineWidth
| GCForeground
| GCBackground
,
4716 XSetDashes (FRAME_X_DISPLAY (f
), erase_gc
, 0, dash_list
, dashes
);
4723 if (x_mouse_y
>= XINT (w
->top
)
4724 && x_mouse_y
< XINT (w
->top
) + XINT (w
->height
) - 1)
4726 previous_y
= x_mouse_y
;
4727 line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4728 + f
->output_data
.x
->internal_border_width
;
4729 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4730 line_gc
, left
, line
, right
, line
);
4732 XFlush (FRAME_X_DISPLAY (f
));
4737 obj
= read_char (-1, 0, 0, Qnil
, 0);
4739 || (! EQ (Fcar (Fcdr (Fcdr (obj
))),
4740 Qvertical_scroll_bar
))
4744 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4745 erase_gc
, left
, line
, right
, line
);
4746 unread_command_event
= obj
;
4748 XFreeGC (FRAME_X_DISPLAY (f
), line_gc
);
4749 XFreeGC (FRAME_X_DISPLAY (f
), erase_gc
);
4755 while (x_mouse_y
== previous_y
);
4758 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4759 erase_gc
, left
, line
, right
, line
);
4766 /* These keep track of the rectangle following the pointer. */
4767 int mouse_track_top
, mouse_track_left
, mouse_track_width
;
4769 /* Offset in buffer of character under the pointer, or 0. */
4770 int mouse_buffer_offset
;
4772 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 0, 0, 0,
4773 "Track the pointer.")
4776 static Cursor current_pointer_shape
;
4777 FRAME_PTR f
= x_mouse_frame
;
4780 if (EQ (Vmouse_frame_part
, Qtext_part
)
4781 && (current_pointer_shape
!= f
->output_data
.x
->nontext_cursor
))
4786 current_pointer_shape
= f
->output_data
.x
->nontext_cursor
;
4787 XDefineCursor (FRAME_X_DISPLAY (f
),
4789 current_pointer_shape
);
4791 buf
= XBUFFER (XWINDOW (Vmouse_window
)->buffer
);
4792 c
= *(BUF_CHAR_ADDRESS (buf
, mouse_buffer_offset
));
4794 else if (EQ (Vmouse_frame_part
, Qmodeline_part
)
4795 && (current_pointer_shape
!= f
->output_data
.x
->modeline_cursor
))
4797 current_pointer_shape
= f
->output_data
.x
->modeline_cursor
;
4798 XDefineCursor (FRAME_X_DISPLAY (f
),
4800 current_pointer_shape
);
4803 XFlush (FRAME_X_DISPLAY (f
));
4809 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 1, 1, "e",
4810 "Draw rectangle around character under mouse pointer, if there is one.")
4814 struct window
*w
= XWINDOW (Vmouse_window
);
4815 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4816 struct buffer
*b
= XBUFFER (w
->buffer
);
4819 if (! EQ (Vmouse_window
, selected_window
))
4822 if (EQ (event
, Qnil
))
4826 x_read_mouse_position (selected_frame
, &x
, &y
);
4830 mouse_track_width
= 0;
4831 mouse_track_left
= mouse_track_top
= -1;
4835 if ((x_mouse_x
!= mouse_track_left
4836 && (x_mouse_x
< mouse_track_left
4837 || x_mouse_x
> (mouse_track_left
+ mouse_track_width
)))
4838 || x_mouse_y
!= mouse_track_top
)
4840 int hp
= 0; /* Horizontal position */
4841 int len
= FRAME_CURRENT_GLYPHS (f
)->used
[x_mouse_y
];
4842 int p
= FRAME_CURRENT_GLYPHS (f
)->bufp
[x_mouse_y
];
4843 int tab_width
= XINT (b
->tab_width
);
4844 int ctl_arrow_p
= !NILP (b
->ctl_arrow
);
4846 int mode_line_vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
4847 int in_mode_line
= 0;
4849 if (! FRAME_CURRENT_GLYPHS (f
)->enable
[x_mouse_y
])
4852 /* Erase previous rectangle. */
4853 if (mouse_track_width
)
4855 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4856 mouse_track_left
, mouse_track_top
,
4857 mouse_track_width
, 1);
4859 if ((mouse_track_left
== f
->phys_cursor_x
4860 || mouse_track_left
== f
->phys_cursor_x
- 1)
4861 && mouse_track_top
== f
->phys_cursor_y
)
4863 x_display_cursor (f
, 1);
4867 mouse_track_left
= x_mouse_x
;
4868 mouse_track_top
= x_mouse_y
;
4869 mouse_track_width
= 0;
4871 if (mouse_track_left
> len
) /* Past the end of line. */
4874 if (mouse_track_top
== mode_line_vpos
)
4880 if (tab_width
<= 0 || tab_width
> 20) tab_width
= 8;
4884 if (len
== f
->width
&& hp
== len
- 1 && c
!= '\n')
4890 mouse_track_width
= tab_width
- (hp
% tab_width
);
4892 hp
+= mouse_track_width
;
4895 mouse_track_left
= hp
- mouse_track_width
;
4901 mouse_track_width
= -1;
4905 if (ctl_arrow_p
&& (c
< 040 || c
== 0177))
4910 mouse_track_width
= 2;
4915 mouse_track_left
= hp
- mouse_track_width
;
4921 mouse_track_width
= 1;
4928 while (hp
<= x_mouse_x
);
4931 if (mouse_track_width
) /* Over text; use text pointer shape. */
4933 XDefineCursor (FRAME_X_DISPLAY (f
),
4935 f
->output_data
.x
->text_cursor
);
4936 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4937 mouse_track_left
, mouse_track_top
,
4938 mouse_track_width
, 1);
4940 else if (in_mode_line
)
4941 XDefineCursor (FRAME_X_DISPLAY (f
),
4943 f
->output_data
.x
->modeline_cursor
);
4945 XDefineCursor (FRAME_X_DISPLAY (f
),
4947 f
->output_data
.x
->nontext_cursor
);
4950 XFlush (FRAME_X_DISPLAY (f
));
4953 obj
= read_char (-1, 0, 0, Qnil
, 0);
4956 while (CONSP (obj
) /* Mouse event */
4957 && EQ (Fcar (Fcdr (Fcdr (obj
))), Qnil
) /* Not scroll bar */
4958 && EQ (Vmouse_depressed
, Qnil
) /* Only motion events */
4959 && EQ (Vmouse_window
, selected_window
) /* In this window */
4962 unread_command_event
= obj
;
4964 if (mouse_track_width
)
4966 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4967 mouse_track_left
, mouse_track_top
,
4968 mouse_track_width
, 1);
4969 mouse_track_width
= 0;
4970 if ((mouse_track_left
== f
->phys_cursor_x
4971 || mouse_track_left
- 1 == f
->phys_cursor_x
)
4972 && mouse_track_top
== f
->phys_cursor_y
)
4974 x_display_cursor (f
, 1);
4977 XDefineCursor (FRAME_X_DISPLAY (f
),
4979 f
->output_data
.x
->nontext_cursor
);
4980 XFlush (FRAME_X_DISPLAY (f
));
4990 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4991 on the frame F at position X, Y. */
4993 x_draw_pixmap (f
, x
, y
, image_data
, width
, height
)
4995 int x
, y
, width
, height
;
5000 image
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
5001 FRAME_X_WINDOW (f
), image_data
,
5003 XCopyPlane (FRAME_X_DISPLAY (f
), image
, FRAME_X_WINDOW (f
),
5004 f
->output_data
.x
->normal_gc
, 0, 0, width
, height
, x
, y
);
5008 #if 0 /* I'm told these functions are superfluous
5009 given the ability to bind function keys. */
5012 DEFUN ("x-rebind-key", Fx_rebind_key
, Sx_rebind_key
, 3, 3, 0,
5013 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
5014 KEYSYM is a string which conforms to the X keysym definitions found\n\
5015 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
5016 list of strings specifying modifier keys such as Control_L, which must\n\
5017 also be depressed for NEWSTRING to appear.")
5018 (x_keysym
, modifiers
, newstring
)
5019 register Lisp_Object x_keysym
;
5020 register Lisp_Object modifiers
;
5021 register Lisp_Object newstring
;
5024 register KeySym keysym
;
5025 KeySym modifier_list
[16];
5028 CHECK_STRING (x_keysym
, 1);
5029 CHECK_STRING (newstring
, 3);
5031 keysym
= XStringToKeysym ((char *) XSTRING (x_keysym
)->data
);
5032 if (keysym
== NoSymbol
)
5033 error ("Keysym does not exist");
5035 if (NILP (modifiers
))
5036 XRebindKeysym (x_current_display
, keysym
, modifier_list
, 0,
5037 XSTRING (newstring
)->data
,
5038 STRING_BYTES (XSTRING (newstring
)));
5041 register Lisp_Object rest
, mod
;
5044 for (rest
= modifiers
; !NILP (rest
); rest
= Fcdr (rest
))
5047 error ("Can't have more than 16 modifiers");
5050 CHECK_STRING (mod
, 3);
5051 modifier_list
[i
] = XStringToKeysym ((char *) XSTRING (mod
)->data
);
5053 if (modifier_list
[i
] == NoSymbol
5054 || !(IsModifierKey (modifier_list
[i
])
5055 || ((unsigned)(modifier_list
[i
]) == XK_Mode_switch
)
5056 || ((unsigned)(modifier_list
[i
]) == XK_Num_Lock
)))
5058 if (modifier_list
[i
] == NoSymbol
5059 || !IsModifierKey (modifier_list
[i
]))
5061 error ("Element is not a modifier keysym");
5065 XRebindKeysym (x_current_display
, keysym
, modifier_list
, i
,
5066 XSTRING (newstring
)->data
,
5067 STRING_BYTES (XSTRING (newstring
)));
5073 DEFUN ("x-rebind-keys", Fx_rebind_keys
, Sx_rebind_keys
, 2, 2, 0,
5074 "Rebind KEYCODE to list of strings STRINGS.\n\
5075 STRINGS should be a list of 16 elements, one for each shift combination.\n\
5076 nil as element means don't change.\n\
5077 See the documentation of `x-rebind-key' for more information.")
5079 register Lisp_Object keycode
;
5080 register Lisp_Object strings
;
5082 register Lisp_Object item
;
5083 register unsigned char *rawstring
;
5084 KeySym rawkey
, modifier
[1];
5086 register unsigned i
;
5089 CHECK_NUMBER (keycode
, 1);
5090 CHECK_CONS (strings
, 2);
5091 rawkey
= (KeySym
) ((unsigned) (XINT (keycode
))) & 255;
5092 for (i
= 0; i
<= 15; strings
= Fcdr (strings
), i
++)
5094 item
= Fcar (strings
);
5097 CHECK_STRING (item
, 2);
5098 strsize
= STRING_BYTES (XSTRING (item
));
5099 rawstring
= (unsigned char *) xmalloc (strsize
);
5100 bcopy (XSTRING (item
)->data
, rawstring
, strsize
);
5101 modifier
[1] = 1 << i
;
5102 XRebindKeysym (x_current_display
, rawkey
, modifier
, 1,
5103 rawstring
, strsize
);
5108 #endif /* HAVE_X11 */
5111 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5113 XScreenNumberOfScreen (scr
)
5114 register Screen
*scr
;
5116 register Display
*dpy
;
5117 register Screen
*dpyscr
;
5121 dpyscr
= dpy
->screens
;
5123 for (i
= 0; i
< dpy
->nscreens
; i
++, dpyscr
++)
5129 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5132 select_visual (dpy
, screen
, depth
)
5135 unsigned int *depth
;
5138 XVisualInfo
*vinfo
, vinfo_template
;
5141 v
= DefaultVisualOfScreen (screen
);
5144 vinfo_template
.visualid
= XVisualIDFromVisual (v
);
5146 vinfo_template
.visualid
= v
->visualid
;
5149 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5151 vinfo
= XGetVisualInfo (dpy
,
5152 VisualIDMask
| VisualScreenMask
, &vinfo_template
,
5155 fatal ("Can't get proper X visual info");
5157 if ((1 << vinfo
->depth
) == vinfo
->colormap_size
)
5158 *depth
= vinfo
->depth
;
5162 int n
= vinfo
->colormap_size
- 1;
5171 XFree ((char *) vinfo
);
5175 /* Return the X display structure for the display named NAME.
5176 Open a new connection if necessary. */
5178 struct x_display_info
*
5179 x_display_info_for_name (name
)
5183 struct x_display_info
*dpyinfo
;
5185 CHECK_STRING (name
, 0);
5187 if (! EQ (Vwindow_system
, intern ("x")))
5188 error ("Not using X Windows");
5190 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5192 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
5195 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
5200 /* Use this general default value to start with. */
5201 Vx_resource_name
= Vinvocation_name
;
5203 validate_x_resource_name ();
5205 dpyinfo
= x_term_init (name
, (unsigned char *)0,
5206 (char *) XSTRING (Vx_resource_name
)->data
);
5209 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5212 XSETFASTINT (Vwindow_system_version
, 11);
5217 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5218 1, 3, 0, "Open a connection to an X server.\n\
5219 DISPLAY is the name of the display to connect to.\n\
5220 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5221 If the optional third arg MUST-SUCCEED is non-nil,\n\
5222 terminate Emacs if we can't open the connection.")
5223 (display
, xrm_string
, must_succeed
)
5224 Lisp_Object display
, xrm_string
, must_succeed
;
5226 unsigned char *xrm_option
;
5227 struct x_display_info
*dpyinfo
;
5229 CHECK_STRING (display
, 0);
5230 if (! NILP (xrm_string
))
5231 CHECK_STRING (xrm_string
, 1);
5233 if (! EQ (Vwindow_system
, intern ("x")))
5234 error ("Not using X Windows");
5236 if (! NILP (xrm_string
))
5237 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5239 xrm_option
= (unsigned char *) 0;
5241 validate_x_resource_name ();
5243 /* This is what opens the connection and sets x_current_display.
5244 This also initializes many symbols, such as those used for input. */
5245 dpyinfo
= x_term_init (display
, xrm_option
,
5246 (char *) XSTRING (Vx_resource_name
)->data
);
5250 if (!NILP (must_succeed
))
5251 fatal ("Cannot connect to X server %s.\n\
5252 Check the DISPLAY environment variable or use `-d'.\n\
5253 Also use the `xhost' program to verify that it is set to permit\n\
5254 connections from your machine.\n",
5255 XSTRING (display
)->data
);
5257 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5262 XSETFASTINT (Vwindow_system_version
, 11);
5266 DEFUN ("x-close-connection", Fx_close_connection
,
5267 Sx_close_connection
, 1, 1, 0,
5268 "Close the connection to DISPLAY's X server.\n\
5269 For DISPLAY, specify either a frame or a display name (a string).\n\
5270 If DISPLAY is nil, that stands for the selected frame's display.")
5272 Lisp_Object display
;
5274 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5277 if (dpyinfo
->reference_count
> 0)
5278 error ("Display still has frames on it");
5281 /* Free the fonts in the font table. */
5282 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5283 if (dpyinfo
->font_table
[i
].name
)
5285 xfree (dpyinfo
->font_table
[i
].name
);
5286 /* Don't free the full_name string;
5287 it is always shared with something else. */
5288 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5291 x_destroy_all_bitmaps (dpyinfo
);
5292 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5294 #ifdef USE_X_TOOLKIT
5295 XtCloseDisplay (dpyinfo
->display
);
5297 XCloseDisplay (dpyinfo
->display
);
5300 x_delete_display (dpyinfo
);
5306 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5307 "Return the list of display names that Emacs has connections to.")
5310 Lisp_Object tail
, result
;
5313 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
5314 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
5319 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5320 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5321 If ON is nil, allow buffering of requests.\n\
5322 Turning on synchronization prohibits the Xlib routines from buffering\n\
5323 requests and seriously degrades performance, but makes debugging much\n\
5325 The optional second argument DISPLAY specifies which display to act on.\n\
5326 DISPLAY should be either a frame or a display name (a string).\n\
5327 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5329 Lisp_Object display
, on
;
5331 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5333 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5338 /* Wait for responses to all X commands issued so far for frame F. */
5345 XSync (FRAME_X_DISPLAY (f
), False
);
5350 /***********************************************************************
5352 ***********************************************************************/
5354 /* Value is the number of elements of vector VECTOR. */
5356 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5358 /* List of supported image types. Use define_image_type to add new
5359 types. Use lookup_image_type to find a type for a given symbol. */
5361 static struct image_type
*image_types
;
5363 /* A list of symbols, one for each supported image type. */
5365 Lisp_Object Vimage_types
;
5367 /* The symbol `image' which is the car of the lists used to represent
5370 extern Lisp_Object Qimage
;
5372 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5378 Lisp_Object QCtype
, QCdata
, QCfile
, QCascent
, QCmargin
, QCrelief
;
5379 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
;
5380 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5381 extern Lisp_Object QCimage
;
5383 /* Other symbols. */
5385 Lisp_Object Qlaplace
;
5387 /* Time in seconds after which images should be removed from the cache
5388 if not displayed. */
5390 Lisp_Object Vimage_eviction_seconds
;
5392 /* Function prototypes. */
5394 static void define_image_type
P_ ((struct image_type
*type
));
5395 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5396 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5397 static void x_laplace
P_ ((struct frame
*, struct image
*));
5398 static int x_build_heuristic_mask
P_ ((struct frame
*, Lisp_Object
,
5399 struct image
*, Lisp_Object
));
5402 /* Define a new image type from TYPE. This adds a copy of TYPE to
5403 image_types and adds the symbol *TYPE->type to Vimage_types. */
5406 define_image_type (type
)
5407 struct image_type
*type
;
5409 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5410 The initialized data segment is read-only. */
5411 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5412 bcopy (type
, p
, sizeof *p
);
5413 p
->next
= image_types
;
5415 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5419 /* Look up image type SYMBOL, and return a pointer to its image_type
5420 structure. Value is null if SYMBOL is not a known image type. */
5422 static INLINE
struct image_type
*
5423 lookup_image_type (symbol
)
5426 struct image_type
*type
;
5428 for (type
= image_types
; type
; type
= type
->next
)
5429 if (EQ (symbol
, *type
->type
))
5436 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5437 valid image specification is a list whose car is the symbol
5438 `image', and whose rest is a property list. The property list must
5439 contain a value for key `:type'. That value must be the name of a
5440 supported image type. The rest of the property list depends on the
5444 valid_image_p (object
)
5449 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5451 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5452 struct image_type
*type
= lookup_image_type (symbol
);
5455 valid_p
= type
->valid_p (object
);
5462 /* Display an error message with format string FORMAT and argument
5463 ARG. Signaling an error, e.g. when an image cannot be loaded,
5464 is not a good idea because this would interrupt redisplay, and
5465 the error message display would lead to another redisplay. This
5466 function therefore simply displays a message. */
5469 image_error (format
, arg1
, arg2
)
5471 Lisp_Object arg1
, arg2
;
5473 Lisp_Object args
[3];
5475 args
[0] = build_string (format
);
5478 Fmessage (make_number (DIM (args
)), args
);
5483 /***********************************************************************
5484 Image specifications
5485 ***********************************************************************/
5487 enum image_value_type
5489 IMAGE_DONT_CHECK_VALUE_TYPE
,
5492 IMAGE_POSITIVE_INTEGER_VALUE
,
5493 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5494 IMAGE_INTEGER_VALUE
,
5495 IMAGE_FUNCTION_VALUE
,
5500 /* Structure used when parsing image specifications. */
5502 struct image_keyword
5504 /* Name of keyword. */
5507 /* The type of value allowed. */
5508 enum image_value_type type
;
5510 /* Non-zero means key must be present. */
5513 /* Used to recognize duplicate keywords in a property list. */
5516 /* The value that was found. */
5521 static int parse_image_spec
P_ ((Lisp_Object spec
,
5522 struct image_keyword
*keywords
,
5523 int nkeywords
, Lisp_Object type
,
5524 int allow_other_keys_p
));
5525 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5528 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5529 has the format (image KEYWORD VALUE ...). One of the keyword/
5530 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5531 image_keywords structures of size NKEYWORDS describing other
5532 allowed keyword/value pairs. ALLOW_OTHER_KEYS_P non-zero means
5533 allow KEYWORD/VALUE pairs other than those described by KEYWORDS
5534 without checking them. Value is non-zero if SPEC is valid. */
5537 parse_image_spec (spec
, keywords
, nkeywords
, type
, allow_other_keys_p
)
5539 struct image_keyword
*keywords
;
5542 int allow_other_keys_p
;
5547 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5550 plist
= XCDR (spec
);
5551 while (CONSP (plist
))
5553 Lisp_Object key
, value
;
5555 /* First element of a pair must be a symbol. */
5557 plist
= XCDR (plist
);
5561 /* There must follow a value. */
5564 value
= XCAR (plist
);
5565 plist
= XCDR (plist
);
5567 /* Find key in KEYWORDS. Error if not found. */
5568 for (i
= 0; i
< nkeywords
; ++i
)
5569 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5574 if (!allow_other_keys_p
)
5579 /* Record that we recognized the keyword. If a keywords
5580 was found more than once, it's an error. */
5581 keywords
[i
].value
= value
;
5582 ++keywords
[i
].count
;
5584 if (keywords
[i
].count
> 1)
5587 /* Check type of value against allowed type. */
5588 switch (keywords
[i
].type
)
5590 case IMAGE_STRING_VALUE
:
5591 if (!STRINGP (value
))
5595 case IMAGE_SYMBOL_VALUE
:
5596 if (!SYMBOLP (value
))
5600 case IMAGE_POSITIVE_INTEGER_VALUE
:
5601 if (!INTEGERP (value
) || XINT (value
) <= 0)
5605 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5606 if (!INTEGERP (value
) || XINT (value
) < 0)
5610 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5613 case IMAGE_FUNCTION_VALUE
:
5614 value
= indirect_function (value
);
5616 || COMPILEDP (value
)
5617 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5621 case IMAGE_NUMBER_VALUE
:
5622 if (!INTEGERP (value
) && !FLOATP (value
))
5626 case IMAGE_INTEGER_VALUE
:
5627 if (!INTEGERP (value
))
5631 case IMAGE_BOOL_VALUE
:
5632 if (!NILP (value
) && !EQ (value
, Qt
))
5641 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5645 /* Check that all mandatory fields are present. */
5646 for (i
= 0; i
< nkeywords
; ++i
)
5647 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5650 return NILP (plist
);
5654 /* Return the value of KEY in image specification SPEC. Value is nil
5655 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5656 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5659 image_spec_value (spec
, key
, found
)
5660 Lisp_Object spec
, key
;
5665 xassert (valid_image_p (spec
));
5667 for (tail
= XCDR (spec
);
5668 CONSP (tail
) && CONSP (XCDR (tail
));
5669 tail
= XCDR (XCDR (tail
)))
5671 if (EQ (XCAR (tail
), key
))
5675 return XCAR (XCDR (tail
));
5687 /***********************************************************************
5688 Image type independent image structures
5689 ***********************************************************************/
5691 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5692 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5695 /* Allocate and return a new image structure for image specification
5696 SPEC. SPEC has a hash value of HASH. */
5698 static struct image
*
5699 make_image (spec
, hash
)
5703 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5705 xassert (valid_image_p (spec
));
5706 bzero (img
, sizeof *img
);
5707 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5708 xassert (img
->type
!= NULL
);
5710 img
->data
.lisp_val
= Qnil
;
5711 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5717 /* Free image IMG which was used on frame F, including its resources. */
5726 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5728 /* Remove IMG from the hash table of its cache. */
5730 img
->prev
->next
= img
->next
;
5732 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5735 img
->next
->prev
= img
->prev
;
5737 c
->images
[img
->id
] = NULL
;
5739 /* Free resources, then free IMG. */
5740 img
->type
->free (f
, img
);
5746 /* Prepare image IMG for display on frame F. Must be called before
5747 drawing an image. */
5750 prepare_image_for_display (f
, img
)
5756 /* We're about to display IMG, so set its timestamp to `now'. */
5758 img
->timestamp
= EMACS_SECS (t
);
5760 /* If IMG doesn't have a pixmap yet, load it now, using the image
5761 type dependent loader function. */
5762 if (img
->pixmap
== 0)
5763 img
->type
->load (f
, img
);
5768 /***********************************************************************
5769 Helper functions for X image types
5770 ***********************************************************************/
5772 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5773 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5775 Lisp_Object color_name
,
5776 unsigned long dflt
));
5778 /* Free X resources of image IMG which is used on frame F. */
5781 x_clear_image (f
, img
)
5788 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5795 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
5797 /* If display has an immutable color map, freeing colors is not
5798 necessary and some servers don't allow it. So don't do it. */
5799 if (class != StaticColor
5800 && class != StaticGray
5801 && class != TrueColor
)
5805 cmap
= DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f
)->screen
);
5806 XFreeColors (FRAME_X_DISPLAY (f
), cmap
, img
->colors
,
5811 xfree (img
->colors
);
5818 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5819 cannot be allocated, use DFLT. Add a newly allocated color to
5820 IMG->colors, so that it can be freed again. Value is the pixel
5823 static unsigned long
5824 x_alloc_image_color (f
, img
, color_name
, dflt
)
5827 Lisp_Object color_name
;
5831 unsigned long result
;
5833 xassert (STRINGP (color_name
));
5835 if (defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5837 /* This isn't called frequently so we get away with simply
5838 reallocating the color vector to the needed size, here. */
5841 (unsigned long *) xrealloc (img
->colors
,
5842 img
->ncolors
* sizeof *img
->colors
);
5843 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5844 result
= color
.pixel
;
5854 /***********************************************************************
5856 ***********************************************************************/
5858 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5861 /* Return a new, initialized image cache that is allocated from the
5862 heap. Call free_image_cache to free an image cache. */
5864 struct image_cache
*
5867 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5870 bzero (c
, sizeof *c
);
5872 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5873 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5874 c
->buckets
= (struct image
**) xmalloc (size
);
5875 bzero (c
->buckets
, size
);
5880 /* Free image cache of frame F. Be aware that X frames share images
5884 free_image_cache (f
)
5887 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5892 /* Cache should not be referenced by any frame when freed. */
5893 xassert (c
->refcount
== 0);
5895 for (i
= 0; i
< c
->used
; ++i
)
5896 free_image (f
, c
->images
[i
]);
5900 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5905 /* Clear image cache of frame F. FORCE_P non-zero means free all
5906 images. FORCE_P zero means clear only images that haven't been
5907 displayed for some time. Should be called from time to time to
5908 reduce the number of loaded images. If image-eviction-seconds is
5909 non-nil, this frees images in the cache which weren't displayed for
5910 at least that many seconds. */
5913 clear_image_cache (f
, force_p
)
5917 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5919 if (c
&& INTEGERP (Vimage_eviction_seconds
))
5923 int i
, any_freed_p
= 0;
5926 old
= EMACS_SECS (t
) - XFASTINT (Vimage_eviction_seconds
);
5928 for (i
= 0; i
< c
->used
; ++i
)
5930 struct image
*img
= c
->images
[i
];
5933 || (img
->timestamp
> old
)))
5935 free_image (f
, img
);
5940 /* We may be clearing the image cache because, for example,
5941 Emacs was iconified for a longer period of time. In that
5942 case, current matrices may still contain references to
5943 images freed above. So, clear these matrices. */
5946 clear_current_matrices (f
);
5947 ++windows_or_buffers_changed
;
5953 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5955 "Clear the image cache of FRAME.\n\
5956 FRAME nil or omitted means use the selected frame.\n\
5957 FRAME t means clear the image caches of all frames.")
5965 FOR_EACH_FRAME (tail
, frame
)
5966 if (FRAME_X_P (XFRAME (frame
)))
5967 clear_image_cache (XFRAME (frame
), 1);
5970 clear_image_cache (check_x_frame (frame
), 1);
5976 /* Return the id of image with Lisp specification SPEC on frame F.
5977 SPEC must be a valid Lisp image specification (see valid_image_p). */
5980 lookup_image (f
, spec
)
5984 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5988 struct gcpro gcpro1
;
5990 /* F must be a window-system frame, and SPEC must be a valid image
5992 xassert (FRAME_WINDOW_P (f
));
5993 xassert (valid_image_p (spec
));
5997 /* Look up SPEC in the hash table of the image cache. */
5998 hash
= sxhash (spec
, 0);
5999 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6001 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6002 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6005 /* If not found, create a new image and cache it. */
6008 extern Lisp_Object QCenable
, QCselect
;
6010 int loading_failed_p
;
6012 img
= make_image (spec
, hash
);
6013 cache_image (f
, img
);
6014 loading_failed_p
= img
->type
->load (f
, img
) == 0;
6016 /* If we can't load the image, and we don't have a width and
6017 height, use some arbitrary width and height so that we can
6018 draw a rectangle for it. */
6019 if (loading_failed_p
)
6023 value
= image_spec_value (spec
, QCwidth
, NULL
);
6024 img
->width
= (INTEGERP (value
)
6025 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6026 value
= image_spec_value (spec
, QCheight
, NULL
);
6027 img
->height
= (INTEGERP (value
)
6028 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6032 /* Handle image type independent image attributes
6033 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
6034 Lisp_Object ascent
, margin
, relief
, algorithm
, heuristic_mask
;
6037 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6038 if (INTEGERP (ascent
))
6039 img
->ascent
= XFASTINT (ascent
);
6041 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6042 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6043 img
->margin
= XFASTINT (margin
);
6045 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6046 if (INTEGERP (relief
))
6048 img
->relief
= XINT (relief
);
6049 img
->margin
+= abs (img
->relief
);
6052 /* Should we apply a Laplace edge-detection algorithm? */
6053 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
6054 if (img
->pixmap
&& EQ (algorithm
, Qlaplace
))
6057 /* Should we built a mask heuristically? */
6058 heuristic_mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6059 if (img
->pixmap
&& !img
->mask
&& !NILP (heuristic_mask
))
6061 file
= image_spec_value (spec
, QCfile
, NULL
);
6062 x_build_heuristic_mask (f
, file
, img
, heuristic_mask
);
6069 /* Value is the image id. */
6074 /* Cache image IMG in the image cache of frame F. */
6077 cache_image (f
, img
)
6081 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6084 /* Find a free slot in c->images. */
6085 for (i
= 0; i
< c
->used
; ++i
)
6086 if (c
->images
[i
] == NULL
)
6089 /* If no free slot found, maybe enlarge c->images. */
6090 if (i
== c
->used
&& c
->used
== c
->size
)
6093 c
->images
= (struct image
**) xrealloc (c
->images
,
6094 c
->size
* sizeof *c
->images
);
6097 /* Add IMG to c->images, and assign IMG an id. */
6103 /* Add IMG to the cache's hash table. */
6104 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6105 img
->next
= c
->buckets
[i
];
6107 img
->next
->prev
= img
;
6109 c
->buckets
[i
] = img
;
6113 /* Call FN on every image in the image cache of frame F. Used to mark
6114 Lisp Objects in the image cache. */
6117 forall_images_in_image_cache (f
, fn
)
6119 void (*fn
) P_ ((struct image
*img
));
6121 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6123 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6127 for (i
= 0; i
< c
->used
; ++i
)
6136 /***********************************************************************
6138 ***********************************************************************/
6140 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, Lisp_Object
,
6141 int, int, int, XImage
**,
6143 static void x_destroy_x_image
P_ ((XImage
*));
6144 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6147 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6148 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6149 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6150 via xmalloc. Print error messages via image_error if an error
6151 occurs. FILE is the name of an image file being processed, for
6152 error messages. Value is non-zero if successful. */
6155 x_create_x_image_and_pixmap (f
, file
, width
, height
, depth
, ximg
, pixmap
)
6158 int width
, height
, depth
;
6162 Display
*display
= FRAME_X_DISPLAY (f
);
6163 Screen
*screen
= FRAME_X_SCREEN (f
);
6164 Window window
= FRAME_X_WINDOW (f
);
6166 xassert (interrupt_input_blocked
);
6169 depth
= DefaultDepthOfScreen (screen
);
6170 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6171 depth
, ZPixmap
, 0, NULL
, width
, height
,
6172 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6175 image_error ("Unable to allocate X image for %s", file
, Qnil
);
6179 /* Allocate image raster. */
6180 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6182 /* Allocate a pixmap of the same size. */
6183 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6186 x_destroy_x_image (*ximg
);
6188 image_error ("Unable to create pixmap for `%s'", file
, Qnil
);
6196 /* Destroy XImage XIMG. Free XIMG->data. */
6199 x_destroy_x_image (ximg
)
6202 xassert (interrupt_input_blocked
);
6207 XDestroyImage (ximg
);
6212 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6213 are width and height of both the image and pixmap. */
6216 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6223 xassert (interrupt_input_blocked
);
6224 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6225 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6226 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6231 /***********************************************************************
6233 ***********************************************************************/
6235 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6237 /* Find image file FILE. Look in data-directory, then
6238 x-bitmap-file-path. Value is the full name of the file found, or
6239 nil if not found. */
6242 x_find_image_file (file
)
6245 Lisp_Object file_found
, search_path
;
6246 struct gcpro gcpro1
, gcpro2
;
6250 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6251 GCPRO2 (file_found
, search_path
);
6253 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6254 fd
= openp (search_path
, file
, "", &file_found
, 0);
6267 /***********************************************************************
6269 ***********************************************************************/
6271 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6272 static int xbm_load_image_from_file
P_ ((struct frame
*f
, struct image
*img
,
6274 static int xbm_image_p
P_ ((Lisp_Object object
));
6275 static int xbm_read_bitmap_file_data
P_ ((char *, int *, int *,
6277 static int xbm_read_hexint
P_ ((FILE *));
6280 /* Indices of image specification fields in xbm_format, below. */
6282 enum xbm_keyword_index
6299 /* Vector of image_keyword structures describing the format
6300 of valid XBM image specifications. */
6302 static struct image_keyword xbm_format
[XBM_LAST
] =
6304 {":type", IMAGE_SYMBOL_VALUE
, 1},
6305 {":file", IMAGE_STRING_VALUE
, 0},
6306 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6307 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6308 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6309 {":foreground", IMAGE_STRING_VALUE
, 0},
6310 {":background", IMAGE_STRING_VALUE
, 0},
6311 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6312 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6313 {":relief", IMAGE_INTEGER_VALUE
, 0},
6314 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6315 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6318 /* Structure describing the image type XBM. */
6320 static struct image_type xbm_type
=
6329 /* Tokens returned from xbm_scan. */
6338 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6339 A valid specification is a list starting with the symbol `image'
6340 The rest of the list is a property list which must contain an
6343 If the specification specifies a file to load, it must contain
6344 an entry `:file FILENAME' where FILENAME is a string.
6346 If the specification is for a bitmap loaded from memory it must
6347 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6348 WIDTH and HEIGHT are integers > 0. DATA may be:
6350 1. a string large enough to hold the bitmap data, i.e. it must
6351 have a size >= (WIDTH + 7) / 8 * HEIGHT
6353 2. a bool-vector of size >= WIDTH * HEIGHT
6355 3. a vector of strings or bool-vectors, one for each line of the
6358 Both the file and data forms may contain the additional entries
6359 `:background COLOR' and `:foreground COLOR'. If not present,
6360 foreground and background of the frame on which the image is
6361 displayed, is used. */
6364 xbm_image_p (object
)
6367 struct image_keyword kw
[XBM_LAST
];
6369 bcopy (xbm_format
, kw
, sizeof kw
);
6370 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
, 0))
6373 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6375 if (kw
[XBM_FILE
].count
)
6377 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6385 /* Entries for `:width', `:height' and `:data' must be present. */
6386 if (!kw
[XBM_WIDTH
].count
6387 || !kw
[XBM_HEIGHT
].count
6388 || !kw
[XBM_DATA
].count
)
6391 data
= kw
[XBM_DATA
].value
;
6392 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6393 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6395 /* Check type of data, and width and height against contents of
6401 /* Number of elements of the vector must be >= height. */
6402 if (XVECTOR (data
)->size
< height
)
6405 /* Each string or bool-vector in data must be large enough
6406 for one line of the image. */
6407 for (i
= 0; i
< height
; ++i
)
6409 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6413 if (XSTRING (elt
)->size
6414 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6417 else if (BOOL_VECTOR_P (elt
))
6419 if (XBOOL_VECTOR (elt
)->size
< width
)
6426 else if (STRINGP (data
))
6428 if (XSTRING (data
)->size
6429 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6432 else if (BOOL_VECTOR_P (data
))
6434 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6441 /* Baseline must be a value between 0 and 100 (a percentage). */
6442 if (kw
[XBM_ASCENT
].count
6443 && XFASTINT (kw
[XBM_ASCENT
].value
) > 100)
6450 /* Scan a bitmap file. FP is the stream to read from. Value is
6451 either an enumerator from enum xbm_token, or a character for a
6452 single-character token, or 0 at end of file. If scanning an
6453 identifier, store the lexeme of the identifier in SVAL. If
6454 scanning a number, store its value in *IVAL. */
6457 xbm_scan (fp
, sval
, ival
)
6464 /* Skip white space. */
6465 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
6470 else if (isdigit (c
))
6472 int value
= 0, digit
;
6477 if (c
== 'x' || c
== 'X')
6479 while ((c
= fgetc (fp
)) != EOF
)
6483 else if (c
>= 'a' && c
<= 'f')
6484 digit
= c
- 'a' + 10;
6485 else if (c
>= 'A' && c
<= 'F')
6486 digit
= c
- 'A' + 10;
6489 value
= 16 * value
+ digit
;
6492 else if (isdigit (c
))
6495 while ((c
= fgetc (fp
)) != EOF
6497 value
= 8 * value
+ c
- '0';
6503 while ((c
= fgetc (fp
)) != EOF
6505 value
= 10 * value
+ c
- '0';
6513 else if (isalpha (c
) || c
== '_')
6516 while ((c
= fgetc (fp
)) != EOF
6517 && (isalnum (c
) || c
== '_'))
6529 /* Replacement for XReadBitmapFileData which isn't available under old
6530 X versions. FILE is the name of the bitmap file to read. Set
6531 *WIDTH and *HEIGHT to the width and height of the image. Return in
6532 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
6536 xbm_read_bitmap_file_data (file
, width
, height
, data
)
6538 int *width
, *height
;
6539 unsigned char **data
;
6542 char buffer
[BUFSIZ
];
6545 int bytes_per_line
, i
, nbytes
;
6551 LA1 = xbm_scan (fp, buffer, &value)
6553 #define expect(TOKEN) \
6554 if (LA1 != (TOKEN)) \
6559 #define expect_ident(IDENT) \
6560 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6565 fp
= fopen (file
, "r");
6569 *width
= *height
= -1;
6571 LA1
= xbm_scan (fp
, buffer
, &value
);
6573 /* Parse defines for width, height and hot-spots. */
6579 expect_ident ("define");
6580 expect (XBM_TK_IDENT
);
6582 if (LA1
== XBM_TK_NUMBER
);
6584 char *p
= strrchr (buffer
, '_');
6585 p
= p
? p
+ 1 : buffer
;
6586 if (strcmp (p
, "width") == 0)
6588 else if (strcmp (p
, "height") == 0)
6591 expect (XBM_TK_NUMBER
);
6594 if (*width
< 0 || *height
< 0)
6597 /* Parse bits. Must start with `static'. */
6598 expect_ident ("static");
6599 if (LA1
== XBM_TK_IDENT
)
6601 if (strcmp (buffer
, "unsigned") == 0)
6604 expect_ident ("char");
6606 else if (strcmp (buffer
, "short") == 0)
6610 if (*width
% 16 && *width
% 16 < 9)
6613 else if (strcmp (buffer
, "char") == 0)
6621 expect (XBM_TK_IDENT
);
6627 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6628 nbytes
= bytes_per_line
* *height
;
6629 p
= *data
= (char *) xmalloc (nbytes
);
6634 for (i
= 0; i
< nbytes
; i
+= 2)
6637 expect (XBM_TK_NUMBER
);
6640 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6643 if (LA1
== ',' || LA1
== '}')
6651 for (i
= 0; i
< nbytes
; ++i
)
6654 expect (XBM_TK_NUMBER
);
6658 if (LA1
== ',' || LA1
== '}')
6684 /* Load XBM image IMG which will be displayed on frame F from file
6685 SPECIFIED_FILE. Value is non-zero if successful. */
6688 xbm_load_image_from_file (f
, img
, specified_file
)
6691 Lisp_Object specified_file
;
6694 unsigned char *data
;
6697 struct gcpro gcpro1
;
6699 xassert (STRINGP (specified_file
));
6703 file
= x_find_image_file (specified_file
);
6704 if (!STRINGP (file
))
6706 image_error ("Cannot find image file %s", specified_file
, Qnil
);
6711 rc
= xbm_read_bitmap_file_data (XSTRING (file
)->data
, &img
->width
,
6712 &img
->height
, &data
);
6715 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6716 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6717 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6720 xassert (img
->width
> 0 && img
->height
> 0);
6722 /* Get foreground and background colors, maybe allocate colors. */
6723 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6725 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6727 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6729 background
= x_alloc_image_color (f
, img
, value
, background
);
6733 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6736 img
->width
, img
->height
,
6737 foreground
, background
,
6741 if (img
->pixmap
== 0)
6743 x_clear_image (f
, img
);
6744 image_error ("Unable to create X pixmap for `%s'", file
, Qnil
);
6752 image_error ("Error loading XBM image %s", img
->spec
, Qnil
);
6759 /* Fill image IMG which is used on frame F with pixmap data. Value is
6760 non-zero if successful. */
6768 Lisp_Object file_name
;
6770 xassert (xbm_image_p (img
->spec
));
6772 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6773 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6774 if (STRINGP (file_name
))
6775 success_p
= xbm_load_image_from_file (f
, img
, file_name
);
6778 struct image_keyword fmt
[XBM_LAST
];
6781 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6782 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6786 /* Parse the list specification. */
6787 bcopy (xbm_format
, fmt
, sizeof fmt
);
6788 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
, 0);
6791 /* Get specified width, and height. */
6792 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6793 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6794 xassert (img
->width
> 0 && img
->height
> 0);
6798 if (fmt
[XBM_ASCENT
].count
)
6799 img
->ascent
= XFASTINT (fmt
[XBM_ASCENT
].value
);
6801 /* Get foreground and background colors, maybe allocate colors. */
6802 if (fmt
[XBM_FOREGROUND
].count
)
6803 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6805 if (fmt
[XBM_BACKGROUND
].count
)
6806 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6809 /* Set bits to the bitmap image data. */
6810 data
= fmt
[XBM_DATA
].value
;
6815 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6817 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6818 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6820 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6822 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6824 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6827 else if (STRINGP (data
))
6828 bits
= XSTRING (data
)->data
;
6830 bits
= XBOOL_VECTOR (data
)->data
;
6832 /* Create the pixmap. */
6833 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6835 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6838 img
->width
, img
->height
,
6839 foreground
, background
,
6845 image_error ("Unable to create pixmap for XBM image", Qnil
, Qnil
);
6846 x_clear_image (f
, img
);
6857 /***********************************************************************
6859 ***********************************************************************/
6863 static int xpm_image_p
P_ ((Lisp_Object object
));
6864 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6865 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6867 #include "X11/xpm.h"
6869 /* The symbol `xpm' identifying XPM-format images. */
6873 /* Indices of image specification fields in xpm_format, below. */
6875 enum xpm_keyword_index
6889 /* Vector of image_keyword structures describing the format
6890 of valid XPM image specifications. */
6892 static struct image_keyword xpm_format
[XPM_LAST
] =
6894 {":type", IMAGE_SYMBOL_VALUE
, 1},
6895 {":file", IMAGE_STRING_VALUE
, 0},
6896 {":data", IMAGE_STRING_VALUE
, 0},
6897 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6898 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6899 {":relief", IMAGE_INTEGER_VALUE
, 0},
6900 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6901 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6902 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6905 /* Structure describing the image type XBM. */
6907 static struct image_type xpm_type
=
6917 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6918 for XPM images. Such a list must consist of conses whose car and
6922 xpm_valid_color_symbols_p (color_symbols
)
6923 Lisp_Object color_symbols
;
6925 while (CONSP (color_symbols
))
6927 Lisp_Object sym
= XCAR (color_symbols
);
6929 || !STRINGP (XCAR (sym
))
6930 || !STRINGP (XCDR (sym
)))
6932 color_symbols
= XCDR (color_symbols
);
6935 return NILP (color_symbols
);
6939 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6942 xpm_image_p (object
)
6945 struct image_keyword fmt
[XPM_LAST
];
6946 bcopy (xpm_format
, fmt
, sizeof fmt
);
6947 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
, 0)
6948 /* Either `:file' or `:data' must be present. */
6949 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
6950 /* Either no `:color-symbols' or it's a list of conses
6951 whose car and cdr are strings. */
6952 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
6953 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
))
6954 && (fmt
[XPM_ASCENT
].count
== 0
6955 || XFASTINT (fmt
[XPM_ASCENT
].value
) < 100));
6959 /* Load image IMG which will be displayed on frame F. Value is
6960 non-zero if successful. */
6968 XpmAttributes attrs
;
6969 Lisp_Object specified_file
, color_symbols
;
6971 /* Configure the XPM lib. Use the visual of frame F. Allocate
6972 close colors. Return colors allocated. */
6973 bzero (&attrs
, sizeof attrs
);
6974 attrs
.visual
= FRAME_X_DISPLAY_INFO (f
)->visual
;
6975 attrs
.valuemask
|= XpmVisual
;
6976 attrs
.valuemask
|= XpmReturnAllocPixels
;
6977 #ifdef XpmAllocCloseColors
6978 attrs
.alloc_close_colors
= 1;
6979 attrs
.valuemask
|= XpmAllocCloseColors
;
6981 attrs
.closeness
= 600;
6982 attrs
.valuemask
|= XpmCloseness
;
6985 /* If image specification contains symbolic color definitions, add
6986 these to `attrs'. */
6987 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
6988 if (CONSP (color_symbols
))
6991 XpmColorSymbol
*xpm_syms
;
6994 attrs
.valuemask
|= XpmColorSymbols
;
6996 /* Count number of symbols. */
6997 attrs
.numsymbols
= 0;
6998 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7001 /* Allocate an XpmColorSymbol array. */
7002 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7003 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7004 bzero (xpm_syms
, size
);
7005 attrs
.colorsymbols
= xpm_syms
;
7007 /* Fill the color symbol array. */
7008 for (tail
= color_symbols
, i
= 0;
7010 ++i
, tail
= XCDR (tail
))
7012 Lisp_Object name
= XCAR (XCAR (tail
));
7013 Lisp_Object color
= XCDR (XCAR (tail
));
7014 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7015 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7016 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7017 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7021 /* Create a pixmap for the image, either from a file, or from a
7022 string buffer containing data in the same format as an XPM file. */
7024 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7025 if (STRINGP (specified_file
))
7027 Lisp_Object file
= x_find_image_file (specified_file
);
7028 if (!STRINGP (file
))
7030 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7034 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7035 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7040 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7041 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7042 XSTRING (buffer
)->data
,
7043 &img
->pixmap
, &img
->mask
,
7048 if (rc
== XpmSuccess
)
7050 /* Remember allocated colors. */
7051 img
->ncolors
= attrs
.nalloc_pixels
;
7052 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7053 * sizeof *img
->colors
);
7054 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7055 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7057 img
->width
= attrs
.width
;
7058 img
->height
= attrs
.height
;
7059 xassert (img
->width
> 0 && img
->height
> 0);
7061 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7063 XpmFreeAttributes (&attrs
);
7071 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7074 case XpmFileInvalid
:
7075 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7079 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7082 case XpmColorFailed
:
7083 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7087 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7092 return rc
== XpmSuccess
;
7095 #endif /* HAVE_XPM != 0 */
7098 /***********************************************************************
7100 ***********************************************************************/
7102 /* An entry in the color table mapping an RGB color to a pixel color. */
7107 unsigned long pixel
;
7109 /* Next in color table collision list. */
7110 struct ct_color
*next
;
7113 /* The bucket vector size to use. Must be prime. */
7117 /* Value is a hash of the RGB color given by R, G, and B. */
7119 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7121 /* The color hash table. */
7123 struct ct_color
**ct_table
;
7125 /* Number of entries in the color table. */
7127 int ct_colors_allocated
;
7129 /* Function prototypes. */
7131 static void init_color_table
P_ ((void));
7132 static void free_color_table
P_ ((void));
7133 static unsigned long *colors_in_color_table
P_ ((int *n
));
7134 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
7135 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
7138 /* Initialize the color table. */
7143 int size
= CT_SIZE
* sizeof (*ct_table
);
7144 ct_table
= (struct ct_color
**) xmalloc (size
);
7145 bzero (ct_table
, size
);
7146 ct_colors_allocated
= 0;
7150 /* Free memory associated with the color table. */
7156 struct ct_color
*p
, *next
;
7158 for (i
= 0; i
< CT_SIZE
; ++i
)
7159 for (p
= ct_table
[i
]; p
; p
= next
)
7170 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7171 entry for that color already is in the color table, return the
7172 pixel color of that entry. Otherwise, allocate a new color for R,
7173 G, B, and make an entry in the color table. */
7175 static unsigned long
7176 lookup_rgb_color (f
, r
, g
, b
)
7180 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7181 int i
= hash
% CT_SIZE
;
7184 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7185 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7199 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7200 rc
= x_alloc_nearest_color (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN (f
),
7206 ++ct_colors_allocated
;
7208 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7212 p
->pixel
= color
.pixel
;
7213 p
->next
= ct_table
[i
];
7217 return FRAME_FOREGROUND_PIXEL (f
);
7224 /* Look up pixel color PIXEL which is used on frame F in the color
7225 table. If not already present, allocate it. Value is PIXEL. */
7227 static unsigned long
7228 lookup_pixel_color (f
, pixel
)
7230 unsigned long pixel
;
7232 int i
= pixel
% CT_SIZE
;
7235 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7236 if (p
->pixel
== pixel
)
7247 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7248 color
.pixel
= pixel
;
7249 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7250 rc
= x_alloc_nearest_color (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN (f
),
7256 ++ct_colors_allocated
;
7258 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7263 p
->next
= ct_table
[i
];
7267 return FRAME_FOREGROUND_PIXEL (f
);
7274 /* Value is a vector of all pixel colors contained in the color table,
7275 allocated via xmalloc. Set *N to the number of colors. */
7277 static unsigned long *
7278 colors_in_color_table (n
)
7283 unsigned long *colors
;
7285 if (ct_colors_allocated
== 0)
7292 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7294 *n
= ct_colors_allocated
;
7296 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7297 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7298 colors
[j
++] = p
->pixel
;
7306 /***********************************************************************
7308 ***********************************************************************/
7310 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7311 int, XImage
*, int));
7312 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7313 XColor
*, int, XImage
*, int));
7316 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7317 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7318 the width of one row in the image. */
7321 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
7331 for (x
= 0; x
< width
; ++x
)
7332 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
7334 XQueryColors (FRAME_X_DISPLAY (f
), cmap
, colors
, width
);
7338 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7339 containing the pixel colors to write. F is the frame we are
7343 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
7352 for (x
= 0; x
< width
; ++x
)
7353 XPutPixel (ximg
, x
, y
, pixels
[x
]);
7357 /* Transform image IMG which is used on frame F with a Laplace
7358 edge-detection algorithm. The result is an image that can be used
7359 to draw disabled buttons, for example. */
7366 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7367 XImage
*ximg
, *oimg
;
7373 int in_y
, out_y
, rc
;
7378 /* Get the X image IMG->pixmap. */
7379 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7380 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7382 /* Allocate 3 input rows, and one output row of colors. */
7383 for (i
= 0; i
< 3; ++i
)
7384 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
7385 out
= (long *) alloca (img
->width
* sizeof (long));
7387 /* Create an X image for output. */
7388 rc
= x_create_x_image_and_pixmap (f
, Qnil
, img
->width
, img
->height
, 0,
7391 /* Fill first two rows. */
7392 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
7393 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
7396 /* Write first row, all zeros. */
7397 init_color_table ();
7398 pixel
= lookup_rgb_color (f
, 0, 0, 0);
7399 for (x
= 0; x
< img
->width
; ++x
)
7401 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
7404 for (y
= 2; y
< img
->height
; ++y
)
7407 int rowb
= (y
+ 2) % 3;
7409 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
7411 for (x
= 0; x
< img
->width
- 2; ++x
)
7413 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
7414 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
7415 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
7417 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
7421 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
7424 /* Write last line, all zeros. */
7425 for (x
= 0; x
< img
->width
; ++x
)
7427 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
7429 /* Free the input image, and free resources of IMG. */
7430 XDestroyImage (ximg
);
7431 x_clear_image (f
, img
);
7433 /* Put the output image into pixmap, and destroy it. */
7434 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7435 x_destroy_x_image (oimg
);
7437 /* Remember new pixmap and colors in IMG. */
7438 img
->pixmap
= pixmap
;
7439 img
->colors
= colors_in_color_table (&img
->ncolors
);
7440 free_color_table ();
7446 /* Build a mask for image IMG which is used on frame F. FILE is the
7447 name of an image file, for error messages. HOW determines how to
7448 determine the background color of IMG. If it is an integer, take
7449 that as the pixel value of the background. Otherwise, determine
7450 the background color of IMG heuristically. Value is non-zero
7454 x_build_heuristic_mask (f
, file
, img
, how
)
7460 Display
*dpy
= FRAME_X_DISPLAY (f
);
7461 Window win
= FRAME_X_WINDOW (f
);
7462 XImage
*ximg
, *mask_img
;
7468 /* Create an image and pixmap serving as mask. */
7469 rc
= x_create_x_image_and_pixmap (f
, file
, img
->width
, img
->height
, 1,
7470 &mask_img
, &img
->mask
);
7477 /* Get the X image of IMG->pixmap. */
7478 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7481 /* Determine the background color of ximg. If HOW is an integer,
7482 take that as a pixel color. Otherwise, try to determine the
7483 color heuristically. */
7485 bg
= XFASTINT (how
);
7488 unsigned long corners
[4];
7491 /* Get the colors at the corners of ximg. */
7492 corners
[0] = XGetPixel (ximg
, 0, 0);
7493 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7494 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7495 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7497 /* Choose the most frequently found color as background. */
7498 for (i
= best_count
= 0; i
< 4; ++i
)
7502 for (j
= n
= 0; j
< 4; ++j
)
7503 if (corners
[i
] == corners
[j
])
7507 bg
= corners
[i
], best_count
= n
;
7511 /* Set all bits in mask_img to 1 whose color in ximg is different
7512 from the background color bg. */
7513 for (y
= 0; y
< img
->height
; ++y
)
7514 for (x
= 0; x
< img
->width
; ++x
)
7515 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7517 /* Put mask_img into img->mask. */
7518 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7519 x_destroy_x_image (mask_img
);
7520 XDestroyImage (ximg
);
7528 /***********************************************************************
7529 PBM (mono, gray, color)
7530 ***********************************************************************/
7532 static int pbm_image_p
P_ ((Lisp_Object object
));
7533 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7534 static int pbm_scan_number
P_ ((FILE *fp
));
7536 /* The symbol `pbm' identifying images of this type. */
7540 /* Indices of image specification fields in gs_format, below. */
7542 enum pbm_keyword_index
7554 /* Vector of image_keyword structures describing the format
7555 of valid user-defined image specifications. */
7557 static struct image_keyword pbm_format
[PBM_LAST
] =
7559 {":type", IMAGE_SYMBOL_VALUE
, 1},
7560 {":file", IMAGE_STRING_VALUE
, 1},
7561 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7562 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7563 {":relief", IMAGE_INTEGER_VALUE
, 0},
7564 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7565 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7568 /* Structure describing the image type `pbm'. */
7570 static struct image_type pbm_type
=
7580 /* Return non-zero if OBJECT is a valid PBM image specification. */
7583 pbm_image_p (object
)
7586 struct image_keyword fmt
[PBM_LAST
];
7588 bcopy (pbm_format
, fmt
, sizeof fmt
);
7590 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
, 0)
7591 || (fmt
[PBM_ASCENT
].count
7592 && XFASTINT (fmt
[PBM_ASCENT
].value
) > 100))
7598 /* Scan a decimal number from PBM input file FP and return it. Value
7599 is -1 at end of file or if an error occurs. */
7602 pbm_scan_number (fp
)
7609 /* Skip white-space. */
7610 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
7615 /* Skip comment to end of line. */
7616 while ((c
= fgetc (fp
)) != EOF
&& c
!= '\n')
7619 else if (isdigit (c
))
7621 /* Read decimal number. */
7623 while ((c
= fgetc (fp
)) != EOF
&& isdigit (c
))
7624 val
= 10 * val
+ c
- '0';
7635 /* Load PBM image IMG for use on frame F. */
7645 int width
, height
, max_color_idx
= 0, value
;
7647 Lisp_Object file
, specified_file
;
7648 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
7649 struct gcpro gcpro1
;
7651 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7652 file
= x_find_image_file (specified_file
);
7654 if (!STRINGP (file
))
7656 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7661 fp
= fopen (XSTRING (file
)->data
, "r");
7668 /* Read first two characters. */
7669 if (fread (magic
, sizeof *magic
, 2, fp
) != 2)
7672 image_error ("Not a PBM image file: %s", file
, Qnil
);
7680 image_error ("Not a PBM image file: %s", file
, Qnil
);
7688 raw_p
= 0, type
= PBM_MONO
;
7692 raw_p
= 0, type
= PBM_GRAY
;
7696 raw_p
= 0, type
= PBM_COLOR
;
7700 raw_p
= 1, type
= PBM_MONO
;
7704 raw_p
= 1, type
= PBM_GRAY
;
7708 raw_p
= 1, type
= PBM_COLOR
;
7713 image_error ("Not a PBM image file: %s", file
, Qnil
);
7718 /* Read width, height, maximum color-component. Characters
7719 starting with `#' up to the end of a line are ignored. */
7720 width
= pbm_scan_number (fp
);
7721 height
= pbm_scan_number (fp
);
7723 if (type
!= PBM_MONO
)
7725 max_color_idx
= pbm_scan_number (fp
);
7726 if (raw_p
&& max_color_idx
> 255)
7727 max_color_idx
= 255;
7730 if (width
< 0 || height
< 0
7731 || (type
!= PBM_MONO
&& max_color_idx
< 0))
7739 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0,
7740 &ximg
, &img
->pixmap
))
7748 /* Initialize the color hash table. */
7749 init_color_table ();
7751 if (type
== PBM_MONO
)
7755 for (y
= 0; y
< height
; ++y
)
7756 for (x
= 0; x
< width
; ++x
)
7766 g
= pbm_scan_number (fp
);
7768 XPutPixel (ximg
, x
, y
, (g
7769 ? FRAME_FOREGROUND_PIXEL (f
)
7770 : FRAME_BACKGROUND_PIXEL (f
)));
7775 for (y
= 0; y
< height
; ++y
)
7776 for (x
= 0; x
< width
; ++x
)
7780 if (type
== PBM_GRAY
)
7781 r
= g
= b
= raw_p
? fgetc (fp
) : pbm_scan_number (fp
);
7790 r
= pbm_scan_number (fp
);
7791 g
= pbm_scan_number (fp
);
7792 b
= pbm_scan_number (fp
);
7795 if (r
< 0 || g
< 0 || b
< 0)
7800 XDestroyImage (ximg
);
7802 image_error ("Invalid pixel value in file `%s'",
7808 /* RGB values are now in the range 0..max_color_idx.
7809 Scale this to the range 0..0xffff supported by X. */
7810 r
= (double) r
* 65535 / max_color_idx
;
7811 g
= (double) g
* 65535 / max_color_idx
;
7812 b
= (double) b
* 65535 / max_color_idx
;
7813 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
7819 /* Store in IMG->colors the colors allocated for the image, and
7820 free the color table. */
7821 img
->colors
= colors_in_color_table (&img
->ncolors
);
7822 free_color_table ();
7824 /* Put the image into a pixmap. */
7825 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7826 x_destroy_x_image (ximg
);
7830 img
->height
= height
;
7838 /***********************************************************************
7840 ***********************************************************************/
7846 /* Function prototypes. */
7848 static int png_image_p
P_ ((Lisp_Object object
));
7849 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
7851 /* The symbol `png' identifying images of this type. */
7855 /* Indices of image specification fields in png_format, below. */
7857 enum png_keyword_index
7869 /* Vector of image_keyword structures describing the format
7870 of valid user-defined image specifications. */
7872 static struct image_keyword png_format
[PNG_LAST
] =
7874 {":type", IMAGE_SYMBOL_VALUE
, 1},
7875 {":file", IMAGE_STRING_VALUE
, 1},
7876 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7877 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7878 {":relief", IMAGE_INTEGER_VALUE
, 0},
7879 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7880 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7883 /* Structure describing the image type `gif'. */
7885 static struct image_type png_type
=
7895 /* Return non-zero if OBJECT is a valid PNG image specification. */
7898 png_image_p (object
)
7901 struct image_keyword fmt
[PNG_LAST
];
7902 bcopy (png_format
, fmt
, sizeof fmt
);
7904 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
, 1)
7905 || (fmt
[PNG_ASCENT
].count
7906 && XFASTINT (fmt
[PNG_ASCENT
].value
) > 100))
7912 /* Error and warning handlers installed when the PNG library
7916 my_png_error (png_ptr
, msg
)
7917 png_struct
*png_ptr
;
7920 xassert (png_ptr
!= NULL
);
7921 image_error ("PNG error: %s", build_string (msg
), Qnil
);
7922 longjmp (png_ptr
->jmpbuf
, 1);
7927 my_png_warning (png_ptr
, msg
)
7928 png_struct
*png_ptr
;
7931 xassert (png_ptr
!= NULL
);
7932 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
7936 /* Load PNG image IMG for use on frame F. Value is non-zero if
7944 Lisp_Object file
, specified_file
;
7946 XImage
*ximg
, *mask_img
= NULL
;
7947 struct gcpro gcpro1
;
7948 png_struct
*png_ptr
= NULL
;
7949 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
7952 png_byte
*pixels
= NULL
;
7953 png_byte
**rows
= NULL
;
7954 png_uint_32 width
, height
;
7955 int bit_depth
, color_type
, interlace_type
;
7957 png_uint_32 row_bytes
;
7960 double screen_gamma
, image_gamma
;
7963 /* Find out what file to load. */
7964 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7965 file
= x_find_image_file (specified_file
);
7967 if (!STRINGP (file
))
7969 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7974 /* Open the image file. */
7975 fp
= fopen (XSTRING (file
)->data
, "rb");
7978 image_error ("Cannot open image file %s", file
, Qnil
);
7984 /* Check PNG signature. */
7985 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
7986 || !png_check_sig (sig
, sizeof sig
))
7988 image_error ("Not a PNG file: %s", file
, Qnil
);
7994 /* Initialize read and info structs for PNG lib. */
7995 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
7996 my_png_error
, my_png_warning
);
8004 info_ptr
= png_create_info_struct (png_ptr
);
8007 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8013 end_info
= png_create_info_struct (png_ptr
);
8016 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8022 /* Set error jump-back. We come back here when the PNG library
8023 detects an error. */
8024 if (setjmp (png_ptr
->jmpbuf
))
8028 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8037 /* Read image info. */
8038 png_init_io (png_ptr
, fp
);
8039 png_set_sig_bytes (png_ptr
, sizeof sig
);
8040 png_read_info (png_ptr
, info_ptr
);
8041 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8042 &interlace_type
, NULL
, NULL
);
8044 /* If image contains simply transparency data, we prefer to
8045 construct a clipping mask. */
8046 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8051 /* This function is easier to write if we only have to handle
8052 one data format: RGB or RGBA with 8 bits per channel. Let's
8053 transform other formats into that format. */
8055 /* Strip more than 8 bits per channel. */
8056 if (bit_depth
== 16)
8057 png_set_strip_16 (png_ptr
);
8059 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8061 png_set_expand (png_ptr
);
8063 /* Convert grayscale images to RGB. */
8064 if (color_type
== PNG_COLOR_TYPE_GRAY
8065 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8066 png_set_gray_to_rgb (png_ptr
);
8068 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8069 gamma_str
= getenv ("SCREEN_GAMMA");
8070 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8072 /* Tell the PNG lib to handle gamma correction for us. */
8074 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8075 /* There is a special chunk in the image specifying the gamma. */
8076 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8077 else if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8078 /* Image contains gamma information. */
8079 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8081 /* Use a default of 0.5 for the image gamma. */
8082 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8084 /* Handle alpha channel by combining the image with a background
8085 color. Do this only if a real alpha channel is supplied. For
8086 simple transparency, we prefer a clipping mask. */
8089 png_color_16
*image_background
;
8091 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8092 /* Image contains a background color with which to
8093 combine the image. */
8094 png_set_background (png_ptr
, image_background
,
8095 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8098 /* Image does not contain a background color with which
8099 to combine the image data via an alpha channel. Use
8100 the frame's background instead. */
8103 png_color_16 frame_background
;
8106 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
8107 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8108 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
8111 bzero (&frame_background
, sizeof frame_background
);
8112 frame_background
.red
= color
.red
;
8113 frame_background
.green
= color
.green
;
8114 frame_background
.blue
= color
.blue
;
8116 png_set_background (png_ptr
, &frame_background
,
8117 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8121 /* Update info structure. */
8122 png_read_update_info (png_ptr
, info_ptr
);
8124 /* Get number of channels. Valid values are 1 for grayscale images
8125 and images with a palette, 2 for grayscale images with transparency
8126 information (alpha channel), 3 for RGB images, and 4 for RGB
8127 images with alpha channel, i.e. RGBA. If conversions above were
8128 sufficient we should only have 3 or 4 channels here. */
8129 channels
= png_get_channels (png_ptr
, info_ptr
);
8130 xassert (channels
== 3 || channels
== 4);
8132 /* Number of bytes needed for one row of the image. */
8133 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8135 /* Allocate memory for the image. */
8136 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8137 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8138 for (i
= 0; i
< height
; ++i
)
8139 rows
[i
] = pixels
+ i
* row_bytes
;
8141 /* Read the entire image. */
8142 png_read_image (png_ptr
, rows
);
8143 png_read_end (png_ptr
, info_ptr
);
8149 /* Create the X image and pixmap. */
8150 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8157 /* Create an image and pixmap serving as mask if the PNG image
8158 contains an alpha channel. */
8161 && !x_create_x_image_and_pixmap (f
, file
, width
, height
, 1,
8162 &mask_img
, &img
->mask
))
8164 x_destroy_x_image (ximg
);
8165 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8171 /* Fill the X image and mask from PNG data. */
8172 init_color_table ();
8174 for (y
= 0; y
< height
; ++y
)
8176 png_byte
*p
= rows
[y
];
8178 for (x
= 0; x
< width
; ++x
)
8185 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8187 /* An alpha channel, aka mask channel, associates variable
8188 transparency with an image. Where other image formats
8189 support binary transparency---fully transparent or fully
8190 opaque---PNG allows up to 254 levels of partial transparency.
8191 The PNG library implements partial transparency by combining
8192 the image with a specified background color.
8194 I'm not sure how to handle this here nicely: because the
8195 background on which the image is displayed may change, for
8196 real alpha channel support, it would be necessary to create
8197 a new image for each possible background.
8199 What I'm doing now is that a mask is created if we have
8200 boolean transparency information. Otherwise I'm using
8201 the frame's background color to combine the image with. */
8206 XPutPixel (mask_img
, x
, y
, *p
> 0);
8212 /* Remember colors allocated for this image. */
8213 img
->colors
= colors_in_color_table (&img
->ncolors
);
8214 free_color_table ();
8217 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8222 img
->height
= height
;
8224 /* Put the image into the pixmap, then free the X image and its buffer. */
8225 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8226 x_destroy_x_image (ximg
);
8228 /* Same for the mask. */
8231 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8232 x_destroy_x_image (mask_img
);
8240 #endif /* HAVE_PNG != 0 */
8244 /***********************************************************************
8246 ***********************************************************************/
8250 #include <jpeglib.h>
8254 static int jpeg_image_p
P_ ((Lisp_Object object
));
8255 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8257 /* The symbol `jpeg' identifying images of this type. */
8261 /* Indices of image specification fields in gs_format, below. */
8263 enum jpeg_keyword_index
8271 JPEG_HEURISTIC_MASK
,
8275 /* Vector of image_keyword structures describing the format
8276 of valid user-defined image specifications. */
8278 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8280 {":type", IMAGE_SYMBOL_VALUE
, 1},
8281 {":file", IMAGE_STRING_VALUE
, 1},
8282 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8283 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8284 {":relief", IMAGE_INTEGER_VALUE
, 0},
8285 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8286 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8289 /* Structure describing the image type `jpeg'. */
8291 static struct image_type jpeg_type
=
8301 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8304 jpeg_image_p (object
)
8307 struct image_keyword fmt
[JPEG_LAST
];
8309 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8311 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
, 0)
8312 || (fmt
[JPEG_ASCENT
].count
8313 && XFASTINT (fmt
[JPEG_ASCENT
].value
) > 100))
8318 struct my_jpeg_error_mgr
8320 struct jpeg_error_mgr pub
;
8321 jmp_buf setjmp_buffer
;
8325 my_error_exit (cinfo
)
8328 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8329 longjmp (mgr
->setjmp_buffer
, 1);
8332 /* Load image IMG for use on frame F. Patterned after example.c
8333 from the JPEG lib. */
8340 struct jpeg_decompress_struct cinfo
;
8341 struct my_jpeg_error_mgr mgr
;
8342 Lisp_Object file
, specified_file
;
8345 int row_stride
, x
, y
;
8346 XImage
*ximg
= NULL
;
8348 unsigned long *colors
;
8350 struct gcpro gcpro1
;
8352 /* Open the JPEG file. */
8353 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8354 file
= x_find_image_file (specified_file
);
8356 if (!STRINGP (file
))
8358 image_error ("Cannot find image file %s", specified_file
, Qnil
);
8363 fp
= fopen (XSTRING (file
)->data
, "r");
8366 image_error ("Cannot open `%s'", file
, Qnil
);
8371 /* Customize libjpeg's error handling to call my_error_exit
8372 when an error is detected. This function will perform
8374 mgr
.pub
.error_exit
= my_error_exit
;
8375 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8377 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8381 /* Called from my_error_exit. Display a JPEG error. */
8382 char buffer
[JMSG_LENGTH_MAX
];
8383 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8384 image_error ("Error reading JPEG file `%s': %s", file
,
8385 build_string (buffer
));
8388 /* Close the input file and destroy the JPEG object. */
8390 jpeg_destroy_decompress (&cinfo
);
8394 /* If we already have an XImage, free that. */
8395 x_destroy_x_image (ximg
);
8397 /* Free pixmap and colors. */
8398 x_clear_image (f
, img
);
8405 /* Create the JPEG decompression object. Let it read from fp.
8406 Read the JPEG image header. */
8407 jpeg_create_decompress (&cinfo
);
8408 jpeg_stdio_src (&cinfo
, fp
);
8409 jpeg_read_header (&cinfo
, TRUE
);
8411 /* Customize decompression so that color quantization will be used.
8412 Start decompression. */
8413 cinfo
.quantize_colors
= TRUE
;
8414 jpeg_start_decompress (&cinfo
);
8415 width
= img
->width
= cinfo
.output_width
;
8416 height
= img
->height
= cinfo
.output_height
;
8420 /* Create X image and pixmap. */
8421 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8425 longjmp (mgr
.setjmp_buffer
, 2);
8428 /* Allocate colors. When color quantization is used,
8429 cinfo.actual_number_of_colors has been set with the number of
8430 colors generated, and cinfo.colormap is a two-dimensional array
8431 of color indices in the range 0..cinfo.actual_number_of_colors.
8432 No more than 255 colors will be generated. */
8436 if (cinfo
.out_color_components
> 2)
8437 ir
= 0, ig
= 1, ib
= 2;
8438 else if (cinfo
.out_color_components
> 1)
8439 ir
= 0, ig
= 1, ib
= 0;
8441 ir
= 0, ig
= 0, ib
= 0;
8443 /* Use the color table mechanism because it handles colors that
8444 cannot be allocated nicely. Such colors will be replaced with
8445 a default color, and we don't have to care about which colors
8446 can be freed safely, and which can't. */
8447 init_color_table ();
8448 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8451 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8453 /* Multiply RGB values with 255 because X expects RGB values
8454 in the range 0..0xffff. */
8455 int r
= cinfo
.colormap
[ir
][i
] << 8;
8456 int g
= cinfo
.colormap
[ig
][i
] << 8;
8457 int b
= cinfo
.colormap
[ib
][i
] << 8;
8458 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8461 /* Remember those colors actually allocated. */
8462 img
->colors
= colors_in_color_table (&img
->ncolors
);
8463 free_color_table ();
8467 row_stride
= width
* cinfo
.output_components
;
8468 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
8470 for (y
= 0; y
< height
; ++y
)
8472 jpeg_read_scanlines (&cinfo
, buffer
, 1);
8473 for (x
= 0; x
< cinfo
.output_width
; ++x
)
8474 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
8478 jpeg_finish_decompress (&cinfo
);
8479 jpeg_destroy_decompress (&cinfo
);
8482 /* Put the image into the pixmap. */
8483 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8484 x_destroy_x_image (ximg
);
8490 #endif /* HAVE_JPEG */
8494 /***********************************************************************
8496 ***********************************************************************/
8500 #include <tiff34/tiffio.h>
8502 static int tiff_image_p
P_ ((Lisp_Object object
));
8503 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
8505 /* The symbol `tiff' identifying images of this type. */
8509 /* Indices of image specification fields in tiff_format, below. */
8511 enum tiff_keyword_index
8519 TIFF_HEURISTIC_MASK
,
8523 /* Vector of image_keyword structures describing the format
8524 of valid user-defined image specifications. */
8526 static struct image_keyword tiff_format
[TIFF_LAST
] =
8528 {":type", IMAGE_SYMBOL_VALUE
, 1},
8529 {":file", IMAGE_STRING_VALUE
, 1},
8530 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8531 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8532 {":relief", IMAGE_INTEGER_VALUE
, 0},
8533 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8534 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8537 /* Structure describing the image type `tiff'. */
8539 static struct image_type tiff_type
=
8549 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8552 tiff_image_p (object
)
8555 struct image_keyword fmt
[TIFF_LAST
];
8556 bcopy (tiff_format
, fmt
, sizeof fmt
);
8558 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
, 1)
8559 || (fmt
[TIFF_ASCENT
].count
8560 && XFASTINT (fmt
[TIFF_ASCENT
].value
) > 100))
8566 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8574 Lisp_Object file
, specified_file
;
8576 int width
, height
, x
, y
;
8580 struct gcpro gcpro1
;
8582 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8583 file
= x_find_image_file (specified_file
);
8585 if (!STRINGP (file
))
8587 image_error ("Cannot find image file %s", file
, Qnil
);
8592 /* Try to open the image file. */
8593 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
8596 image_error ("Cannot open `%s'", file
, Qnil
);
8601 /* Get width and height of the image, and allocate a raster buffer
8602 of width x height 32-bit values. */
8603 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
8604 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
8605 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8607 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8611 image_error ("Error reading `%s'", file
, Qnil
);
8619 /* Create the X image and pixmap. */
8620 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8629 /* Initialize the color table. */
8630 init_color_table ();
8632 /* Process the pixel raster. Origin is in the lower-left corner. */
8633 for (y
= 0; y
< height
; ++y
)
8635 uint32
*row
= buf
+ y
* width
;
8637 for (x
= 0; x
< width
; ++x
)
8639 uint32 abgr
= row
[x
];
8640 int r
= TIFFGetR (abgr
) << 8;
8641 int g
= TIFFGetG (abgr
) << 8;
8642 int b
= TIFFGetB (abgr
) << 8;
8643 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
8647 /* Remember the colors allocated for the image. Free the color table. */
8648 img
->colors
= colors_in_color_table (&img
->ncolors
);
8649 free_color_table ();
8651 /* Put the image into the pixmap, then free the X image and its buffer. */
8652 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8653 x_destroy_x_image (ximg
);
8658 img
->height
= height
;
8664 #endif /* HAVE_TIFF != 0 */
8668 /***********************************************************************
8670 ***********************************************************************/
8674 #include <gif_lib.h>
8676 static int gif_image_p
P_ ((Lisp_Object object
));
8677 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
8679 /* The symbol `gif' identifying images of this type. */
8683 /* Indices of image specification fields in gif_format, below. */
8685 enum gif_keyword_index
8698 /* Vector of image_keyword structures describing the format
8699 of valid user-defined image specifications. */
8701 static struct image_keyword gif_format
[GIF_LAST
] =
8703 {":type", IMAGE_SYMBOL_VALUE
, 1},
8704 {":file", IMAGE_STRING_VALUE
, 1},
8705 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8706 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8707 {":relief", IMAGE_INTEGER_VALUE
, 0},
8708 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8709 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8710 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
8713 /* Structure describing the image type `gif'. */
8715 static struct image_type gif_type
=
8725 /* Return non-zero if OBJECT is a valid GIF image specification. */
8728 gif_image_p (object
)
8731 struct image_keyword fmt
[GIF_LAST
];
8732 bcopy (gif_format
, fmt
, sizeof fmt
);
8734 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
, 1)
8735 || (fmt
[GIF_ASCENT
].count
8736 && XFASTINT (fmt
[GIF_ASCENT
].value
) > 100))
8742 /* Load GIF image IMG for use on frame F. Value is non-zero if
8750 Lisp_Object file
, specified_file
;
8751 int rc
, width
, height
, x
, y
, i
;
8753 ColorMapObject
*gif_color_map
;
8754 unsigned long pixel_colors
[256];
8756 struct gcpro gcpro1
;
8758 int ino
, image_left
, image_top
, image_width
, image_height
;
8761 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8762 file
= x_find_image_file (specified_file
);
8764 if (!STRINGP (file
))
8766 image_error ("Cannot find image file %s", specified_file
, Qnil
);
8771 /* Open the GIF file. */
8772 gif
= DGifOpenFileName (XSTRING (file
)->data
);
8775 image_error ("Cannot open `%s'", file
, Qnil
);
8780 /* Read entire contents. */
8781 rc
= DGifSlurp (gif
);
8782 if (rc
== GIF_ERROR
)
8784 image_error ("Error reading `%s'", file
, Qnil
);
8785 DGifCloseFile (gif
);
8790 image
= image_spec_value (img
->spec
, QCimage
, NULL
);
8791 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8792 if (ino
>= gif
->ImageCount
)
8794 image_error ("Invalid image number `%s'", image
, Qnil
);
8795 DGifCloseFile (gif
);
8800 width
= img
->width
= gif
->SWidth
;
8801 height
= img
->height
= gif
->SHeight
;
8805 /* Create the X image and pixmap. */
8806 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8810 DGifCloseFile (gif
);
8815 /* Allocate colors. */
8816 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8818 gif_color_map
= gif
->SColorMap
;
8819 init_color_table ();
8820 bzero (pixel_colors
, sizeof pixel_colors
);
8822 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8824 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8825 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8826 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8827 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8830 img
->colors
= colors_in_color_table (&img
->ncolors
);
8831 free_color_table ();
8833 /* Clear the part of the screen image that are not covered by
8834 the image from the GIF file. Full animated GIF support
8835 requires more than can be done here (see the gif89 spec,
8836 disposal methods). Let's simply assume that the part
8837 not covered by a sub-image is in the frame's background color. */
8838 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
8839 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
8840 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8841 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8843 for (y
= 0; y
< image_top
; ++y
)
8844 for (x
= 0; x
< width
; ++x
)
8845 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8847 for (y
= image_top
+ image_height
; y
< height
; ++y
)
8848 for (x
= 0; x
< width
; ++x
)
8849 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8851 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
8853 for (x
= 0; x
< image_left
; ++x
)
8854 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8855 for (x
= image_left
+ image_width
; x
< width
; ++x
)
8856 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8859 /* Read the GIF image into the X image. */
8860 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8862 static int interlace_start
[] = {0, 4, 2, 1};
8863 static int interlace_increment
[] = {8, 8, 4, 2};
8866 for (pass
= 0; pass
< 4; ++pass
)
8868 inc
= interlace_increment
[pass
];
8869 for (y
= interlace_start
[pass
]; y
< image_height
; y
+= inc
)
8870 for (x
= 0; x
< image_width
; ++x
)
8872 unsigned i
= gif
->SavedImages
[ino
].RasterBits
[y
* image_width
+ x
];
8873 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
,
8880 for (y
= 0; y
< image_height
; ++y
)
8881 for (x
= 0; x
< image_width
; ++x
)
8883 unsigned i
= gif
->SavedImages
[ino
].RasterBits
[y
* image_width
+ x
];
8884 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
8888 DGifCloseFile (gif
);
8890 /* Put the image into the pixmap, then free the X image and its buffer. */
8891 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8892 x_destroy_x_image (ximg
);
8899 #endif /* HAVE_GIF != 0 */
8903 /***********************************************************************
8905 ***********************************************************************/
8907 static int gs_image_p
P_ ((Lisp_Object object
));
8908 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8909 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8911 /* The symbol `ghostscript' identifying images of this type. */
8913 Lisp_Object Qghostscript
;
8915 /* Keyword symbols. */
8917 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8919 /* Indices of image specification fields in gs_format, below. */
8921 enum gs_keyword_index
8937 /* Vector of image_keyword structures describing the format
8938 of valid user-defined image specifications. */
8940 static struct image_keyword gs_format
[GS_LAST
] =
8942 {":type", IMAGE_SYMBOL_VALUE
, 1},
8943 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8944 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8945 {":file", IMAGE_STRING_VALUE
, 1},
8946 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8947 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8948 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8949 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8950 {":relief", IMAGE_INTEGER_VALUE
, 0},
8951 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8952 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8955 /* Structure describing the image type `ghostscript'. */
8957 static struct image_type gs_type
=
8967 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8970 gs_clear_image (f
, img
)
8974 /* IMG->data.ptr_val may contain a recorded colormap. */
8975 xfree (img
->data
.ptr_val
);
8976 x_clear_image (f
, img
);
8980 /* Return non-zero if OBJECT is a valid Ghostscript image
8987 struct image_keyword fmt
[GS_LAST
];
8991 bcopy (gs_format
, fmt
, sizeof fmt
);
8993 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qghostscript
, 1)
8994 || (fmt
[GS_ASCENT
].count
8995 && XFASTINT (fmt
[GS_ASCENT
].value
) > 100))
8998 /* Bounding box must be a list or vector containing 4 integers. */
8999 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9002 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9003 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9008 else if (VECTORP (tem
))
9010 if (XVECTOR (tem
)->size
!= 4)
9012 for (i
= 0; i
< 4; ++i
)
9013 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9023 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9032 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9033 struct gcpro gcpro1
, gcpro2
;
9035 double in_width
, in_height
;
9036 Lisp_Object pixel_colors
= Qnil
;
9038 /* Compute pixel size of pixmap needed from the given size in the
9039 image specification. Sizes in the specification are in pt. 1 pt
9040 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9042 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9043 in_width
= XFASTINT (pt_width
) / 72.0;
9044 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9045 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9046 in_height
= XFASTINT (pt_height
) / 72.0;
9047 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9049 /* Create the pixmap. */
9051 xassert (img
->pixmap
== 0);
9052 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9053 img
->width
, img
->height
,
9054 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9059 image_error ("Unable to create pixmap for `%s'",
9060 image_spec_value (img
->spec
, QCfile
, NULL
), Qnil
);
9064 /* Call the loader to fill the pixmap. It returns a process object
9065 if successful. We do not record_unwind_protect here because
9066 other places in redisplay like calling window scroll functions
9067 don't either. Let the Lisp loader use `unwind-protect' instead. */
9068 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9070 sprintf (buffer
, "%lu %lu",
9071 (unsigned long) FRAME_X_WINDOW (f
),
9072 (unsigned long) img
->pixmap
);
9073 window_and_pixmap_id
= build_string (buffer
);
9075 sprintf (buffer
, "%lu %lu",
9076 FRAME_FOREGROUND_PIXEL (f
),
9077 FRAME_BACKGROUND_PIXEL (f
));
9078 pixel_colors
= build_string (buffer
);
9080 XSETFRAME (frame
, f
);
9081 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9083 loader
= intern ("gs-load-image");
9085 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9086 make_number (img
->width
),
9087 make_number (img
->height
),
9088 window_and_pixmap_id
,
9091 return PROCESSP (img
->data
.lisp_val
);
9095 /* Kill the Ghostscript process that was started to fill PIXMAP on
9096 frame F. Called from XTread_socket when receiving an event
9097 telling Emacs that Ghostscript has finished drawing. */
9100 x_kill_gs_process (pixmap
, f
)
9104 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9108 /* Find the image containing PIXMAP. */
9109 for (i
= 0; i
< c
->used
; ++i
)
9110 if (c
->images
[i
]->pixmap
== pixmap
)
9113 /* Kill the GS process. We should have found PIXMAP in the image
9114 cache and its image should contain a process object. */
9115 xassert (i
< c
->used
);
9117 xassert (PROCESSP (img
->data
.lisp_val
));
9118 Fkill_process (img
->data
.lisp_val
, Qnil
);
9119 img
->data
.lisp_val
= Qnil
;
9121 /* On displays with a mutable colormap, figure out the colors
9122 allocated for the image by looking at the pixels of an XImage for
9124 class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
9125 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9131 /* Try to get an XImage for img->pixmep. */
9132 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9133 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9138 /* Initialize the color table. */
9139 init_color_table ();
9141 /* For each pixel of the image, look its color up in the
9142 color table. After having done so, the color table will
9143 contain an entry for each color used by the image. */
9144 for (y
= 0; y
< img
->height
; ++y
)
9145 for (x
= 0; x
< img
->width
; ++x
)
9147 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9148 lookup_pixel_color (f
, pixel
);
9151 /* Record colors in the image. Free color table and XImage. */
9152 img
->colors
= colors_in_color_table (&img
->ncolors
);
9153 free_color_table ();
9154 XDestroyImage (ximg
);
9156 #if 0 /* This doesn't seem to be the case. If we free the colors
9157 here, we get a BadAccess later in x_clear_image when
9158 freeing the colors. */
9159 /* We have allocated colors once, but Ghostscript has also
9160 allocated colors on behalf of us. So, to get the
9161 reference counts right, free them once. */
9164 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9165 XFreeColors (FRAME_X_DISPLAY (f
), cmap
,
9166 img
->colors
, img
->ncolors
, 0);
9171 image_error ("Cannot get X image of `%s'; colors will not be freed",
9172 image_spec_value (img
->spec
, QCfile
, NULL
), Qnil
);
9180 /***********************************************************************
9182 ***********************************************************************/
9184 DEFUN ("x-change-window-property", Fx_change_window_property
,
9185 Sx_change_window_property
, 2, 3, 0,
9186 "Change window property PROP to VALUE on the X window of FRAME.\n\
9187 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9188 selected frame. Value is VALUE.")
9189 (prop
, value
, frame
)
9190 Lisp_Object frame
, prop
, value
;
9192 struct frame
*f
= check_x_frame (frame
);
9195 CHECK_STRING (prop
, 1);
9196 CHECK_STRING (value
, 2);
9199 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9200 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9201 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9202 XSTRING (value
)->data
, XSTRING (value
)->size
);
9204 /* Make sure the property is set when we return. */
9205 XFlush (FRAME_X_DISPLAY (f
));
9212 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9213 Sx_delete_window_property
, 1, 2, 0,
9214 "Remove window property PROP from X window of FRAME.\n\
9215 FRAME nil or omitted means use the selected frame. Value is PROP.")
9217 Lisp_Object prop
, frame
;
9219 struct frame
*f
= check_x_frame (frame
);
9222 CHECK_STRING (prop
, 1);
9224 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9225 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9227 /* Make sure the property is removed when we return. */
9228 XFlush (FRAME_X_DISPLAY (f
));
9235 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9237 "Value is the value of window property PROP on FRAME.\n\
9238 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9239 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9242 Lisp_Object prop
, frame
;
9244 struct frame
*f
= check_x_frame (frame
);
9247 Lisp_Object prop_value
= Qnil
;
9248 char *tmp_data
= NULL
;
9251 unsigned long actual_size
, bytes_remaining
;
9253 CHECK_STRING (prop
, 1);
9255 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9256 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9257 prop_atom
, 0, 0, False
, XA_STRING
,
9258 &actual_type
, &actual_format
, &actual_size
,
9259 &bytes_remaining
, (unsigned char **) &tmp_data
);
9262 int size
= bytes_remaining
;
9267 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9268 prop_atom
, 0, bytes_remaining
,
9270 &actual_type
, &actual_format
,
9271 &actual_size
, &bytes_remaining
,
9272 (unsigned char **) &tmp_data
);
9274 prop_value
= make_string (tmp_data
, size
);
9285 /***********************************************************************
9287 ***********************************************************************/
9289 /* The implementation partly follows a patch from
9290 F.Pierresteguy@frcl.bull.fr dated 1994. */
9292 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
9293 the next X event is read and we enter XTread_socket again. Setting
9294 it to 1 inhibits busy-cursor display for direct commands. */
9296 int inhibit_busy_cursor
;
9298 /* Incremented with each call to x-display-busy-cursor.
9299 Decremented in x-undisplay-busy-cursor. */
9301 static int busy_count
;
9304 DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor
,
9305 Sx_show_busy_cursor
, 0, 0, 0,
9306 "Show a busy cursor, if not already shown.\n\
9307 Each call to this function must be matched by a call to\n\
9308 x-undisplay-busy-cursor to make the busy pointer disappear again.")
9312 if (busy_count
== 1)
9314 Lisp_Object rest
, frame
;
9316 FOR_EACH_FRAME (rest
, frame
)
9317 if (FRAME_X_P (XFRAME (frame
)))
9319 struct frame
*f
= XFRAME (frame
);
9322 f
->output_data
.x
->busy_p
= 1;
9324 if (!f
->output_data
.x
->busy_window
)
9326 unsigned long mask
= CWCursor
;
9327 XSetWindowAttributes attrs
;
9329 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
9330 f
->output_data
.x
->busy_window
9331 = XCreateWindow (FRAME_X_DISPLAY (f
),
9332 FRAME_OUTER_WINDOW (f
),
9333 0, 0, 32000, 32000, 0, 0,
9334 InputOnly
, CopyFromParent
,
9338 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9347 DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor
,
9348 Sx_hide_busy_cursor
, 0, 1, 0,
9349 "Hide a busy-cursor.\n\
9350 A busy-cursor will actually be undisplayed when a matching\n\
9351 `x-undisplay-busy-cursor' is called for each `x-display-busy-cursor'\n\
9352 issued. FORCE non-nil means undisplay the busy-cursor forcibly,\n\
9353 not counting calls.")
9357 Lisp_Object rest
, frame
;
9359 if (busy_count
== 0)
9362 if (!NILP (force
) && busy_count
!= 0)
9366 if (busy_count
!= 0)
9369 FOR_EACH_FRAME (rest
, frame
)
9371 struct frame
*f
= XFRAME (frame
);
9374 /* Watch out for newly created frames. */
9375 && f
->output_data
.x
->busy_window
)
9379 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9380 /* Sync here because XTread_socket looks at the busy_p flag
9381 that is reset to zero below. */
9382 XSync (FRAME_X_DISPLAY (f
), False
);
9384 f
->output_data
.x
->busy_p
= 0;
9393 /***********************************************************************
9395 ***********************************************************************/
9397 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
9400 /* The frame of a currently visible tooltip, or null. */
9402 struct frame
*tip_frame
;
9404 /* If non-nil, a timer started that hides the last tooltip when it
9407 Lisp_Object tip_timer
;
9410 /* Create a frame for a tooltip on the display described by DPYINFO.
9411 PARMS is a list of frame parameters. Value is the frame. */
9414 x_create_tip_frame (dpyinfo
, parms
)
9415 struct x_display_info
*dpyinfo
;
9419 Lisp_Object frame
, tem
;
9421 int minibuffer_only
= 0;
9422 long window_prompting
= 0;
9424 int count
= specpdl_ptr
- specpdl
;
9425 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
9430 /* Use this general default value to start with until we know if
9431 this frame has a specified name. */
9432 Vx_resource_name
= Vinvocation_name
;
9435 kb
= dpyinfo
->kboard
;
9437 kb
= &the_only_kboard
;
9440 /* Get the name of the frame to use for resource lookup. */
9441 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
9443 && !EQ (name
, Qunbound
)
9445 error ("Invalid frame name--not a string or nil");
9446 Vx_resource_name
= name
;
9449 GCPRO3 (parms
, name
, frame
);
9450 tip_frame
= f
= make_frame (1);
9451 XSETFRAME (frame
, f
);
9452 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
9454 f
->output_method
= output_x_window
;
9455 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
9456 bzero (f
->output_data
.x
, sizeof (struct x_output
));
9457 f
->output_data
.x
->icon_bitmap
= -1;
9458 f
->output_data
.x
->fontset
= -1;
9459 f
->icon_name
= Qnil
;
9460 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
9462 FRAME_KBOARD (f
) = kb
;
9464 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9465 f
->output_data
.x
->explicit_parent
= 0;
9467 /* Set the name; the functions to which we pass f expect the name to
9469 if (EQ (name
, Qunbound
) || NILP (name
))
9471 f
->name
= build_string (dpyinfo
->x_id_name
);
9472 f
->explicit_name
= 0;
9477 f
->explicit_name
= 1;
9478 /* use the frame's title when getting resources for this frame. */
9479 specbind (Qx_resource_name
, name
);
9482 /* Create fontsets from `global_fontset_alist' before handling fonts. */
9483 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
9484 fs_register_fontset (f
, XCONS (tem
)->car
);
9486 /* Extract the window parameters from the supplied values
9487 that are needed to determine window geometry. */
9491 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
9494 /* First, try whatever font the caller has specified. */
9497 tem
= Fquery_fontset (font
, Qnil
);
9499 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
9501 font
= x_new_font (f
, XSTRING (font
)->data
);
9504 /* Try out a font which we hope has bold and italic variations. */
9505 if (!STRINGP (font
))
9506 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9507 if (!STRINGP (font
))
9508 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9509 if (! STRINGP (font
))
9510 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9511 if (! STRINGP (font
))
9512 /* This was formerly the first thing tried, but it finds too many fonts
9513 and takes too long. */
9514 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9515 /* If those didn't work, look for something which will at least work. */
9516 if (! STRINGP (font
))
9517 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9519 if (! STRINGP (font
))
9520 font
= build_string ("fixed");
9522 x_default_parameter (f
, parms
, Qfont
, font
,
9523 "font", "Font", RES_TYPE_STRING
);
9526 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
9527 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
9529 /* This defaults to 2 in order to match xterm. We recognize either
9530 internalBorderWidth or internalBorder (which is what xterm calls
9532 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9536 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
9537 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
9538 if (! EQ (value
, Qunbound
))
9539 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
9543 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
9544 "internalBorderWidth", "internalBorderWidth",
9547 /* Also do the stuff which must be set before the window exists. */
9548 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
9549 "foreground", "Foreground", RES_TYPE_STRING
);
9550 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
9551 "background", "Background", RES_TYPE_STRING
);
9552 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
9553 "pointerColor", "Foreground", RES_TYPE_STRING
);
9554 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
9555 "cursorColor", "Foreground", RES_TYPE_STRING
);
9556 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
9557 "borderColor", "BorderColor", RES_TYPE_STRING
);
9559 /* Init faces before x_default_parameter is called for scroll-bar
9560 parameters because that function calls x_set_scroll_bar_width,
9561 which calls change_frame_size, which calls Fset_window_buffer,
9562 which runs hooks, which call Fvertical_motion. At the end, we
9563 end up in init_iterator with a null face cache, which should not
9565 init_frame_faces (f
);
9567 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9568 window_prompting
= x_figure_window_size (f
, parms
);
9570 if (window_prompting
& XNegative
)
9572 if (window_prompting
& YNegative
)
9573 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
9575 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
9579 if (window_prompting
& YNegative
)
9580 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
9582 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9585 f
->output_data
.x
->size_hint_flags
= window_prompting
;
9587 XSetWindowAttributes attrs
;
9591 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
9592 /* Window managers looks at the override-redirect flag to
9593 determine whether or net to give windows a decoration (Xlib
9595 attrs
.override_redirect
= True
;
9596 attrs
.save_under
= True
;
9597 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
9598 /* Arrange for getting MapNotify and UnmapNotify events. */
9599 attrs
.event_mask
= StructureNotifyMask
;
9601 = FRAME_X_WINDOW (f
)
9602 = XCreateWindow (FRAME_X_DISPLAY (f
),
9603 FRAME_X_DISPLAY_INFO (f
)->root_window
,
9604 /* x, y, width, height */
9608 CopyFromParent
, InputOutput
, CopyFromParent
,
9615 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
9616 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9617 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
9618 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9619 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
9620 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
9622 /* Dimensions, especially f->height, must be done via change_frame_size.
9623 Change will not be effected unless different from the current
9628 SET_FRAME_WIDTH (f
, 0);
9629 change_frame_size (f
, height
, width
, 1, 0);
9635 /* It is now ok to make the frame official even if we get an error
9636 below. And the frame needs to be on Vframe_list or making it
9637 visible won't work. */
9638 Vframe_list
= Fcons (frame
, Vframe_list
);
9640 /* Now that the frame is official, it counts as a reference to
9642 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
9644 return unbind_to (count
, frame
);
9648 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 4, 0,
9649 "Show tooltip STRING on frame FRAME.\n\
9650 FRAME nil or omitted means use the selected frame.\n\
9651 PARMS is an optional list of frame parameters which can be\n\
9652 used to change the tooltip's appearance.\n\
9653 Automatically hide the tooltip after TIMEOUT seconds.\n\
9654 TIMEOUT nil means use the default timeout of 5 seconds.")
9655 (string
, frame
, parms
, timeout
)
9656 Lisp_Object string
, frame
, parms
;
9663 struct buffer
*old_buffer
;
9664 struct text_pos pos
;
9665 int i
, width
, height
;
9666 int root_x
, root_y
, win_x
, win_y
;
9668 struct gcpro gcpro1
, gcpro2
, gcpro3
;
9669 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
9670 int count
= specpdl_ptr
- specpdl
;
9672 specbind (Qinhibit_redisplay
, Qt
);
9674 GCPRO3 (string
, parms
, frame
);
9676 CHECK_STRING (string
, 0);
9677 f
= check_x_frame (frame
);
9679 timeout
= make_number (5);
9681 CHECK_NATNUM (timeout
, 2);
9683 /* Hide a previous tip, if any. */
9686 /* Add default values to frame parameters. */
9687 if (NILP (Fassq (Qname
, parms
)))
9688 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
9689 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9690 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
9691 if (NILP (Fassq (Qborder_width
, parms
)))
9692 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
9693 if (NILP (Fassq (Qborder_color
, parms
)))
9694 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
9695 if (NILP (Fassq (Qbackground_color
, parms
)))
9696 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
9699 /* Create a frame for the tooltip, and record it in the global
9700 variable tip_frame. */
9701 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
9702 tip_frame
= f
= XFRAME (frame
);
9704 /* Set up the frame's root window. Currently we use a size of 80
9705 columns x 40 lines. If someone wants to show a larger tip, he
9706 will loose. I don't think this is a realistic case. */
9707 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
9708 w
->left
= w
->top
= make_number (0);
9712 w
->pseudo_window_p
= 1;
9714 /* Display the tooltip text in a temporary buffer. */
9715 buffer
= Fget_buffer_create (build_string (" *tip*"));
9716 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
9717 old_buffer
= current_buffer
;
9718 set_buffer_internal_1 (XBUFFER (buffer
));
9720 Finsert (make_number (1), &string
);
9721 clear_glyph_matrix (w
->desired_matrix
);
9722 clear_glyph_matrix (w
->current_matrix
);
9723 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
9724 try_window (FRAME_ROOT_WINDOW (f
), pos
);
9726 /* Compute width and height of the tooltip. */
9728 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
9730 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
9734 /* Stop at the first empty row at the end. */
9735 if (!row
->enabled_p
|| !row
->displays_text_p
)
9738 /* Let the row go over the full width of the frame. */
9739 row
->full_width_p
= 1;
9741 /* There's a glyph at the end of rows that is use to place
9742 the cursor there. Don't include the width of this glyph. */
9743 if (row
->used
[TEXT_AREA
])
9745 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
9746 row_width
= row
->pixel_width
- last
->pixel_width
;
9749 row_width
= row
->pixel_width
;
9751 height
+= row
->height
;
9752 width
= max (width
, row_width
);
9755 /* Add the frame's internal border to the width and height the X
9756 window should have. */
9757 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9758 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9760 /* Move the tooltip window where the mouse pointer is. Resize and
9763 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
9764 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
9765 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9766 root_x
+ 5, root_y
- height
- 5, width
, height
);
9767 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9770 /* Draw into the window. */
9771 w
->must_be_updated_p
= 1;
9772 update_single_window (w
, 1);
9774 /* Restore original current buffer. */
9775 set_buffer_internal_1 (old_buffer
);
9776 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
9778 /* Let the tip disappear after timeout seconds. */
9779 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
9780 intern ("x-hide-tip"));
9782 return unbind_to (count
, Qnil
);
9786 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
9787 "Hide the current tooltip, if there is any.\n\
9788 Value is t is tooltip was open, nil otherwise.")
9791 int count
= specpdl_ptr
- specpdl
;
9794 specbind (Qinhibit_redisplay
, Qt
);
9796 if (!NILP (tip_timer
))
9798 call1 (intern ("cancel-timer"), tip_timer
);
9806 XSETFRAME (frame
, tip_frame
);
9807 Fdelete_frame (frame
, Qt
);
9812 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
9817 /***********************************************************************
9818 File selection dialog
9819 ***********************************************************************/
9823 /* Callback for "OK" and "Cancel" on file selection dialog. */
9826 file_dialog_cb (widget
, client_data
, call_data
)
9828 XtPointer call_data
, client_data
;
9830 int *result
= (int *) client_data
;
9831 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
9832 *result
= cb
->reason
;
9836 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
9837 "Read file name, prompting with PROMPT in directory DIR.\n\
9838 Use a file selection dialog.\n\
9839 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
9840 specified. Don't let the user enter a file name in the file\n\
9841 selection dialog's entry field, if MUSTMATCH is non-nil.")
9842 (prompt
, dir
, default_filename
, mustmatch
)
9843 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
9846 struct frame
*f
= selected_frame
;
9847 Lisp_Object file
= Qnil
;
9848 Widget dialog
, text
, list
, help
;
9851 extern XtAppContext Xt_app_con
;
9853 XmString dir_xmstring
, pattern_xmstring
;
9854 int popup_activated_flag
;
9855 int count
= specpdl_ptr
- specpdl
;
9856 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
9858 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
9859 CHECK_STRING (prompt
, 0);
9860 CHECK_STRING (dir
, 1);
9862 /* Prevent redisplay. */
9863 specbind (Qinhibit_redisplay
, Qt
);
9867 /* Create the dialog with PROMPT as title, using DIR as initial
9868 directory and using "*" as pattern. */
9869 dir
= Fexpand_file_name (dir
, Qnil
);
9870 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
9871 pattern_xmstring
= XmStringCreateLocalized ("*");
9873 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
9874 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
9875 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
9876 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
9877 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
9878 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
9880 XmStringFree (dir_xmstring
);
9881 XmStringFree (pattern_xmstring
);
9883 /* Add callbacks for OK and Cancel. */
9884 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
9885 (XtPointer
) &result
);
9886 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
9887 (XtPointer
) &result
);
9889 /* Disable the help button since we can't display help. */
9890 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
9891 XtSetSensitive (help
, False
);
9893 /* Mark OK button as default. */
9894 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
9895 XmNshowAsDefault
, True
, NULL
);
9897 /* If MUSTMATCH is non-nil, disable the file entry field of the
9898 dialog, so that the user must select a file from the files list
9899 box. We can't remove it because we wouldn't have a way to get at
9900 the result file name, then. */
9901 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
9902 if (!NILP (mustmatch
))
9905 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
9906 XtSetSensitive (text
, False
);
9907 XtSetSensitive (label
, False
);
9910 /* Manage the dialog, so that list boxes get filled. */
9911 XtManageChild (dialog
);
9913 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
9914 must include the path for this to work. */
9915 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
9916 if (STRINGP (default_filename
))
9918 XmString default_xmstring
;
9922 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
9924 if (!XmListItemExists (list
, default_xmstring
))
9926 /* Add a new item if DEFAULT_FILENAME is not in the list. */
9927 XmListAddItem (list
, default_xmstring
, 0);
9931 item_pos
= XmListItemPos (list
, default_xmstring
);
9932 XmStringFree (default_xmstring
);
9934 /* Select the item and scroll it into view. */
9935 XmListSelectPos (list
, item_pos
, True
);
9936 XmListSetPos (list
, item_pos
);
9939 /* Process all events until the user presses Cancel or OK. */
9940 for (result
= 0; result
== 0;)
9943 Widget widget
, parent
;
9945 XtAppNextEvent (Xt_app_con
, &event
);
9947 /* See if the receiver of the event is one of the widgets of
9948 the file selection dialog. If so, dispatch it. If not,
9950 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
9952 while (parent
&& parent
!= dialog
)
9953 parent
= XtParent (parent
);
9955 if (parent
== dialog
9956 || (event
.type
== Expose
9957 && !process_expose_from_menu (event
)))
9958 XtDispatchEvent (&event
);
9961 /* Get the result. */
9962 if (result
== XmCR_OK
)
9967 XtVaGetValues (dialog
, XmNtextString
, &text
, 0);
9968 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
9969 XmStringFree (text
);
9970 file
= build_string (data
);
9977 XtUnmanageChild (dialog
);
9978 XtDestroyWidget (dialog
);
9982 /* Make "Cancel" equivalent to C-g. */
9984 Fsignal (Qquit
, Qnil
);
9986 return unbind_to (count
, file
);
9989 #endif /* USE_MOTIF */
9992 /***********************************************************************
9994 ***********************************************************************/
9998 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9999 "Value is non-nil if SPEC is a valid image specification.")
10003 return valid_image_p (spec
) ? Qt
: Qnil
;
10007 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
10013 if (valid_image_p (spec
))
10014 id
= lookup_image (selected_frame
, spec
);
10016 debug_print (spec
);
10017 return make_number (id
);
10020 #endif /* GLYPH_DEBUG != 0 */
10024 /***********************************************************************
10026 ***********************************************************************/
10031 /* This is zero if not using X windows. */
10034 /* The section below is built by the lisp expression at the top of the file,
10035 just above where these variables are declared. */
10036 /*&&& init symbols here &&&*/
10037 Qauto_raise
= intern ("auto-raise");
10038 staticpro (&Qauto_raise
);
10039 Qauto_lower
= intern ("auto-lower");
10040 staticpro (&Qauto_lower
);
10041 Qbar
= intern ("bar");
10043 Qborder_color
= intern ("border-color");
10044 staticpro (&Qborder_color
);
10045 Qborder_width
= intern ("border-width");
10046 staticpro (&Qborder_width
);
10047 Qbox
= intern ("box");
10049 Qcursor_color
= intern ("cursor-color");
10050 staticpro (&Qcursor_color
);
10051 Qcursor_type
= intern ("cursor-type");
10052 staticpro (&Qcursor_type
);
10053 Qgeometry
= intern ("geometry");
10054 staticpro (&Qgeometry
);
10055 Qicon_left
= intern ("icon-left");
10056 staticpro (&Qicon_left
);
10057 Qicon_top
= intern ("icon-top");
10058 staticpro (&Qicon_top
);
10059 Qicon_type
= intern ("icon-type");
10060 staticpro (&Qicon_type
);
10061 Qicon_name
= intern ("icon-name");
10062 staticpro (&Qicon_name
);
10063 Qinternal_border_width
= intern ("internal-border-width");
10064 staticpro (&Qinternal_border_width
);
10065 Qleft
= intern ("left");
10066 staticpro (&Qleft
);
10067 Qright
= intern ("right");
10068 staticpro (&Qright
);
10069 Qmouse_color
= intern ("mouse-color");
10070 staticpro (&Qmouse_color
);
10071 Qnone
= intern ("none");
10072 staticpro (&Qnone
);
10073 Qparent_id
= intern ("parent-id");
10074 staticpro (&Qparent_id
);
10075 Qscroll_bar_width
= intern ("scroll-bar-width");
10076 staticpro (&Qscroll_bar_width
);
10077 Qsuppress_icon
= intern ("suppress-icon");
10078 staticpro (&Qsuppress_icon
);
10079 Qundefined_color
= intern ("undefined-color");
10080 staticpro (&Qundefined_color
);
10081 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10082 staticpro (&Qvertical_scroll_bars
);
10083 Qvisibility
= intern ("visibility");
10084 staticpro (&Qvisibility
);
10085 Qwindow_id
= intern ("window-id");
10086 staticpro (&Qwindow_id
);
10087 Qouter_window_id
= intern ("outer-window-id");
10088 staticpro (&Qouter_window_id
);
10089 Qx_frame_parameter
= intern ("x-frame-parameter");
10090 staticpro (&Qx_frame_parameter
);
10091 Qx_resource_name
= intern ("x-resource-name");
10092 staticpro (&Qx_resource_name
);
10093 Quser_position
= intern ("user-position");
10094 staticpro (&Quser_position
);
10095 Quser_size
= intern ("user-size");
10096 staticpro (&Quser_size
);
10097 Qdisplay
= intern ("display");
10098 staticpro (&Qdisplay
);
10099 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10100 staticpro (&Qscroll_bar_foreground
);
10101 Qscroll_bar_background
= intern ("scroll-bar-background");
10102 staticpro (&Qscroll_bar_background
);
10103 /* This is the end of symbol initialization. */
10105 Qlaplace
= intern ("laplace");
10106 staticpro (&Qlaplace
);
10108 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10109 staticpro (&Qface_set_after_frame_default
);
10111 Fput (Qundefined_color
, Qerror_conditions
,
10112 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10113 Fput (Qundefined_color
, Qerror_message
,
10114 build_string ("Undefined color"));
10116 init_x_parm_symbols ();
10118 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10119 "List of directories to search for bitmap files for X.");
10120 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
10122 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10123 "The shape of the pointer when over text.\n\
10124 Changing the value does not affect existing frames\n\
10125 unless you set the mouse color.");
10126 Vx_pointer_shape
= Qnil
;
10128 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
10129 "The name Emacs uses to look up X resources.\n\
10130 `x-get-resource' uses this as the first component of the instance name\n\
10131 when requesting resource values.\n\
10132 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10133 was invoked, or to the value specified with the `-name' or `-rn'\n\
10134 switches, if present.\n\
10136 It may be useful to bind this variable locally around a call\n\
10137 to `x-get-resource'. See also the variable `x-resource-class'.");
10138 Vx_resource_name
= Qnil
;
10140 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
10141 "The class Emacs uses to look up X resources.\n\
10142 `x-get-resource' uses this as the first component of the instance class\n\
10143 when requesting resource values.\n\
10144 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10146 Setting this variable permanently is not a reasonable thing to do,\n\
10147 but binding this variable locally around a call to `x-get-resource'\n\
10148 is a reasonable practice. See also the variable `x-resource-name'.");
10149 Vx_resource_class
= build_string (EMACS_CLASS
);
10151 #if 0 /* This doesn't really do anything. */
10152 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
10153 "The shape of the pointer when not over text.\n\
10154 This variable takes effect when you create a new frame\n\
10155 or when you set the mouse color.");
10157 Vx_nontext_pointer_shape
= Qnil
;
10159 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
10160 "The shape of the pointer when Emacs is busy.\n\
10161 This variable takes effect when you create a new frame\n\
10162 or when you set the mouse color.");
10163 Vx_busy_pointer_shape
= Qnil
;
10165 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
10166 "Non-zero means Emacs displays a busy cursor on window systems.");
10167 display_busy_cursor_p
= 1;
10169 #if 0 /* This doesn't really do anything. */
10170 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
10171 "The shape of the pointer when over the mode line.\n\
10172 This variable takes effect when you create a new frame\n\
10173 or when you set the mouse color.");
10175 Vx_mode_pointer_shape
= Qnil
;
10177 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10178 &Vx_sensitive_text_pointer_shape
,
10179 "The shape of the pointer when over mouse-sensitive text.\n\
10180 This variable takes effect when you create a new frame\n\
10181 or when you set the mouse color.");
10182 Vx_sensitive_text_pointer_shape
= Qnil
;
10184 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
10185 "A string indicating the foreground color of the cursor box.");
10186 Vx_cursor_fore_pixel
= Qnil
;
10188 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
10189 "Non-nil if no X window manager is in use.\n\
10190 Emacs doesn't try to figure this out; this is always nil\n\
10191 unless you set it to something else.");
10192 /* We don't have any way to find this out, so set it to nil
10193 and maybe the user would like to set it to t. */
10194 Vx_no_window_manager
= Qnil
;
10196 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10197 &Vx_pixel_size_width_font_regexp
,
10198 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10200 Since Emacs gets width of a font matching with this regexp from\n\
10201 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10202 such a font. This is especially effective for such large fonts as\n\
10203 Chinese, Japanese, and Korean.");
10204 Vx_pixel_size_width_font_regexp
= Qnil
;
10206 DEFVAR_LISP ("image-eviction-seconds", &Vimage_eviction_seconds
,
10207 "Time after which cached images are removed from the cache.\n\
10208 When an image has not been displayed this many seconds, remove it\n\
10209 from the image cache. Value must be an integer or nil with nil\n\
10210 meaning don't clear the cache.");
10211 Vimage_eviction_seconds
= make_number (30 * 60);
10213 DEFVAR_LISP ("image-types", &Vimage_types
,
10214 "List of supported image types.\n\
10215 Each element of the list is a symbol for a supported image type.");
10216 Vimage_types
= Qnil
;
10218 #ifdef USE_X_TOOLKIT
10219 Fprovide (intern ("x-toolkit"));
10222 Fprovide (intern ("motif"));
10225 defsubr (&Sx_get_resource
);
10227 /* X window properties. */
10228 defsubr (&Sx_change_window_property
);
10229 defsubr (&Sx_delete_window_property
);
10230 defsubr (&Sx_window_property
);
10233 defsubr (&Sx_draw_rectangle
);
10234 defsubr (&Sx_erase_rectangle
);
10235 defsubr (&Sx_contour_region
);
10236 defsubr (&Sx_uncontour_region
);
10238 defsubr (&Sx_display_color_p
);
10239 defsubr (&Sx_display_grayscale_p
);
10240 defsubr (&Sx_color_defined_p
);
10241 defsubr (&Sx_color_values
);
10242 defsubr (&Sx_server_max_request_size
);
10243 defsubr (&Sx_server_vendor
);
10244 defsubr (&Sx_server_version
);
10245 defsubr (&Sx_display_pixel_width
);
10246 defsubr (&Sx_display_pixel_height
);
10247 defsubr (&Sx_display_mm_width
);
10248 defsubr (&Sx_display_mm_height
);
10249 defsubr (&Sx_display_screens
);
10250 defsubr (&Sx_display_planes
);
10251 defsubr (&Sx_display_color_cells
);
10252 defsubr (&Sx_display_visual_class
);
10253 defsubr (&Sx_display_backing_store
);
10254 defsubr (&Sx_display_save_under
);
10256 defsubr (&Sx_rebind_key
);
10257 defsubr (&Sx_rebind_keys
);
10258 defsubr (&Sx_track_pointer
);
10259 defsubr (&Sx_grab_pointer
);
10260 defsubr (&Sx_ungrab_pointer
);
10262 defsubr (&Sx_parse_geometry
);
10263 defsubr (&Sx_create_frame
);
10265 defsubr (&Sx_horizontal_line
);
10267 defsubr (&Sx_open_connection
);
10268 defsubr (&Sx_close_connection
);
10269 defsubr (&Sx_display_list
);
10270 defsubr (&Sx_synchronize
);
10272 /* Setting callback functions for fontset handler. */
10273 get_font_info_func
= x_get_font_info
;
10275 #if 0 /* This function pointer doesn't seem to be used anywhere.
10276 And the pointer assigned has the wrong type, anyway. */
10277 list_fonts_func
= x_list_fonts
;
10280 load_font_func
= x_load_font
;
10281 find_ccl_program_func
= x_find_ccl_program
;
10282 query_font_func
= x_query_font
;
10283 set_frame_fontset_func
= x_set_font
;
10284 check_window_system_func
= check_x
;
10287 Qxbm
= intern ("xbm");
10289 QCtype
= intern (":type");
10290 staticpro (&QCtype
);
10291 QCfile
= intern (":file");
10292 staticpro (&QCfile
);
10293 QCalgorithm
= intern (":algorithm");
10294 staticpro (&QCalgorithm
);
10295 QCheuristic_mask
= intern (":heuristic-mask");
10296 staticpro (&QCheuristic_mask
);
10297 QCcolor_symbols
= intern (":color-symbols");
10298 staticpro (&QCcolor_symbols
);
10299 QCdata
= intern (":data");
10300 staticpro (&QCdata
);
10301 QCascent
= intern (":ascent");
10302 staticpro (&QCascent
);
10303 QCmargin
= intern (":margin");
10304 staticpro (&QCmargin
);
10305 QCrelief
= intern (":relief");
10306 staticpro (&QCrelief
);
10307 Qghostscript
= intern ("ghostscript");
10308 staticpro (&Qghostscript
);
10309 QCloader
= intern (":loader");
10310 staticpro (&QCloader
);
10311 QCbounding_box
= intern (":bounding-box");
10312 staticpro (&QCbounding_box
);
10313 QCpt_width
= intern (":pt-width");
10314 staticpro (&QCpt_width
);
10315 QCpt_height
= intern (":pt-height");
10316 staticpro (&QCpt_height
);
10317 Qpbm
= intern ("pbm");
10321 Qxpm
= intern ("xpm");
10326 Qjpeg
= intern ("jpeg");
10327 staticpro (&Qjpeg
);
10331 Qtiff
= intern ("tiff");
10332 staticpro (&Qtiff
);
10336 Qgif
= intern ("gif");
10341 Qpng
= intern ("png");
10345 defsubr (&Sclear_image_cache
);
10348 defsubr (&Simagep
);
10349 defsubr (&Slookup_image
);
10353 defsubr (&Sx_show_busy_cursor
);
10354 defsubr (&Sx_hide_busy_cursor
);
10356 inhibit_busy_cursor
= 0;
10358 defsubr (&Sx_show_tip
);
10359 defsubr (&Sx_hide_tip
);
10360 staticpro (&tip_timer
);
10364 defsubr (&Sx_file_dialog
);
10372 image_types
= NULL
;
10373 Vimage_types
= Qnil
;
10375 define_image_type (&xbm_type
);
10376 define_image_type (&gs_type
);
10377 define_image_type (&pbm_type
);
10380 define_image_type (&xpm_type
);
10384 define_image_type (&jpeg_type
);
10388 define_image_type (&tiff_type
);
10392 define_image_type (&gif_type
);
10396 define_image_type (&png_type
);
10400 #endif /* HAVE_X_WINDOWS */