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 /* Now process them in reverse of specified order. */
886 for (i
--; i
>= 0; i
--)
888 Lisp_Object prop
, val
;
893 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
894 width
= XFASTINT (val
);
895 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
896 height
= XFASTINT (val
);
897 else if (EQ (prop
, Qtop
))
899 else if (EQ (prop
, Qleft
))
901 else if (EQ (prop
, Qicon_top
))
903 else if (EQ (prop
, Qicon_left
))
907 register Lisp_Object param_index
, old_value
;
909 param_index
= Fget (prop
, Qx_frame_parameter
);
910 old_value
= get_frame_param (f
, prop
);
911 store_frame_param (f
, prop
, val
);
912 if (NATNUMP (param_index
)
913 && (XFASTINT (param_index
)
914 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
915 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
919 /* Don't die if just one of these was set. */
920 if (EQ (left
, Qunbound
))
923 if (f
->output_data
.x
->left_pos
< 0)
924 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
926 XSETINT (left
, f
->output_data
.x
->left_pos
);
928 if (EQ (top
, Qunbound
))
931 if (f
->output_data
.x
->top_pos
< 0)
932 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
934 XSETINT (top
, f
->output_data
.x
->top_pos
);
937 /* If one of the icon positions was not set, preserve or default it. */
938 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
940 icon_left_no_change
= 1;
941 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
942 if (NILP (icon_left
))
943 XSETINT (icon_left
, 0);
945 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
947 icon_top_no_change
= 1;
948 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
950 XSETINT (icon_top
, 0);
953 /* Don't set these parameters unless they've been explicitly
954 specified. The window might be mapped or resized while we're in
955 this function, and we don't want to override that unless the lisp
956 code has asked for it.
958 Don't set these parameters unless they actually differ from the
959 window's current parameters; the window may not actually exist
964 check_frame_size (f
, &height
, &width
);
966 XSETFRAME (frame
, f
);
968 if (width
!= FRAME_WIDTH (f
)
969 || height
!= FRAME_HEIGHT (f
)
970 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
971 Fset_frame_size (frame
, make_number (width
), make_number (height
));
973 if ((!NILP (left
) || !NILP (top
))
974 && ! (left_no_change
&& top_no_change
)
975 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
976 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
981 /* Record the signs. */
982 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
983 if (EQ (left
, Qminus
))
984 f
->output_data
.x
->size_hint_flags
|= XNegative
;
985 else if (INTEGERP (left
))
987 leftpos
= XINT (left
);
989 f
->output_data
.x
->size_hint_flags
|= XNegative
;
991 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
992 && CONSP (XCONS (left
)->cdr
)
993 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
995 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
996 f
->output_data
.x
->size_hint_flags
|= XNegative
;
998 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
999 && CONSP (XCONS (left
)->cdr
)
1000 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
1002 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
1005 if (EQ (top
, Qminus
))
1006 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1007 else if (INTEGERP (top
))
1009 toppos
= XINT (top
);
1011 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1013 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
1014 && CONSP (XCONS (top
)->cdr
)
1015 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
1017 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
1018 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1020 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
1021 && CONSP (XCONS (top
)->cdr
)
1022 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
1024 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
1028 /* Store the numeric value of the position. */
1029 f
->output_data
.x
->top_pos
= toppos
;
1030 f
->output_data
.x
->left_pos
= leftpos
;
1032 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1034 /* Actually set that position, and convert to absolute. */
1035 x_set_offset (f
, leftpos
, toppos
, -1);
1038 if ((!NILP (icon_left
) || !NILP (icon_top
))
1039 && ! (icon_left_no_change
&& icon_top_no_change
))
1040 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1046 /* Store the screen positions of frame F into XPTR and YPTR.
1047 These are the positions of the containing window manager window,
1048 not Emacs's own window. */
1051 x_real_positions (f
, xptr
, yptr
)
1058 /* This is pretty gross, but seems to be the easiest way out of
1059 the problem that arises when restarting window-managers. */
1061 #ifdef USE_X_TOOLKIT
1062 Window outer
= (f
->output_data
.x
->widget
1063 ? XtWindow (f
->output_data
.x
->widget
)
1064 : FRAME_X_WINDOW (f
));
1066 Window outer
= f
->output_data
.x
->window_desc
;
1068 Window tmp_root_window
;
1069 Window
*tmp_children
;
1074 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1075 Window outer_window
;
1077 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1078 &f
->output_data
.x
->parent_desc
,
1079 &tmp_children
, &tmp_nchildren
);
1080 XFree ((char *) tmp_children
);
1084 /* Find the position of the outside upper-left corner of
1085 the inner window, with respect to the outer window. */
1086 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1087 outer_window
= f
->output_data
.x
->parent_desc
;
1089 outer_window
= outer
;
1091 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1093 /* From-window, to-window. */
1095 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1097 /* From-position, to-position. */
1098 0, 0, &win_x
, &win_y
,
1103 /* It is possible for the window returned by the XQueryNotify
1104 to become invalid by the time we call XTranslateCoordinates.
1105 That can happen when you restart some window managers.
1106 If so, we get an error in XTranslateCoordinates.
1107 Detect that and try the whole thing over. */
1108 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1110 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1114 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1121 /* Insert a description of internally-recorded parameters of frame X
1122 into the parameter alist *ALISTPTR that is to be given to the user.
1123 Only parameters that are specific to the X window system
1124 and whose values are not correctly recorded in the frame's
1125 param_alist need to be considered here. */
1128 x_report_frame_params (f
, alistptr
)
1130 Lisp_Object
*alistptr
;
1135 /* Represent negative positions (off the top or left screen edge)
1136 in a way that Fmodify_frame_parameters will understand correctly. */
1137 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1138 if (f
->output_data
.x
->left_pos
>= 0)
1139 store_in_alist (alistptr
, Qleft
, tem
);
1141 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1143 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1144 if (f
->output_data
.x
->top_pos
>= 0)
1145 store_in_alist (alistptr
, Qtop
, tem
);
1147 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1149 store_in_alist (alistptr
, Qborder_width
,
1150 make_number (f
->output_data
.x
->border_width
));
1151 store_in_alist (alistptr
, Qinternal_border_width
,
1152 make_number (f
->output_data
.x
->internal_border_width
));
1153 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1154 store_in_alist (alistptr
, Qwindow_id
,
1155 build_string (buf
));
1156 #ifdef USE_X_TOOLKIT
1157 /* Tooltip frame may not have this widget. */
1158 if (f
->output_data
.x
->widget
)
1160 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1161 store_in_alist (alistptr
, Qouter_window_id
,
1162 build_string (buf
));
1163 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1164 FRAME_SAMPLE_VISIBILITY (f
);
1165 store_in_alist (alistptr
, Qvisibility
,
1166 (FRAME_VISIBLE_P (f
) ? Qt
1167 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1168 store_in_alist (alistptr
, Qdisplay
,
1169 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->car
);
1171 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1174 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1175 store_in_alist (alistptr
, Qparent_id
, tem
);
1179 /* Decide if color named COLOR is valid for the display associated with
1180 the selected frame; if so, return the rgb values in COLOR_DEF.
1181 If ALLOC is nonzero, allocate a new colormap cell. */
1184 defined_color (f
, color
, color_def
, alloc
)
1190 register int status
;
1191 Colormap screen_colormap
;
1192 Display
*display
= FRAME_X_DISPLAY (f
);
1195 screen_colormap
= DefaultColormap (display
, XDefaultScreen (display
));
1197 status
= XParseColor (display
, screen_colormap
, color
, color_def
);
1198 if (status
&& alloc
)
1200 status
= XAllocColor (display
, screen_colormap
, color_def
);
1203 /* If we got to this point, the colormap is full, so we're
1204 going to try and get the next closest color.
1205 The algorithm used is a least-squares matching, which is
1206 what X uses for closest color matching with StaticColor visuals. */
1211 long nearest_delta
, trial_delta
;
1214 no_cells
= XDisplayCells (display
, XDefaultScreen (display
));
1215 cells
= (XColor
*) alloca (sizeof (XColor
) * no_cells
);
1217 for (x
= 0; x
< no_cells
; x
++)
1220 XQueryColors (display
, screen_colormap
, cells
, no_cells
);
1222 /* I'm assuming CSE so I'm not going to condense this. */
1223 nearest_delta
= ((((color_def
->red
>> 8) - (cells
[0].red
>> 8))
1224 * ((color_def
->red
>> 8) - (cells
[0].red
>> 8)))
1226 (((color_def
->green
>> 8) - (cells
[0].green
>> 8))
1227 * ((color_def
->green
>> 8) - (cells
[0].green
>> 8)))
1229 (((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))
1230 * ((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))));
1231 for (x
= 1; x
< no_cells
; x
++)
1233 trial_delta
= ((((color_def
->red
>> 8) - (cells
[x
].red
>> 8))
1234 * ((color_def
->red
>> 8) - (cells
[x
].red
>> 8)))
1236 (((color_def
->green
>> 8) - (cells
[x
].green
>> 8))
1237 * ((color_def
->green
>> 8) - (cells
[x
].green
>> 8)))
1239 (((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))
1240 * ((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))));
1241 if (trial_delta
< nearest_delta
)
1244 temp
.red
= cells
[x
].red
;
1245 temp
.green
= cells
[x
].green
;
1246 temp
.blue
= cells
[x
].blue
;
1247 status
= XAllocColor (display
, screen_colormap
, &temp
);
1251 nearest_delta
= trial_delta
;
1255 color_def
->red
= cells
[nearest
].red
;
1256 color_def
->green
= cells
[nearest
].green
;
1257 color_def
->blue
= cells
[nearest
].blue
;
1258 status
= XAllocColor (display
, screen_colormap
, color_def
);
1269 /* Given a string ARG naming a color, compute a pixel value from it
1270 suitable for screen F.
1271 If F is not a color screen, return DEF (default) regardless of what
1275 x_decode_color (f
, arg
, def
)
1282 CHECK_STRING (arg
, 0);
1284 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1285 return BLACK_PIX_DEFAULT (f
);
1286 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1287 return WHITE_PIX_DEFAULT (f
);
1289 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1292 /* defined_color is responsible for coping with failures
1293 by looking for a near-miss. */
1294 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1297 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
1298 Fcons (arg
, Qnil
)));
1301 /* Functions called only from `x_set_frame_param'
1302 to set individual parameters.
1304 If FRAME_X_WINDOW (f) is 0,
1305 the frame is being created and its X-window does not exist yet.
1306 In that case, just record the parameter's new value
1307 in the standard place; do not attempt to change the window. */
1310 x_set_foreground_color (f
, arg
, oldval
)
1312 Lisp_Object arg
, oldval
;
1315 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1317 if (f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->mouse_pixel
1318 && f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->cursor_pixel
1319 && f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
)
1320 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
1321 f
->output_data
.x
->foreground_pixel
= pixel
;
1323 if (FRAME_X_WINDOW (f
) != 0)
1326 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1327 f
->output_data
.x
->foreground_pixel
);
1328 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1329 f
->output_data
.x
->foreground_pixel
);
1331 recompute_basic_faces (f
);
1332 if (FRAME_VISIBLE_P (f
))
1338 x_set_background_color (f
, arg
, oldval
)
1340 Lisp_Object arg
, oldval
;
1346 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1348 if (f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->mouse_pixel
1349 && f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->cursor_pixel
1350 && f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
)
1351 unload_color (f
, f
->output_data
.x
->background_pixel
);
1352 f
->output_data
.x
->background_pixel
= pixel
;
1354 if (FRAME_X_WINDOW (f
) != 0)
1357 /* The main frame area. */
1358 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1359 f
->output_data
.x
->background_pixel
);
1360 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1361 f
->output_data
.x
->background_pixel
);
1362 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1363 f
->output_data
.x
->background_pixel
);
1364 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1365 f
->output_data
.x
->background_pixel
);
1368 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1369 bar
= XSCROLL_BAR (bar
)->next
)
1370 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1371 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1372 f
->output_data
.x
->background_pixel
);
1376 recompute_basic_faces (f
);
1378 if (FRAME_VISIBLE_P (f
))
1384 x_set_mouse_color (f
, arg
, oldval
)
1386 Lisp_Object arg
, oldval
;
1388 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1392 unsigned long pixel
= f
->output_data
.x
->mouse_pixel
;
1394 if (!EQ (Qnil
, arg
))
1395 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1397 mask_color
= f
->output_data
.x
->background_pixel
;
1398 /* No invisible pointers. */
1399 if (mask_color
== pixel
1400 && mask_color
== f
->output_data
.x
->background_pixel
)
1401 pixel
= f
->output_data
.x
->foreground_pixel
;
1403 if (f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->mouse_pixel
1404 && f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->mouse_pixel
1405 && f
->output_data
.x
->cursor_pixel
!= f
->output_data
.x
->mouse_pixel
1406 && f
->output_data
.x
->cursor_foreground_pixel
!= f
->output_data
.x
->mouse_pixel
)
1407 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
1408 f
->output_data
.x
->mouse_pixel
= pixel
;
1412 /* It's not okay to crash if the user selects a screwy cursor. */
1413 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1415 if (!EQ (Qnil
, Vx_pointer_shape
))
1417 CHECK_NUMBER (Vx_pointer_shape
, 0);
1418 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1421 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1422 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1424 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1426 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1427 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1428 XINT (Vx_nontext_pointer_shape
));
1431 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1432 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1434 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
1436 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
1437 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1438 XINT (Vx_busy_pointer_shape
));
1441 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_watch
);
1442 x_check_errors (FRAME_X_DISPLAY (f
), "bad busy pointer cursor: %s");
1444 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1445 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1447 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1448 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1449 XINT (Vx_mode_pointer_shape
));
1452 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1453 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1455 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1457 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1459 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1460 XINT (Vx_sensitive_text_pointer_shape
));
1463 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1465 /* Check and report errors with the above calls. */
1466 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1467 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1470 XColor fore_color
, back_color
;
1472 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1473 back_color
.pixel
= mask_color
;
1474 XQueryColor (FRAME_X_DISPLAY (f
),
1475 DefaultColormap (FRAME_X_DISPLAY (f
),
1476 DefaultScreen (FRAME_X_DISPLAY (f
))),
1478 XQueryColor (FRAME_X_DISPLAY (f
),
1479 DefaultColormap (FRAME_X_DISPLAY (f
),
1480 DefaultScreen (FRAME_X_DISPLAY (f
))),
1482 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1483 &fore_color
, &back_color
);
1484 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1485 &fore_color
, &back_color
);
1486 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1487 &fore_color
, &back_color
);
1488 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1489 &fore_color
, &back_color
);
1490 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1491 &fore_color
, &back_color
);
1494 if (FRAME_X_WINDOW (f
) != 0)
1495 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1497 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1498 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1499 f
->output_data
.x
->text_cursor
= cursor
;
1501 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1502 && f
->output_data
.x
->nontext_cursor
!= 0)
1503 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1504 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1506 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1507 && f
->output_data
.x
->busy_cursor
!= 0)
1508 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1509 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1511 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1512 && f
->output_data
.x
->modeline_cursor
!= 0)
1513 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1514 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1516 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1517 && f
->output_data
.x
->cross_cursor
!= 0)
1518 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1519 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1521 XFlush (FRAME_X_DISPLAY (f
));
1526 x_set_cursor_color (f
, arg
, oldval
)
1528 Lisp_Object arg
, oldval
;
1530 unsigned long fore_pixel
, pixel
;
1532 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1533 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1534 WHITE_PIX_DEFAULT (f
));
1536 fore_pixel
= f
->output_data
.x
->background_pixel
;
1537 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1539 /* Make sure that the cursor color differs from the background color. */
1540 if (pixel
== f
->output_data
.x
->background_pixel
)
1542 pixel
= f
->output_data
.x
->mouse_pixel
;
1543 if (pixel
== fore_pixel
)
1544 fore_pixel
= f
->output_data
.x
->background_pixel
;
1547 if (f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
1548 && f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
1549 && f
->output_data
.x
->mouse_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
1550 && f
->output_data
.x
->cursor_pixel
!= f
->output_data
.x
->cursor_foreground_pixel
)
1551 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1552 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1554 if (f
->output_data
.x
->background_pixel
!= f
->output_data
.x
->cursor_pixel
1555 && f
->output_data
.x
->foreground_pixel
!= f
->output_data
.x
->cursor_pixel
1556 && f
->output_data
.x
->mouse_pixel
!= f
->output_data
.x
->cursor_pixel
1557 && f
->output_data
.x
->cursor_foreground_pixel
!= f
->output_data
.x
->cursor_pixel
)
1558 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1559 f
->output_data
.x
->cursor_pixel
= pixel
;
1561 if (FRAME_X_WINDOW (f
) != 0)
1564 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1565 f
->output_data
.x
->cursor_pixel
);
1566 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1570 if (FRAME_VISIBLE_P (f
))
1572 x_update_cursor (f
, 0);
1573 x_update_cursor (f
, 1);
1578 /* Set the border-color of frame F to value described by ARG.
1579 ARG can be a string naming a color.
1580 The border-color is used for the border that is drawn by the X server.
1581 Note that this does not fully take effect if done before
1582 F has an x-window; it must be redone when the window is created.
1584 Note: this is done in two routines because of the way X10 works.
1586 Note: under X11, this is normally the province of the window manager,
1587 and so emacs' border colors may be overridden. */
1590 x_set_border_color (f
, arg
, oldval
)
1592 Lisp_Object arg
, oldval
;
1597 CHECK_STRING (arg
, 0);
1598 str
= XSTRING (arg
)->data
;
1600 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1602 x_set_border_pixel (f
, pix
);
1605 /* Set the border-color of frame F to pixel value PIX.
1606 Note that this does not fully take effect if done before
1607 F has an x-window. */
1610 x_set_border_pixel (f
, pix
)
1614 unload_color (f
, f
->output_data
.x
->border_pixel
);
1615 f
->output_data
.x
->border_pixel
= pix
;
1617 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1623 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1624 (unsigned long)pix
);
1627 if (FRAME_VISIBLE_P (f
))
1633 x_set_cursor_type (f
, arg
, oldval
)
1635 Lisp_Object arg
, oldval
;
1639 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1640 f
->output_data
.x
->cursor_width
= 2;
1642 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
1643 && INTEGERP (XCONS (arg
)->cdr
))
1645 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1646 f
->output_data
.x
->cursor_width
= XINT (XCONS (arg
)->cdr
);
1649 /* Treat anything unknown as "box cursor".
1650 It was bad to signal an error; people have trouble fixing
1651 .Xdefaults with Emacs, when it has something bad in it. */
1652 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
1654 /* Make sure the cursor gets redrawn. This is overkill, but how
1655 often do people change cursor types? */
1656 update_mode_lines
++;
1660 x_set_icon_type (f
, arg
, oldval
)
1662 Lisp_Object arg
, oldval
;
1668 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1671 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1676 result
= x_text_icon (f
,
1677 (char *) XSTRING ((!NILP (f
->icon_name
)
1681 result
= x_bitmap_icon (f
, arg
);
1686 error ("No icon window available");
1689 XFlush (FRAME_X_DISPLAY (f
));
1693 /* Return non-nil if frame F wants a bitmap icon. */
1701 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1703 return XCONS (tem
)->cdr
;
1709 x_set_icon_name (f
, arg
, oldval
)
1711 Lisp_Object arg
, oldval
;
1717 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1720 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1725 if (f
->output_data
.x
->icon_bitmap
!= 0)
1730 result
= x_text_icon (f
,
1731 (char *) XSTRING ((!NILP (f
->icon_name
)
1740 error ("No icon window available");
1743 XFlush (FRAME_X_DISPLAY (f
));
1748 x_set_font (f
, arg
, oldval
)
1750 Lisp_Object arg
, oldval
;
1753 Lisp_Object fontset_name
;
1756 CHECK_STRING (arg
, 1);
1758 fontset_name
= Fquery_fontset (arg
, Qnil
);
1761 result
= (STRINGP (fontset_name
)
1762 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1763 : x_new_font (f
, XSTRING (arg
)->data
));
1766 if (EQ (result
, Qnil
))
1767 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1768 else if (EQ (result
, Qt
))
1769 error ("The characters of the given font have varying widths");
1770 else if (STRINGP (result
))
1772 store_frame_param (f
, Qfont
, result
);
1773 recompute_basic_faces (f
);
1778 /* Don't call `face-set-after-frame-default' when faces haven't been
1779 initialized yet. This is the case when called from
1780 Fx_create_frame. In that case, the X widget or window doesn't
1781 exist either, and we can end up in x_report_frame_params with a
1782 null widget which gives a segfault. */
1783 if (FRAME_FACE_CACHE (f
))
1785 XSETFRAME (frame
, f
);
1786 call1 (Qface_set_after_frame_default
, frame
);
1791 x_set_border_width (f
, arg
, oldval
)
1793 Lisp_Object arg
, oldval
;
1795 CHECK_NUMBER (arg
, 0);
1797 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1800 if (FRAME_X_WINDOW (f
) != 0)
1801 error ("Cannot change the border width of a window");
1803 f
->output_data
.x
->border_width
= XINT (arg
);
1807 x_set_internal_border_width (f
, arg
, oldval
)
1809 Lisp_Object arg
, oldval
;
1811 int old
= f
->output_data
.x
->internal_border_width
;
1813 CHECK_NUMBER (arg
, 0);
1814 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1815 if (f
->output_data
.x
->internal_border_width
< 0)
1816 f
->output_data
.x
->internal_border_width
= 0;
1818 #ifdef USE_X_TOOLKIT
1819 if (f
->output_data
.x
->edit_widget
)
1820 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1823 if (f
->output_data
.x
->internal_border_width
== old
)
1826 if (FRAME_X_WINDOW (f
) != 0)
1829 x_set_window_size (f
, 0, f
->width
, f
->height
);
1831 x_set_resize_hint (f
);
1833 XFlush (FRAME_X_DISPLAY (f
));
1835 SET_FRAME_GARBAGED (f
);
1840 x_set_visibility (f
, value
, oldval
)
1842 Lisp_Object value
, oldval
;
1845 XSETFRAME (frame
, f
);
1848 Fmake_frame_invisible (frame
, Qt
);
1849 else if (EQ (value
, Qicon
))
1850 Ficonify_frame (frame
);
1852 Fmake_frame_visible (frame
);
1856 x_set_menu_bar_lines_1 (window
, n
)
1860 struct window
*w
= XWINDOW (window
);
1862 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1863 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1865 /* Handle just the top child in a vertical split. */
1866 if (!NILP (w
->vchild
))
1867 x_set_menu_bar_lines_1 (w
->vchild
, n
);
1869 /* Adjust all children in a horizontal split. */
1870 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1872 w
= XWINDOW (window
);
1873 x_set_menu_bar_lines_1 (window
, n
);
1878 x_set_menu_bar_lines (f
, value
, oldval
)
1880 Lisp_Object value
, oldval
;
1883 int olines
= FRAME_MENU_BAR_LINES (f
);
1885 /* Right now, menu bars don't work properly in minibuf-only frames;
1886 most of the commands try to apply themselves to the minibuffer
1887 frame itself, and get an error because you can't switch buffers
1888 in or split the minibuffer window. */
1889 if (FRAME_MINIBUF_ONLY_P (f
))
1892 if (INTEGERP (value
))
1893 nlines
= XINT (value
);
1897 /* Make sure we redisplay all windows in this frame. */
1898 windows_or_buffers_changed
++;
1900 #ifdef USE_X_TOOLKIT
1901 FRAME_MENU_BAR_LINES (f
) = 0;
1904 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1905 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1906 /* Make sure next redisplay shows the menu bar. */
1907 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1911 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1912 free_frame_menubar (f
);
1913 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1915 f
->output_data
.x
->menubar_widget
= 0;
1917 #else /* not USE_X_TOOLKIT */
1918 FRAME_MENU_BAR_LINES (f
) = nlines
;
1919 x_set_menu_bar_lines_1 (f
->root_window
, nlines
- olines
);
1920 #endif /* not USE_X_TOOLKIT */
1925 /* Set the number of lines used for the tool bar of frame F to VALUE.
1926 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1927 is the old number of tool bar lines. This function changes the
1928 height of all windows on frame F to match the new tool bar height.
1929 The frame's height doesn't change. */
1932 x_set_toolbar_lines (f
, value
, oldval
)
1934 Lisp_Object value
, oldval
;
1938 /* Use VALUE only if an integer >= 0. */
1939 if (INTEGERP (value
) && XINT (value
) >= 0)
1940 nlines
= XFASTINT (value
);
1944 /* Make sure we redisplay all windows in this frame. */
1945 ++windows_or_buffers_changed
;
1947 delta
= nlines
- FRAME_TOOLBAR_LINES (f
);
1948 FRAME_TOOLBAR_LINES (f
) = nlines
;
1949 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f
), delta
);
1954 /* Set the foreground color for scroll bars on frame F to VALUE.
1955 VALUE should be a string, a color name. If it isn't a string or
1956 isn't a valid color name, do nothing. OLDVAL is the old value of
1957 the frame parameter. */
1960 x_set_scroll_bar_foreground (f
, value
, oldval
)
1962 Lisp_Object value
, oldval
;
1964 unsigned long pixel
;
1966 if (STRINGP (value
))
1967 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
1971 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
1972 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
1974 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
1975 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
1977 /* Remove all scroll bars because they have wrong colors. */
1978 if (condemn_scroll_bars_hook
)
1979 (*condemn_scroll_bars_hook
) (f
);
1980 if (judge_scroll_bars_hook
)
1981 (*judge_scroll_bars_hook
) (f
);
1988 /* Set the background color for scroll bars on frame F to VALUE VALUE
1989 should be a string, a color name. If it isn't a string or isn't a
1990 valid color name, do nothing. OLDVAL is the old value of the frame
1994 x_set_scroll_bar_background (f
, value
, oldval
)
1996 Lisp_Object value
, oldval
;
1998 unsigned long pixel
;
2000 if (STRINGP (value
))
2001 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2005 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2006 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2008 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2009 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2011 /* Remove all scroll bars because they have wrong colors. */
2012 if (condemn_scroll_bars_hook
)
2013 (*condemn_scroll_bars_hook
) (f
);
2014 if (judge_scroll_bars_hook
)
2015 (*judge_scroll_bars_hook
) (f
);
2022 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2025 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2026 name; if NAME is a string, set F's name to NAME and set
2027 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2029 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2030 suggesting a new name, which lisp code should override; if
2031 F->explicit_name is set, ignore the new name; otherwise, set it. */
2034 x_set_name (f
, name
, explicit)
2039 /* Make sure that requests from lisp code override requests from
2040 Emacs redisplay code. */
2043 /* If we're switching from explicit to implicit, we had better
2044 update the mode lines and thereby update the title. */
2045 if (f
->explicit_name
&& NILP (name
))
2046 update_mode_lines
= 1;
2048 f
->explicit_name
= ! NILP (name
);
2050 else if (f
->explicit_name
)
2053 /* If NAME is nil, set the name to the x_id_name. */
2056 /* Check for no change needed in this very common case
2057 before we do any consing. */
2058 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2059 XSTRING (f
->name
)->data
))
2061 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2064 CHECK_STRING (name
, 0);
2066 /* Don't change the name if it's already NAME. */
2067 if (! NILP (Fstring_equal (name
, f
->name
)))
2072 /* For setting the frame title, the title parameter should override
2073 the name parameter. */
2074 if (! NILP (f
->title
))
2077 if (FRAME_X_WINDOW (f
))
2082 XTextProperty text
, icon
;
2083 Lisp_Object icon_name
;
2085 text
.value
= XSTRING (name
)->data
;
2086 text
.encoding
= XA_STRING
;
2088 text
.nitems
= STRING_BYTES (XSTRING (name
));
2090 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2092 icon
.value
= XSTRING (icon_name
)->data
;
2093 icon
.encoding
= XA_STRING
;
2095 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2096 #ifdef USE_X_TOOLKIT
2097 XSetWMName (FRAME_X_DISPLAY (f
),
2098 XtWindow (f
->output_data
.x
->widget
), &text
);
2099 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2101 #else /* not USE_X_TOOLKIT */
2102 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2103 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2104 #endif /* not USE_X_TOOLKIT */
2106 #else /* not HAVE_X11R4 */
2107 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2108 XSTRING (name
)->data
);
2109 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2110 XSTRING (name
)->data
);
2111 #endif /* not HAVE_X11R4 */
2116 /* This function should be called when the user's lisp code has
2117 specified a name for the frame; the name will override any set by the
2120 x_explicitly_set_name (f
, arg
, oldval
)
2122 Lisp_Object arg
, oldval
;
2124 x_set_name (f
, arg
, 1);
2127 /* This function should be called by Emacs redisplay code to set the
2128 name; names set this way will never override names set by the user's
2131 x_implicitly_set_name (f
, arg
, oldval
)
2133 Lisp_Object arg
, oldval
;
2135 x_set_name (f
, arg
, 0);
2138 /* Change the title of frame F to NAME.
2139 If NAME is nil, use the frame name as the title.
2141 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2142 name; if NAME is a string, set F's name to NAME and set
2143 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2145 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2146 suggesting a new name, which lisp code should override; if
2147 F->explicit_name is set, ignore the new name; otherwise, set it. */
2150 x_set_title (f
, name
)
2154 /* Don't change the title if it's already NAME. */
2155 if (EQ (name
, f
->title
))
2158 update_mode_lines
= 1;
2165 CHECK_STRING (name
, 0);
2167 if (FRAME_X_WINDOW (f
))
2172 XTextProperty text
, icon
;
2173 Lisp_Object icon_name
;
2175 text
.value
= XSTRING (name
)->data
;
2176 text
.encoding
= XA_STRING
;
2178 text
.nitems
= STRING_BYTES (XSTRING (name
));
2180 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2182 icon
.value
= XSTRING (icon_name
)->data
;
2183 icon
.encoding
= XA_STRING
;
2185 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2186 #ifdef USE_X_TOOLKIT
2187 XSetWMName (FRAME_X_DISPLAY (f
),
2188 XtWindow (f
->output_data
.x
->widget
), &text
);
2189 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2191 #else /* not USE_X_TOOLKIT */
2192 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2193 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2194 #endif /* not USE_X_TOOLKIT */
2196 #else /* not HAVE_X11R4 */
2197 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2198 XSTRING (name
)->data
);
2199 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2200 XSTRING (name
)->data
);
2201 #endif /* not HAVE_X11R4 */
2207 x_set_autoraise (f
, arg
, oldval
)
2209 Lisp_Object arg
, oldval
;
2211 f
->auto_raise
= !EQ (Qnil
, arg
);
2215 x_set_autolower (f
, arg
, oldval
)
2217 Lisp_Object arg
, oldval
;
2219 f
->auto_lower
= !EQ (Qnil
, arg
);
2223 x_set_unsplittable (f
, arg
, oldval
)
2225 Lisp_Object arg
, oldval
;
2227 f
->no_split
= !NILP (arg
);
2231 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2233 Lisp_Object arg
, oldval
;
2235 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2236 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2237 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2238 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2240 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2242 ? vertical_scroll_bar_none
2244 ? vertical_scroll_bar_right
2245 : vertical_scroll_bar_left
);
2247 /* We set this parameter before creating the X window for the
2248 frame, so we can get the geometry right from the start.
2249 However, if the window hasn't been created yet, we shouldn't
2250 call x_set_window_size. */
2251 if (FRAME_X_WINDOW (f
))
2252 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2257 x_set_scroll_bar_width (f
, arg
, oldval
)
2259 Lisp_Object arg
, oldval
;
2261 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2265 #ifdef USE_X_TOOLKIT
2266 /* A too wide or narrow toolkit scroll bar doesn't look good. */
2267 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2268 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2269 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2271 /* Make the actual width at least 14 pixels and a multiple of a
2273 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2275 /* Use all of that space (aside from required margins) for the
2277 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2280 if (FRAME_X_WINDOW (f
))
2281 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2283 else if (INTEGERP (arg
) && XINT (arg
) > 0
2284 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2286 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2287 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2289 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2290 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2291 if (FRAME_X_WINDOW (f
))
2292 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2295 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0);
2296 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2297 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2302 /* Subroutines of creating an X frame. */
2304 /* Make sure that Vx_resource_name is set to a reasonable value.
2305 Fix it up, or set it to `emacs' if it is too hopeless. */
2308 validate_x_resource_name ()
2311 /* Number of valid characters in the resource name. */
2313 /* Number of invalid characters in the resource name. */
2318 if (!STRINGP (Vx_resource_class
))
2319 Vx_resource_class
= build_string (EMACS_CLASS
);
2321 if (STRINGP (Vx_resource_name
))
2323 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2326 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2328 /* Only letters, digits, - and _ are valid in resource names.
2329 Count the valid characters and count the invalid ones. */
2330 for (i
= 0; i
< len
; i
++)
2333 if (! ((c
>= 'a' && c
<= 'z')
2334 || (c
>= 'A' && c
<= 'Z')
2335 || (c
>= '0' && c
<= '9')
2336 || c
== '-' || c
== '_'))
2343 /* Not a string => completely invalid. */
2344 bad_count
= 5, good_count
= 0;
2346 /* If name is valid already, return. */
2350 /* If name is entirely invalid, or nearly so, use `emacs'. */
2352 || (good_count
== 1 && bad_count
> 0))
2354 Vx_resource_name
= build_string ("emacs");
2358 /* Name is partly valid. Copy it and replace the invalid characters
2359 with underscores. */
2361 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2363 for (i
= 0; i
< len
; i
++)
2365 int c
= XSTRING (new)->data
[i
];
2366 if (! ((c
>= 'a' && c
<= 'z')
2367 || (c
>= 'A' && c
<= 'Z')
2368 || (c
>= '0' && c
<= '9')
2369 || c
== '-' || c
== '_'))
2370 XSTRING (new)->data
[i
] = '_';
2375 extern char *x_get_string_resource ();
2377 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2378 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2379 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2380 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2381 the name specified by the `-name' or `-rn' command-line arguments.\n\
2383 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2384 class, respectively. You must specify both of them or neither.\n\
2385 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2386 and the class is `Emacs.CLASS.SUBCLASS'.")
2387 (attribute
, class, component
, subclass
)
2388 Lisp_Object attribute
, class, component
, subclass
;
2390 register char *value
;
2396 CHECK_STRING (attribute
, 0);
2397 CHECK_STRING (class, 0);
2399 if (!NILP (component
))
2400 CHECK_STRING (component
, 1);
2401 if (!NILP (subclass
))
2402 CHECK_STRING (subclass
, 2);
2403 if (NILP (component
) != NILP (subclass
))
2404 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2406 validate_x_resource_name ();
2408 /* Allocate space for the components, the dots which separate them,
2409 and the final '\0'. Make them big enough for the worst case. */
2410 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2411 + (STRINGP (component
)
2412 ? STRING_BYTES (XSTRING (component
)) : 0)
2413 + STRING_BYTES (XSTRING (attribute
))
2416 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2417 + STRING_BYTES (XSTRING (class))
2418 + (STRINGP (subclass
)
2419 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2422 /* Start with emacs.FRAMENAME for the name (the specific one)
2423 and with `Emacs' for the class key (the general one). */
2424 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2425 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2427 strcat (class_key
, ".");
2428 strcat (class_key
, XSTRING (class)->data
);
2430 if (!NILP (component
))
2432 strcat (class_key
, ".");
2433 strcat (class_key
, XSTRING (subclass
)->data
);
2435 strcat (name_key
, ".");
2436 strcat (name_key
, XSTRING (component
)->data
);
2439 strcat (name_key
, ".");
2440 strcat (name_key
, XSTRING (attribute
)->data
);
2442 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2443 name_key
, class_key
);
2445 if (value
!= (char *) 0)
2446 return build_string (value
);
2451 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2454 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2455 struct x_display_info
*dpyinfo
;
2456 Lisp_Object attribute
, class, component
, subclass
;
2458 register char *value
;
2464 CHECK_STRING (attribute
, 0);
2465 CHECK_STRING (class, 0);
2467 if (!NILP (component
))
2468 CHECK_STRING (component
, 1);
2469 if (!NILP (subclass
))
2470 CHECK_STRING (subclass
, 2);
2471 if (NILP (component
) != NILP (subclass
))
2472 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2474 validate_x_resource_name ();
2476 /* Allocate space for the components, the dots which separate them,
2477 and the final '\0'. Make them big enough for the worst case. */
2478 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2479 + (STRINGP (component
)
2480 ? STRING_BYTES (XSTRING (component
)) : 0)
2481 + STRING_BYTES (XSTRING (attribute
))
2484 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2485 + STRING_BYTES (XSTRING (class))
2486 + (STRINGP (subclass
)
2487 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2490 /* Start with emacs.FRAMENAME for the name (the specific one)
2491 and with `Emacs' for the class key (the general one). */
2492 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2493 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2495 strcat (class_key
, ".");
2496 strcat (class_key
, XSTRING (class)->data
);
2498 if (!NILP (component
))
2500 strcat (class_key
, ".");
2501 strcat (class_key
, XSTRING (subclass
)->data
);
2503 strcat (name_key
, ".");
2504 strcat (name_key
, XSTRING (component
)->data
);
2507 strcat (name_key
, ".");
2508 strcat (name_key
, XSTRING (attribute
)->data
);
2510 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2512 if (value
!= (char *) 0)
2513 return build_string (value
);
2518 /* Used when C code wants a resource value. */
2521 x_get_resource_string (attribute
, class)
2522 char *attribute
, *class;
2527 /* Allocate space for the components, the dots which separate them,
2528 and the final '\0'. */
2529 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2530 + strlen (attribute
) + 2);
2531 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2532 + strlen (class) + 2);
2534 sprintf (name_key
, "%s.%s",
2535 XSTRING (Vinvocation_name
)->data
,
2537 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2539 return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame
)->xrdb
,
2540 name_key
, class_key
);
2543 /* Types we might convert a resource string into. */
2552 /* Return the value of parameter PARAM.
2554 First search ALIST, then Vdefault_frame_alist, then the X defaults
2555 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2557 Convert the resource to the type specified by desired_type.
2559 If no default is specified, return Qunbound. If you call
2560 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2561 and don't let it get stored in any Lisp-visible variables! */
2564 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2565 struct x_display_info
*dpyinfo
;
2566 Lisp_Object alist
, param
;
2569 enum resource_types type
;
2571 register Lisp_Object tem
;
2573 tem
= Fassq (param
, alist
);
2575 tem
= Fassq (param
, Vdefault_frame_alist
);
2581 tem
= display_x_get_resource (dpyinfo
,
2582 build_string (attribute
),
2583 build_string (class),
2591 case RES_TYPE_NUMBER
:
2592 return make_number (atoi (XSTRING (tem
)->data
));
2594 case RES_TYPE_BOOLEAN
:
2595 tem
= Fdowncase (tem
);
2596 if (!strcmp (XSTRING (tem
)->data
, "on")
2597 || !strcmp (XSTRING (tem
)->data
, "true"))
2602 case RES_TYPE_STRING
:
2605 case RES_TYPE_SYMBOL
:
2606 /* As a special case, we map the values `true' and `on'
2607 to Qt, and `false' and `off' to Qnil. */
2610 lower
= Fdowncase (tem
);
2611 if (!strcmp (XSTRING (lower
)->data
, "on")
2612 || !strcmp (XSTRING (lower
)->data
, "true"))
2614 else if (!strcmp (XSTRING (lower
)->data
, "off")
2615 || !strcmp (XSTRING (lower
)->data
, "false"))
2618 return Fintern (tem
, Qnil
);
2631 /* Like x_get_arg, but also record the value in f->param_alist. */
2634 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2636 Lisp_Object alist
, param
;
2639 enum resource_types type
;
2643 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2644 attribute
, class, type
);
2646 store_frame_param (f
, param
, value
);
2651 /* Record in frame F the specified or default value according to ALIST
2652 of the parameter named PROP (a Lisp symbol).
2653 If no value is specified for PROP, look for an X default for XPROP
2654 on the frame named NAME.
2655 If that is not found either, use the value DEFLT. */
2658 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2665 enum resource_types type
;
2669 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2670 if (EQ (tem
, Qunbound
))
2672 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2677 /* Record in frame F the specified or default value according to ALIST
2678 of the parameter named PROP (a Lisp symbol). If no value is
2679 specified for PROP, look for an X default for XPROP on the frame
2680 named NAME. If that is not found either, use the value DEFLT. */
2683 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2692 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2695 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2696 if (EQ (tem
, Qunbound
))
2698 #ifdef USE_TOOLKIT_SCROLL_BARS
2700 /* See if an X resource for the scroll bar color has been
2702 tem
= display_x_get_resource (dpyinfo
,
2703 build_string (foreground_p
2707 build_string ("verticalScrollBar"),
2711 /* If nothing has been specified, scroll bars will use a
2712 toolkit-dependent default. Because these defaults are
2713 difficult to get at without actually creating a scroll
2714 bar, use nil to indicate that no color has been
2719 #else /* not USE_TOOLKIT_SCROLL_BARS */
2723 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2726 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2732 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2733 "Parse an X-style geometry string STRING.\n\
2734 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2735 The properties returned may include `top', `left', `height', and `width'.\n\
2736 The value of `left' or `top' may be an integer,\n\
2737 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2738 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2743 unsigned int width
, height
;
2746 CHECK_STRING (string
, 0);
2748 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2749 &x
, &y
, &width
, &height
);
2752 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2753 error ("Must specify both x and y position, or neither");
2757 if (geometry
& XValue
)
2759 Lisp_Object element
;
2761 if (x
>= 0 && (geometry
& XNegative
))
2762 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2763 else if (x
< 0 && ! (geometry
& XNegative
))
2764 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2766 element
= Fcons (Qleft
, make_number (x
));
2767 result
= Fcons (element
, result
);
2770 if (geometry
& YValue
)
2772 Lisp_Object element
;
2774 if (y
>= 0 && (geometry
& YNegative
))
2775 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2776 else if (y
< 0 && ! (geometry
& YNegative
))
2777 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2779 element
= Fcons (Qtop
, make_number (y
));
2780 result
= Fcons (element
, result
);
2783 if (geometry
& WidthValue
)
2784 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2785 if (geometry
& HeightValue
)
2786 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2791 /* Calculate the desired size and position of this window,
2792 and return the flags saying which aspects were specified.
2794 This function does not make the coordinates positive. */
2796 #define DEFAULT_ROWS 40
2797 #define DEFAULT_COLS 80
2800 x_figure_window_size (f
, parms
)
2804 register Lisp_Object tem0
, tem1
, tem2
;
2805 int height
, width
, left
, top
;
2806 register int geometry
;
2807 long window_prompting
= 0;
2808 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2810 /* Default values if we fall through.
2811 Actually, if that happens we should get
2812 window manager prompting. */
2813 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2814 f
->height
= DEFAULT_ROWS
;
2815 /* Window managers expect that if program-specified
2816 positions are not (0,0), they're intentional, not defaults. */
2817 f
->output_data
.x
->top_pos
= 0;
2818 f
->output_data
.x
->left_pos
= 0;
2820 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
2821 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
2822 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
2823 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2825 if (!EQ (tem0
, Qunbound
))
2827 CHECK_NUMBER (tem0
, 0);
2828 f
->height
= XINT (tem0
);
2830 if (!EQ (tem1
, Qunbound
))
2832 CHECK_NUMBER (tem1
, 0);
2833 SET_FRAME_WIDTH (f
, XINT (tem1
));
2835 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2836 window_prompting
|= USSize
;
2838 window_prompting
|= PSize
;
2841 f
->output_data
.x
->vertical_scroll_bar_extra
2842 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2844 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2845 f
->output_data
.x
->flags_areas_extra
2846 = 2 * FRAME_FLAGS_AREA_WIDTH (f
);
2847 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2848 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2850 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
2851 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
2852 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
2853 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2855 if (EQ (tem0
, Qminus
))
2857 f
->output_data
.x
->top_pos
= 0;
2858 window_prompting
|= YNegative
;
2860 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2861 && CONSP (XCONS (tem0
)->cdr
)
2862 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2864 f
->output_data
.x
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2865 window_prompting
|= YNegative
;
2867 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2868 && CONSP (XCONS (tem0
)->cdr
)
2869 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2871 f
->output_data
.x
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2873 else if (EQ (tem0
, Qunbound
))
2874 f
->output_data
.x
->top_pos
= 0;
2877 CHECK_NUMBER (tem0
, 0);
2878 f
->output_data
.x
->top_pos
= XINT (tem0
);
2879 if (f
->output_data
.x
->top_pos
< 0)
2880 window_prompting
|= YNegative
;
2883 if (EQ (tem1
, Qminus
))
2885 f
->output_data
.x
->left_pos
= 0;
2886 window_prompting
|= XNegative
;
2888 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2889 && CONSP (XCONS (tem1
)->cdr
)
2890 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2892 f
->output_data
.x
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2893 window_prompting
|= XNegative
;
2895 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2896 && CONSP (XCONS (tem1
)->cdr
)
2897 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2899 f
->output_data
.x
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2901 else if (EQ (tem1
, Qunbound
))
2902 f
->output_data
.x
->left_pos
= 0;
2905 CHECK_NUMBER (tem1
, 0);
2906 f
->output_data
.x
->left_pos
= XINT (tem1
);
2907 if (f
->output_data
.x
->left_pos
< 0)
2908 window_prompting
|= XNegative
;
2911 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2912 window_prompting
|= USPosition
;
2914 window_prompting
|= PPosition
;
2917 return window_prompting
;
2920 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2923 XSetWMProtocols (dpy
, w
, protocols
, count
)
2930 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
2931 if (prop
== None
) return False
;
2932 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
2933 (unsigned char *) protocols
, count
);
2936 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2938 #ifdef USE_X_TOOLKIT
2940 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2941 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2942 already be present because of the toolkit (Motif adds some of them,
2943 for example, but Xt doesn't). */
2946 hack_wm_protocols (f
, widget
)
2950 Display
*dpy
= XtDisplay (widget
);
2951 Window w
= XtWindow (widget
);
2952 int need_delete
= 1;
2958 Atom type
, *atoms
= 0;
2960 unsigned long nitems
= 0;
2961 unsigned long bytes_after
;
2963 if ((XGetWindowProperty (dpy
, w
,
2964 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2965 (long)0, (long)100, False
, XA_ATOM
,
2966 &type
, &format
, &nitems
, &bytes_after
,
2967 (unsigned char **) &atoms
)
2969 && format
== 32 && type
== XA_ATOM
)
2973 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
2975 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
2977 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
2980 if (atoms
) XFree ((char *) atoms
);
2986 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
2988 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
2990 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
2992 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
2993 XA_ATOM
, 32, PropModeAppend
,
2994 (unsigned char *) props
, count
);
3000 #ifdef USE_X_TOOLKIT
3002 /* Create and set up the X widget for frame F. */
3005 x_window (f
, window_prompting
, minibuffer_only
)
3007 long window_prompting
;
3008 int minibuffer_only
;
3010 XClassHint class_hints
;
3011 XSetWindowAttributes attributes
;
3012 unsigned long attribute_mask
;
3014 Widget shell_widget
;
3016 Widget frame_widget
;
3022 /* Use the resource name as the top-level widget name
3023 for looking up resources. Make a non-Lisp copy
3024 for the window manager, so GC relocation won't bother it.
3026 Elsewhere we specify the window name for the window manager. */
3029 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3030 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3031 strcpy (f
->namebuf
, str
);
3035 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3036 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3037 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3038 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3039 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3040 applicationShellWidgetClass
,
3041 FRAME_X_DISPLAY (f
), al
, ac
);
3043 f
->output_data
.x
->widget
= shell_widget
;
3044 /* maybe_set_screen_title_format (shell_widget); */
3046 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3047 (widget_value
*) NULL
,
3048 shell_widget
, False
,
3051 (lw_callback
) NULL
);
3053 f
->output_data
.x
->column_widget
= pane_widget
;
3055 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3056 the emacs screen when changing menubar. This reduces flickering. */
3059 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3060 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3061 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3062 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3063 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3064 frame_widget
= XtCreateWidget (f
->namebuf
,
3066 pane_widget
, al
, ac
);
3068 f
->output_data
.x
->edit_widget
= frame_widget
;
3070 XtManageChild (frame_widget
);
3072 /* Do some needed geometry management. */
3075 char *tem
, shell_position
[32];
3078 int extra_borders
= 0;
3080 = (f
->output_data
.x
->menubar_widget
3081 ? (f
->output_data
.x
->menubar_widget
->core
.height
3082 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3084 extern char *lwlib_toolkit_type
;
3086 #if 0 /* Experimentally, we now get the right results
3087 for -geometry -0-0 without this. 24 Aug 96, rms. */
3088 if (FRAME_EXTERNAL_MENU_BAR (f
))
3091 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3092 menubar_size
+= ibw
;
3096 f
->output_data
.x
->menubar_height
= menubar_size
;
3099 /* Motif seems to need this amount added to the sizes
3100 specified for the shell widget. The Athena/Lucid widgets don't.
3101 Both conclusions reached experimentally. -- rms. */
3102 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3103 &extra_borders
, NULL
);
3107 /* Convert our geometry parameters into a geometry string
3109 Note that we do not specify here whether the position
3110 is a user-specified or program-specified one.
3111 We pass that information later, in x_wm_set_size_hints. */
3113 int left
= f
->output_data
.x
->left_pos
;
3114 int xneg
= window_prompting
& XNegative
;
3115 int top
= f
->output_data
.x
->top_pos
;
3116 int yneg
= window_prompting
& YNegative
;
3122 if (window_prompting
& USPosition
)
3123 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3124 PIXEL_WIDTH (f
) + extra_borders
,
3125 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3126 (xneg
? '-' : '+'), left
,
3127 (yneg
? '-' : '+'), top
);
3129 sprintf (shell_position
, "=%dx%d",
3130 PIXEL_WIDTH (f
) + extra_borders
,
3131 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3134 len
= strlen (shell_position
) + 1;
3135 /* We don't free this because we don't know whether
3136 it is safe to free it while the frame exists.
3137 It isn't worth the trouble of arranging to free it
3138 when the frame is deleted. */
3139 tem
= (char *) xmalloc (len
);
3140 strncpy (tem
, shell_position
, len
);
3141 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3142 XtSetValues (shell_widget
, al
, ac
);
3145 XtManageChild (pane_widget
);
3146 XtRealizeWidget (shell_widget
);
3148 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3150 validate_x_resource_name ();
3152 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3153 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3154 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3157 #ifndef X_I18N_INHIBITED
3162 xim
= XOpenIM (FRAME_X_DISPLAY (f
), NULL
, NULL
, NULL
);
3166 xic
= XCreateIC (xim
,
3167 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
3168 XNClientWindow
, FRAME_X_WINDOW(f
),
3169 XNFocusWindow
, FRAME_X_WINDOW(f
),
3178 FRAME_XIM (f
) = xim
;
3179 FRAME_XIC (f
) = xic
;
3181 #else /* X_I18N_INHIBITED */
3184 #endif /* X_I18N_INHIBITED */
3185 #endif /* HAVE_X_I18N */
3187 f
->output_data
.x
->wm_hints
.input
= True
;
3188 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3189 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3190 &f
->output_data
.x
->wm_hints
);
3192 hack_wm_protocols (f
, shell_widget
);
3195 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3198 /* Do a stupid property change to force the server to generate a
3199 PropertyNotify event so that the event_stream server timestamp will
3200 be initialized to something relevant to the time we created the window.
3202 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3203 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3204 XA_ATOM
, 32, PropModeAppend
,
3205 (unsigned char*) NULL
, 0);
3207 /* Make all the standard events reach the Emacs frame. */
3208 attributes
.event_mask
= STANDARD_EVENT_SET
;
3209 attribute_mask
= CWEventMask
;
3210 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3211 attribute_mask
, &attributes
);
3213 XtMapWidget (frame_widget
);
3215 /* x_set_name normally ignores requests to set the name if the
3216 requested name is the same as the current name. This is the one
3217 place where that assumption isn't correct; f->name is set, but
3218 the X server hasn't been told. */
3221 int explicit = f
->explicit_name
;
3223 f
->explicit_name
= 0;
3226 x_set_name (f
, name
, explicit);
3229 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3230 f
->output_data
.x
->text_cursor
);
3234 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
3235 initialize_frame_menubar (f
);
3236 lw_set_main_areas (pane_widget
, f
->output_data
.x
->menubar_widget
, frame_widget
);
3238 if (FRAME_X_WINDOW (f
) == 0)
3239 error ("Unable to create window");
3242 #else /* not USE_X_TOOLKIT */
3244 /* Create and set up the X window for frame F. */
3251 XClassHint class_hints
;
3252 XSetWindowAttributes attributes
;
3253 unsigned long attribute_mask
;
3255 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3256 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3257 attributes
.bit_gravity
= StaticGravity
;
3258 attributes
.backing_store
= NotUseful
;
3259 attributes
.save_under
= True
;
3260 attributes
.event_mask
= STANDARD_EVENT_SET
;
3261 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
3263 | CWBackingStore
| CWSaveUnder
3269 = XCreateWindow (FRAME_X_DISPLAY (f
),
3270 f
->output_data
.x
->parent_desc
,
3271 f
->output_data
.x
->left_pos
,
3272 f
->output_data
.x
->top_pos
,
3273 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3274 f
->output_data
.x
->border_width
,
3275 CopyFromParent
, /* depth */
3276 InputOutput
, /* class */
3277 FRAME_X_DISPLAY_INFO (f
)->visual
,
3278 attribute_mask
, &attributes
);
3280 #ifndef X_I18N_INHIBITED
3285 xim
= XOpenIM (FRAME_X_DISPLAY(f
), NULL
, NULL
, NULL
);
3289 xic
= XCreateIC (xim
,
3290 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
3291 XNClientWindow
, FRAME_X_WINDOW(f
),
3292 XNFocusWindow
, FRAME_X_WINDOW(f
),
3302 FRAME_XIM (f
) = xim
;
3303 FRAME_XIC (f
) = xic
;
3305 #else /* X_I18N_INHIBITED */
3308 #endif /* X_I18N_INHIBITED */
3309 #endif /* HAVE_X_I18N */
3311 validate_x_resource_name ();
3313 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3314 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3315 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3317 /* The menubar is part of the ordinary display;
3318 it does not count in addition to the height of the window. */
3319 f
->output_data
.x
->menubar_height
= 0;
3321 /* This indicates that we use the "Passive Input" input model.
3322 Unless we do this, we don't get the Focus{In,Out} events that we
3323 need to draw the cursor correctly. Accursed bureaucrats.
3324 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3326 f
->output_data
.x
->wm_hints
.input
= True
;
3327 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3328 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3329 &f
->output_data
.x
->wm_hints
);
3330 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3332 /* Request "save yourself" and "delete window" commands from wm. */
3335 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3336 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3337 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3340 /* x_set_name normally ignores requests to set the name if the
3341 requested name is the same as the current name. This is the one
3342 place where that assumption isn't correct; f->name is set, but
3343 the X server hasn't been told. */
3346 int explicit = f
->explicit_name
;
3348 f
->explicit_name
= 0;
3351 x_set_name (f
, name
, explicit);
3354 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3355 f
->output_data
.x
->text_cursor
);
3359 if (FRAME_X_WINDOW (f
) == 0)
3360 error ("Unable to create window");
3363 #endif /* not USE_X_TOOLKIT */
3365 /* Handle the icon stuff for this window. Perhaps later we might
3366 want an x_set_icon_position which can be called interactively as
3374 Lisp_Object icon_x
, icon_y
;
3375 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3377 /* Set the position of the icon. Note that twm groups all
3378 icons in an icon window. */
3379 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3380 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3381 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3383 CHECK_NUMBER (icon_x
, 0);
3384 CHECK_NUMBER (icon_y
, 0);
3386 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3387 error ("Both left and top icon corners of icon must be specified");
3391 if (! EQ (icon_x
, Qunbound
))
3392 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3394 /* Start up iconic or window? */
3395 x_wm_set_window_state
3396 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3401 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3408 /* Make the GC's needed for this window, setting the
3409 background, border and mouse colors; also create the
3410 mouse cursor and the gray border tile. */
3412 static char cursor_bits
[] =
3414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3424 XGCValues gc_values
;
3428 /* Create the GC's of this frame.
3429 Note that many default values are used. */
3432 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3433 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3434 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3435 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3436 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3438 GCLineWidth
| GCFont
3439 | GCForeground
| GCBackground
,
3442 /* Reverse video style. */
3443 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3444 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3445 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3447 GCFont
| GCForeground
| GCBackground
3451 /* Cursor has cursor-color background, background-color foreground. */
3452 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3453 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3454 gc_values
.fill_style
= FillOpaqueStippled
;
3456 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3457 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3458 cursor_bits
, 16, 16);
3459 f
->output_data
.x
->cursor_gc
3460 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3461 (GCFont
| GCForeground
| GCBackground
3462 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3466 f
->output_data
.x
->white_relief
.gc
= 0;
3467 f
->output_data
.x
->black_relief
.gc
= 0;
3469 /* Create the gray border tile used when the pointer is not in
3470 the frame. Since this depends on the frame's pixel values,
3471 this must be done on a per-frame basis. */
3472 f
->output_data
.x
->border_tile
3473 = (XCreatePixmapFromBitmapData
3474 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3475 gray_bits
, gray_width
, gray_height
,
3476 f
->output_data
.x
->foreground_pixel
,
3477 f
->output_data
.x
->background_pixel
,
3478 DefaultDepth (FRAME_X_DISPLAY (f
),
3479 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3484 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3486 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3487 Returns an Emacs frame object.\n\
3488 ALIST is an alist of frame parameters.\n\
3489 If the parameters specify that the frame should not have a minibuffer,\n\
3490 and do not specify a specific minibuffer window to use,\n\
3491 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3492 be shared by the new frame.\n\
3494 This function is an internal primitive--use `make-frame' instead.")
3499 Lisp_Object frame
, tem
;
3501 int minibuffer_only
= 0;
3502 long window_prompting
= 0;
3504 int count
= specpdl_ptr
- specpdl
;
3505 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3506 Lisp_Object display
;
3507 struct x_display_info
*dpyinfo
= NULL
;
3513 /* Use this general default value to start with
3514 until we know if this frame has a specified name. */
3515 Vx_resource_name
= Vinvocation_name
;
3517 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3518 if (EQ (display
, Qunbound
))
3520 dpyinfo
= check_x_display_info (display
);
3522 kb
= dpyinfo
->kboard
;
3524 kb
= &the_only_kboard
;
3527 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3529 && ! EQ (name
, Qunbound
)
3531 error ("Invalid frame name--not a string or nil");
3534 Vx_resource_name
= name
;
3536 /* See if parent window is specified. */
3537 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
3538 if (EQ (parent
, Qunbound
))
3540 if (! NILP (parent
))
3541 CHECK_NUMBER (parent
, 0);
3543 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3544 /* No need to protect DISPLAY because that's not used after passing
3545 it to make_frame_without_minibuffer. */
3547 GCPRO4 (parms
, parent
, name
, frame
);
3548 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
3550 if (EQ (tem
, Qnone
) || NILP (tem
))
3551 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3552 else if (EQ (tem
, Qonly
))
3554 f
= make_minibuffer_frame ();
3555 minibuffer_only
= 1;
3557 else if (WINDOWP (tem
))
3558 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3562 XSETFRAME (frame
, f
);
3564 /* Note that X Windows does support scroll bars. */
3565 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3567 f
->output_method
= output_x_window
;
3568 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
3569 bzero (f
->output_data
.x
, sizeof (struct x_output
));
3570 f
->output_data
.x
->icon_bitmap
= -1;
3571 f
->output_data
.x
->fontset
= -1;
3572 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
3573 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
3576 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
3578 if (! STRINGP (f
->icon_name
))
3579 f
->icon_name
= Qnil
;
3581 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
3583 FRAME_KBOARD (f
) = kb
;
3586 /* Specify the parent under which to make this X window. */
3590 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
3591 f
->output_data
.x
->explicit_parent
= 1;
3595 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3596 f
->output_data
.x
->explicit_parent
= 0;
3599 /* Set the name; the functions to which we pass f expect the name to
3601 if (EQ (name
, Qunbound
) || NILP (name
))
3603 f
->name
= build_string (dpyinfo
->x_id_name
);
3604 f
->explicit_name
= 0;
3609 f
->explicit_name
= 1;
3610 /* use the frame's title when getting resources for this frame. */
3611 specbind (Qx_resource_name
, name
);
3614 /* Create fontsets from `global_fontset_alist' before handling fonts. */
3615 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
3616 fs_register_fontset (f
, XCONS (tem
)->car
);
3618 /* Extract the window parameters from the supplied values
3619 that are needed to determine window geometry. */
3623 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
3626 /* First, try whatever font the caller has specified. */
3629 tem
= Fquery_fontset (font
, Qnil
);
3631 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
3633 font
= x_new_font (f
, XSTRING (font
)->data
);
3636 /* Try out a font which we hope has bold and italic variations. */
3637 if (!STRINGP (font
))
3638 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3639 if (!STRINGP (font
))
3640 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3641 if (! STRINGP (font
))
3642 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3643 if (! STRINGP (font
))
3644 /* This was formerly the first thing tried, but it finds too many fonts
3645 and takes too long. */
3646 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3647 /* If those didn't work, look for something which will at least work. */
3648 if (! STRINGP (font
))
3649 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3651 if (! STRINGP (font
))
3652 font
= build_string ("fixed");
3654 x_default_parameter (f
, parms
, Qfont
, font
,
3655 "font", "Font", RES_TYPE_STRING
);
3659 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3660 whereby it fails to get any font. */
3661 xlwmenu_default_font
= f
->output_data
.x
->font
;
3664 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
3665 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
3667 /* This defaults to 2 in order to match xterm. We recognize either
3668 internalBorderWidth or internalBorder (which is what xterm calls
3670 if (NILP (Fassq (Qinternal_border_width
, parms
)))
3674 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
3675 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
3676 if (! EQ (value
, Qunbound
))
3677 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
3680 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
3681 "internalBorderWidth", "internalBorderWidth",
3683 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
3684 "verticalScrollBars", "ScrollBars",
3687 /* Also do the stuff which must be set before the window exists. */
3688 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
3689 "foreground", "Foreground", RES_TYPE_STRING
);
3690 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
3691 "background", "Background", RES_TYPE_STRING
);
3692 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
3693 "pointerColor", "Foreground", RES_TYPE_STRING
);
3694 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
3695 "cursorColor", "Foreground", RES_TYPE_STRING
);
3696 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
3697 "borderColor", "BorderColor", RES_TYPE_STRING
);
3699 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
3700 "scrollBarForeground",
3701 "ScrollBarForeground", 1);
3702 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
3703 "scrollBarBackground",
3704 "ScrollBarBackground", 0);
3706 /* Init faces before x_default_parameter is called for scroll-bar
3707 parameters because that function calls x_set_scroll_bar_width,
3708 which calls change_frame_size, which calls Fset_window_buffer,
3709 which runs hooks, which call Fvertical_motion. At the end, we
3710 end up in init_iterator with a null face cache, which should not
3712 init_frame_faces (f
);
3714 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
3715 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
3716 x_default_parameter (f
, parms
, Qtoolbar_lines
, make_number (0),
3717 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
3718 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
3719 "scrollBarWidth", "ScrollBarWidth",
3721 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
3722 "bufferPredicate", "BufferPredicate",
3724 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
3725 "title", "Title", RES_TYPE_STRING
);
3727 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3728 window_prompting
= x_figure_window_size (f
, parms
);
3730 if (window_prompting
& XNegative
)
3732 if (window_prompting
& YNegative
)
3733 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
3735 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
3739 if (window_prompting
& YNegative
)
3740 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
3742 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
3745 f
->output_data
.x
->size_hint_flags
= window_prompting
;
3747 /* Create the X widget or window. Add the toolbar height to the
3748 initial frame height so that the user gets a text display area of
3749 the size he specified with -g or via .Xdefaults. Later changes
3750 of the toolbar height don't change the frame size. This is done
3751 so that users can create tall Emacs frames without having to
3752 guess how tall the toolbar will get. */
3753 f
->height
+= FRAME_TOOLBAR_LINES (f
);
3754 #ifdef USE_X_TOOLKIT
3755 x_window (f
, window_prompting
, minibuffer_only
);
3762 call1 (Qface_set_after_frame_default
, frame
);
3764 /* We need to do this after creating the X window, so that the
3765 icon-creation functions can say whose icon they're describing. */
3766 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
3767 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
3769 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
3770 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
3771 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
3772 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
3773 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
3774 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
3776 /* Dimensions, especially f->height, must be done via change_frame_size.
3777 Change will not be effected unless different from the current
3782 SET_FRAME_WIDTH (f
, 0);
3783 change_frame_size (f
, height
, width
, 1, 0);
3785 /* Tell the server what size and position, etc, we want,
3786 and how badly we want them. */
3788 x_wm_set_size_hint (f
, window_prompting
, 0);
3791 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
3792 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
3796 /* It is now ok to make the frame official
3797 even if we get an error below.
3798 And the frame needs to be on Vframe_list
3799 or making it visible won't work. */
3800 Vframe_list
= Fcons (frame
, Vframe_list
);
3802 /* Now that the frame is official, it counts as a reference to
3804 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
3806 /* Make the window appear on the frame and enable display,
3807 unless the caller says not to. However, with explicit parent,
3808 Emacs cannot control visibility, so don't try. */
3809 if (! f
->output_data
.x
->explicit_parent
)
3811 Lisp_Object visibility
;
3813 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
3815 if (EQ (visibility
, Qunbound
))
3818 if (EQ (visibility
, Qicon
))
3819 x_iconify_frame (f
);
3820 else if (! NILP (visibility
))
3821 x_make_frame_visible (f
);
3823 /* Must have been Qnil. */
3827 return unbind_to (count
, frame
);
3830 /* FRAME is used only to get a handle on the X display. We don't pass the
3831 display info directly because we're called from frame.c, which doesn't
3832 know about that structure. */
3835 x_get_focus_frame (frame
)
3836 struct frame
*frame
;
3838 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
3840 if (! dpyinfo
->x_focus_frame
)
3843 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
3848 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
3849 "Return non-nil if color COLOR is supported on frame FRAME.\n\
3850 If FRAME is omitted or nil, use the selected frame.")
3852 Lisp_Object color
, frame
;
3855 FRAME_PTR f
= check_x_frame (frame
);
3857 CHECK_STRING (color
, 1);
3859 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3865 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
3866 "Return a description of the color named COLOR on frame FRAME.\n\
3867 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
3868 These values appear to range from 0 to 65280 or 65535, depending\n\
3869 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
3870 If FRAME is omitted or nil, use the selected frame.")
3872 Lisp_Object color
, frame
;
3875 FRAME_PTR f
= check_x_frame (frame
);
3877 CHECK_STRING (color
, 1);
3879 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
3883 rgb
[0] = make_number (foo
.red
);
3884 rgb
[1] = make_number (foo
.green
);
3885 rgb
[2] = make_number (foo
.blue
);
3886 return Flist (3, rgb
);
3892 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
3893 "Return t if the X display supports color.\n\
3894 The optional argument DISPLAY specifies which display to ask about.\n\
3895 DISPLAY should be either a frame or a display name (a string).\n\
3896 If omitted or nil, that stands for the selected frame's display.")
3898 Lisp_Object display
;
3900 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3902 if (dpyinfo
->n_planes
<= 2)
3905 switch (dpyinfo
->visual
->class)
3918 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
3920 "Return t if the X display supports shades of gray.\n\
3921 Note that color displays do support shades of gray.\n\
3922 The optional argument DISPLAY specifies which display to ask about.\n\
3923 DISPLAY should be either a frame or a display name (a string).\n\
3924 If omitted or nil, that stands for the selected frame's display.")
3926 Lisp_Object display
;
3928 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3930 if (dpyinfo
->n_planes
<= 1)
3933 switch (dpyinfo
->visual
->class)
3948 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
3950 "Returns the width in pixels of the X display DISPLAY.\n\
3951 The optional argument DISPLAY specifies which display to ask about.\n\
3952 DISPLAY should be either a frame or a display name (a string).\n\
3953 If omitted or nil, that stands for the selected frame's display.")
3955 Lisp_Object display
;
3957 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3959 return make_number (dpyinfo
->width
);
3962 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
3963 Sx_display_pixel_height
, 0, 1, 0,
3964 "Returns the height in pixels of the X display DISPLAY.\n\
3965 The optional argument DISPLAY specifies which display to ask about.\n\
3966 DISPLAY should be either a frame or a display name (a string).\n\
3967 If omitted or nil, that stands for the selected frame's display.")
3969 Lisp_Object display
;
3971 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3973 return make_number (dpyinfo
->height
);
3976 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
3978 "Returns the number of bitplanes of the X display DISPLAY.\n\
3979 The optional argument DISPLAY specifies which display to ask about.\n\
3980 DISPLAY should be either a frame or a display name (a string).\n\
3981 If omitted or nil, that stands for the selected frame's display.")
3983 Lisp_Object display
;
3985 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
3987 return make_number (dpyinfo
->n_planes
);
3990 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
3992 "Returns the number of color cells of the X display DISPLAY.\n\
3993 The optional argument DISPLAY specifies which display to ask about.\n\
3994 DISPLAY should be either a frame or a display name (a string).\n\
3995 If omitted or nil, that stands for the selected frame's display.")
3997 Lisp_Object display
;
3999 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4001 return make_number (DisplayCells (dpyinfo
->display
,
4002 XScreenNumberOfScreen (dpyinfo
->screen
)));
4005 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4006 Sx_server_max_request_size
,
4008 "Returns the maximum request size of the X server of display DISPLAY.\n\
4009 The optional argument DISPLAY specifies which display to ask about.\n\
4010 DISPLAY should be either a frame or a display name (a string).\n\
4011 If omitted or nil, that stands for the selected frame's display.")
4013 Lisp_Object display
;
4015 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4017 return make_number (MAXREQUEST (dpyinfo
->display
));
4020 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4021 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4022 The optional argument DISPLAY specifies which display to ask about.\n\
4023 DISPLAY should be either a frame or a display name (a string).\n\
4024 If omitted or nil, that stands for the selected frame's display.")
4026 Lisp_Object display
;
4028 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4029 char *vendor
= ServerVendor (dpyinfo
->display
);
4031 if (! vendor
) vendor
= "";
4032 return build_string (vendor
);
4035 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4036 "Returns the version numbers of the X server of display DISPLAY.\n\
4037 The value is a list of three integers: the major and minor\n\
4038 version numbers of the X Protocol in use, and the vendor-specific release\n\
4039 number. See also the function `x-server-vendor'.\n\n\
4040 The optional argument DISPLAY specifies which display to ask about.\n\
4041 DISPLAY should be either a frame or a display name (a string).\n\
4042 If omitted or nil, that stands for the selected frame's display.")
4044 Lisp_Object display
;
4046 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4047 Display
*dpy
= dpyinfo
->display
;
4049 return Fcons (make_number (ProtocolVersion (dpy
)),
4050 Fcons (make_number (ProtocolRevision (dpy
)),
4051 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4054 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4055 "Returns the number of screens on the X server of display DISPLAY.\n\
4056 The optional argument DISPLAY specifies which display to ask about.\n\
4057 DISPLAY should be either a frame or a display name (a string).\n\
4058 If omitted or nil, that stands for the selected frame's display.")
4060 Lisp_Object display
;
4062 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4064 return make_number (ScreenCount (dpyinfo
->display
));
4067 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4068 "Returns the height in millimeters of the X display DISPLAY.\n\
4069 The optional argument DISPLAY specifies which display to ask about.\n\
4070 DISPLAY should be either a frame or a display name (a string).\n\
4071 If omitted or nil, that stands for the selected frame's display.")
4073 Lisp_Object display
;
4075 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4077 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4080 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4081 "Returns the width in millimeters of the X display DISPLAY.\n\
4082 The optional argument DISPLAY specifies which display to ask about.\n\
4083 DISPLAY should be either a frame or a display name (a string).\n\
4084 If omitted or nil, that stands for the selected frame's display.")
4086 Lisp_Object display
;
4088 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4090 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4093 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4094 Sx_display_backing_store
, 0, 1, 0,
4095 "Returns an indication of whether X display DISPLAY does backing store.\n\
4096 The value may be `always', `when-mapped', or `not-useful'.\n\
4097 The optional argument DISPLAY specifies which display to ask about.\n\
4098 DISPLAY should be either a frame or a display name (a string).\n\
4099 If omitted or nil, that stands for the selected frame's display.")
4101 Lisp_Object display
;
4103 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4105 switch (DoesBackingStore (dpyinfo
->screen
))
4108 return intern ("always");
4111 return intern ("when-mapped");
4114 return intern ("not-useful");
4117 error ("Strange value for BackingStore parameter of screen");
4121 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4122 Sx_display_visual_class
, 0, 1, 0,
4123 "Returns the visual class of the X display DISPLAY.\n\
4124 The value is one of the symbols `static-gray', `gray-scale',\n\
4125 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4126 The optional argument DISPLAY specifies which display to ask about.\n\
4127 DISPLAY should be either a frame or a display name (a string).\n\
4128 If omitted or nil, that stands for the selected frame's display.")
4130 Lisp_Object display
;
4132 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4134 switch (dpyinfo
->visual
->class)
4136 case StaticGray
: return (intern ("static-gray"));
4137 case GrayScale
: return (intern ("gray-scale"));
4138 case StaticColor
: return (intern ("static-color"));
4139 case PseudoColor
: return (intern ("pseudo-color"));
4140 case TrueColor
: return (intern ("true-color"));
4141 case DirectColor
: return (intern ("direct-color"));
4143 error ("Display has an unknown visual class");
4147 DEFUN ("x-display-save-under", Fx_display_save_under
,
4148 Sx_display_save_under
, 0, 1, 0,
4149 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4150 The optional argument DISPLAY specifies which display to ask about.\n\
4151 DISPLAY should be either a frame or a display name (a string).\n\
4152 If omitted or nil, that stands for the selected frame's display.")
4154 Lisp_Object display
;
4156 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4158 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4166 register struct frame
*f
;
4168 return PIXEL_WIDTH (f
);
4173 register struct frame
*f
;
4175 return PIXEL_HEIGHT (f
);
4180 register struct frame
*f
;
4182 return FONT_WIDTH (f
->output_data
.x
->font
);
4187 register struct frame
*f
;
4189 return f
->output_data
.x
->line_height
;
4194 register struct frame
*f
;
4196 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4199 #if 0 /* These no longer seem like the right way to do things. */
4201 /* Draw a rectangle on the frame with left top corner including
4202 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
4203 CHARS by LINES wide and long and is the color of the cursor. */
4206 x_rectangle (f
, gc
, left_char
, top_char
, chars
, lines
)
4207 register struct frame
*f
;
4209 register int top_char
, left_char
, chars
, lines
;
4213 int left
= (left_char
* FONT_WIDTH (f
->output_data
.x
->font
)
4214 + f
->output_data
.x
->internal_border_width
);
4215 int top
= (top_char
* f
->output_data
.x
->line_height
4216 + f
->output_data
.x
->internal_border_width
);
4219 width
= FONT_WIDTH (f
->output_data
.x
->font
) / 2;
4221 width
= FONT_WIDTH (f
->output_data
.x
->font
) * chars
;
4223 height
= f
->output_data
.x
->line_height
/ 2;
4225 height
= f
->output_data
.x
->line_height
* lines
;
4227 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4228 gc
, left
, top
, width
, height
);
4231 DEFUN ("x-draw-rectangle", Fx_draw_rectangle
, Sx_draw_rectangle
, 5, 5, 0,
4232 "Draw a rectangle on FRAME between coordinates specified by\n\
4233 numbers X0, Y0, X1, Y1 in the cursor pixel.")
4234 (frame
, X0
, Y0
, X1
, Y1
)
4235 register Lisp_Object frame
, X0
, X1
, Y0
, Y1
;
4237 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4239 CHECK_LIVE_FRAME (frame
, 0);
4240 CHECK_NUMBER (X0
, 0);
4241 CHECK_NUMBER (Y0
, 1);
4242 CHECK_NUMBER (X1
, 2);
4243 CHECK_NUMBER (Y1
, 3);
4253 n_lines
= y1
- y0
+ 1;
4258 n_lines
= y0
- y1
+ 1;
4264 n_chars
= x1
- x0
+ 1;
4269 n_chars
= x0
- x1
+ 1;
4273 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->cursor_gc
,
4274 left
, top
, n_chars
, n_lines
);
4280 DEFUN ("x-erase-rectangle", Fx_erase_rectangle
, Sx_erase_rectangle
, 5, 5, 0,
4281 "Draw a rectangle drawn on FRAME between coordinates\n\
4282 X0, Y0, X1, Y1 in the regular background-pixel.")
4283 (frame
, X0
, Y0
, X1
, Y1
)
4284 register Lisp_Object frame
, X0
, Y0
, X1
, Y1
;
4286 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4288 CHECK_LIVE_FRAME (frame
, 0);
4289 CHECK_NUMBER (X0
, 0);
4290 CHECK_NUMBER (Y0
, 1);
4291 CHECK_NUMBER (X1
, 2);
4292 CHECK_NUMBER (Y1
, 3);
4302 n_lines
= y1
- y0
+ 1;
4307 n_lines
= y0
- y1
+ 1;
4313 n_chars
= x1
- x0
+ 1;
4318 n_chars
= x0
- x1
+ 1;
4322 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->reverse_gc
,
4323 left
, top
, n_chars
, n_lines
);
4329 /* Draw lines around the text region beginning at the character position
4330 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4331 pixel and line characteristics. */
4333 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4336 outline_region (f
, gc
, top_x
, top_y
, bottom_x
, bottom_y
)
4337 register struct frame
*f
;
4339 int top_x
, top_y
, bottom_x
, bottom_y
;
4341 register int ibw
= f
->output_data
.x
->internal_border_width
;
4342 register int font_w
= FONT_WIDTH (f
->output_data
.x
->font
);
4343 register int font_h
= f
->output_data
.x
->line_height
;
4345 int x
= line_len (y
);
4346 XPoint
*pixel_points
4347 = (XPoint
*) alloca (((bottom_y
- top_y
+ 2) * 4) * sizeof (XPoint
));
4348 register XPoint
*this_point
= pixel_points
;
4350 /* Do the horizontal top line/lines */
4353 this_point
->x
= ibw
;
4354 this_point
->y
= ibw
+ (font_h
* top_y
);
4357 this_point
->x
= ibw
+ (font_w
/ 2); /* Half-size for newline chars. */
4359 this_point
->x
= ibw
+ (font_w
* x
);
4360 this_point
->y
= (this_point
- 1)->y
;
4364 this_point
->x
= ibw
;
4365 this_point
->y
= ibw
+ (font_h
* (top_y
+ 1));
4367 this_point
->x
= ibw
+ (font_w
* top_x
);
4368 this_point
->y
= (this_point
- 1)->y
;
4370 this_point
->x
= (this_point
- 1)->x
;
4371 this_point
->y
= ibw
+ (font_h
* top_y
);
4373 this_point
->x
= ibw
+ (font_w
* x
);
4374 this_point
->y
= (this_point
- 1)->y
;
4377 /* Now do the right side. */
4378 while (y
< bottom_y
)
4379 { /* Right vertical edge */
4381 this_point
->x
= (this_point
- 1)->x
;
4382 this_point
->y
= ibw
+ (font_h
* (y
+ 1));
4385 y
++; /* Horizontal connection to next line */
4388 this_point
->x
= ibw
+ (font_w
/ 2);
4390 this_point
->x
= ibw
+ (font_w
* x
);
4392 this_point
->y
= (this_point
- 1)->y
;
4395 /* Now do the bottom and connect to the top left point. */
4396 this_point
->x
= ibw
+ (font_w
* (bottom_x
+ 1));
4399 this_point
->x
= (this_point
- 1)->x
;
4400 this_point
->y
= ibw
+ (font_h
* (bottom_y
+ 1));
4402 this_point
->x
= ibw
;
4403 this_point
->y
= (this_point
- 1)->y
;
4405 this_point
->x
= pixel_points
->x
;
4406 this_point
->y
= pixel_points
->y
;
4408 XDrawLines (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4410 (this_point
- pixel_points
+ 1), CoordModeOrigin
);
4413 DEFUN ("x-contour-region", Fx_contour_region
, Sx_contour_region
, 1, 1, 0,
4414 "Highlight the region between point and the character under the mouse\n\
4417 register Lisp_Object event
;
4419 register int x0
, y0
, x1
, y1
;
4420 register struct frame
*f
= selected_frame
;
4421 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4422 register int p1
, p2
;
4424 CHECK_CONS (event
, 0);
4427 x0
= XINT (Fcar (Fcar (event
)));
4428 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4430 /* If the mouse is past the end of the line, don't that area. */
4431 /* ReWrite this... */
4433 /* Where the cursor is. */
4434 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4435 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4437 if (y1
> y0
) /* point below mouse */
4438 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4440 else if (y1
< y0
) /* point above mouse */
4441 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4443 else /* same line: draw horizontal rectangle */
4446 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4447 x0
, y0
, (x1
- x0
+ 1), 1);
4449 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4450 x1
, y1
, (x0
- x1
+ 1), 1);
4453 XFlush (FRAME_X_DISPLAY (f
));
4459 DEFUN ("x-uncontour-region", Fx_uncontour_region
, Sx_uncontour_region
, 1, 1, 0,
4460 "Erase any highlighting of the region between point and the character\n\
4461 at X, Y on the selected frame.")
4463 register Lisp_Object event
;
4465 register int x0
, y0
, x1
, y1
;
4466 register struct frame
*f
= selected_frame
;
4467 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4470 x0
= XINT (Fcar (Fcar (event
)));
4471 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4472 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4473 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4475 if (y1
> y0
) /* point below mouse */
4476 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4478 else if (y1
< y0
) /* point above mouse */
4479 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4481 else /* same line: draw horizontal rectangle */
4484 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4485 x0
, y0
, (x1
- x0
+ 1), 1);
4487 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4488 x1
, y1
, (x0
- x1
+ 1), 1);
4496 int contour_begin_x
, contour_begin_y
;
4497 int contour_end_x
, contour_end_y
;
4498 int contour_npoints
;
4500 /* Clip the top part of the contour lines down (and including) line Y_POS.
4501 If X_POS is in the middle (rather than at the end) of the line, drop
4502 down a line at that character. */
4505 clip_contour_top (y_pos
, x_pos
)
4507 register XPoint
*begin
= contour_lines
[y_pos
].top_left
;
4508 register XPoint
*end
;
4509 register int npoints
;
4510 register struct display_line
*line
= selected_frame
->phys_lines
[y_pos
+ 1];
4512 if (x_pos
>= line
->len
- 1) /* Draw one, straight horizontal line. */
4514 end
= contour_lines
[y_pos
].top_right
;
4515 npoints
= (end
- begin
+ 1);
4516 XDrawLines (x_current_display
, contour_window
,
4517 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4519 bcopy (end
, begin
+ 1, contour_last_point
- end
+ 1);
4520 contour_last_point
-= (npoints
- 2);
4521 XDrawLines (x_current_display
, contour_window
,
4522 contour_erase_gc
, begin
, 2, CoordModeOrigin
);
4523 XFlush (x_current_display
);
4525 /* Now, update contour_lines structure. */
4530 register XPoint
*p
= begin
+ 1;
4531 end
= contour_lines
[y_pos
].bottom_right
;
4532 npoints
= (end
- begin
+ 1);
4533 XDrawLines (x_current_display
, contour_window
,
4534 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4537 p
->x
= ibw
+ (font_w
* (x_pos
+ 1));
4539 p
->y
= begin
->y
+ font_h
;
4541 bcopy (end
, begin
+ 3, contour_last_point
- end
+ 1);
4542 contour_last_point
-= (npoints
- 5);
4543 XDrawLines (x_current_display
, contour_window
,
4544 contour_erase_gc
, begin
, 4, CoordModeOrigin
);
4545 XFlush (x_current_display
);
4547 /* Now, update contour_lines structure. */
4551 /* Erase the top horizontal lines of the contour, and then extend
4552 the contour upwards. */
4555 extend_contour_top (line
)
4560 clip_contour_bottom (x_pos
, y_pos
)
4566 extend_contour_bottom (x_pos
, y_pos
)
4570 DEFUN ("x-select-region", Fx_select_region
, Sx_select_region
, 1, 1, "e",
4575 register struct frame
*f
= selected_frame
;
4576 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4577 register int point_x
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4578 register int point_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4579 register int mouse_below_point
;
4580 register Lisp_Object obj
;
4581 register int x_contour_x
, x_contour_y
;
4583 x_contour_x
= x_mouse_x
;
4584 x_contour_y
= x_mouse_y
;
4585 if (x_contour_y
> point_y
|| (x_contour_y
== point_y
4586 && x_contour_x
> point_x
))
4588 mouse_below_point
= 1;
4589 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4590 x_contour_x
, x_contour_y
);
4594 mouse_below_point
= 0;
4595 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_contour_x
, x_contour_y
,
4601 obj
= read_char (-1, 0, 0, Qnil
, 0);
4605 if (mouse_below_point
)
4607 if (x_mouse_y
<= point_y
) /* Flipped. */
4609 mouse_below_point
= 0;
4611 outline_region (f
, f
->output_data
.x
->reverse_gc
, point_x
, point_y
,
4612 x_contour_x
, x_contour_y
);
4613 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_mouse_x
, x_mouse_y
,
4616 else if (x_mouse_y
< x_contour_y
) /* Bottom clipped. */
4618 clip_contour_bottom (x_mouse_y
);
4620 else if (x_mouse_y
> x_contour_y
) /* Bottom extended. */
4622 extend_bottom_contour (x_mouse_y
);
4625 x_contour_x
= x_mouse_x
;
4626 x_contour_y
= x_mouse_y
;
4628 else /* mouse above or same line as point */
4630 if (x_mouse_y
>= point_y
) /* Flipped. */
4632 mouse_below_point
= 1;
4634 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4635 x_contour_x
, x_contour_y
, point_x
, point_y
);
4636 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4637 x_mouse_x
, x_mouse_y
);
4639 else if (x_mouse_y
> x_contour_y
) /* Top clipped. */
4641 clip_contour_top (x_mouse_y
);
4643 else if (x_mouse_y
< x_contour_y
) /* Top extended. */
4645 extend_contour_top (x_mouse_y
);
4650 unread_command_event
= obj
;
4651 if (mouse_below_point
)
4653 contour_begin_x
= point_x
;
4654 contour_begin_y
= point_y
;
4655 contour_end_x
= x_contour_x
;
4656 contour_end_y
= x_contour_y
;
4660 contour_begin_x
= x_contour_x
;
4661 contour_begin_y
= x_contour_y
;
4662 contour_end_x
= point_x
;
4663 contour_end_y
= point_y
;
4668 DEFUN ("x-horizontal-line", Fx_horizontal_line
, Sx_horizontal_line
, 1, 1, "e",
4673 register Lisp_Object obj
;
4674 struct frame
*f
= selected_frame
;
4675 register struct window
*w
= XWINDOW (selected_window
);
4676 register GC line_gc
= f
->output_data
.x
->cursor_gc
;
4677 register GC erase_gc
= f
->output_data
.x
->reverse_gc
;
4679 char dash_list
[] = {6, 4, 6, 4};
4681 XGCValues gc_values
;
4683 register int previous_y
;
4684 register int line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4685 + f
->output_data
.x
->internal_border_width
;
4686 register int left
= f
->output_data
.x
->internal_border_width
4687 + (WINDOW_LEFT_MARGIN (w
)
4688 * FONT_WIDTH (f
->output_data
.x
->font
));
4689 register int right
= left
+ (w
->width
4690 * FONT_WIDTH (f
->output_data
.x
->font
))
4691 - f
->output_data
.x
->internal_border_width
;
4695 gc_values
.foreground
= f
->output_data
.x
->cursor_pixel
;
4696 gc_values
.background
= f
->output_data
.x
->background_pixel
;
4697 gc_values
.line_width
= 1;
4698 gc_values
.line_style
= LineOnOffDash
;
4699 gc_values
.cap_style
= CapRound
;
4700 gc_values
.join_style
= JoinRound
;
4702 line_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4703 GCLineStyle
| GCJoinStyle
| GCCapStyle
4704 | GCLineWidth
| GCForeground
| GCBackground
,
4706 XSetDashes (FRAME_X_DISPLAY (f
), line_gc
, 0, dash_list
, dashes
);
4707 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
4708 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
4709 erase_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4710 GCLineStyle
| GCJoinStyle
| GCCapStyle
4711 | GCLineWidth
| GCForeground
| GCBackground
,
4713 XSetDashes (FRAME_X_DISPLAY (f
), erase_gc
, 0, dash_list
, dashes
);
4720 if (x_mouse_y
>= XINT (w
->top
)
4721 && x_mouse_y
< XINT (w
->top
) + XINT (w
->height
) - 1)
4723 previous_y
= x_mouse_y
;
4724 line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4725 + f
->output_data
.x
->internal_border_width
;
4726 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4727 line_gc
, left
, line
, right
, line
);
4729 XFlush (FRAME_X_DISPLAY (f
));
4734 obj
= read_char (-1, 0, 0, Qnil
, 0);
4736 || (! EQ (Fcar (Fcdr (Fcdr (obj
))),
4737 Qvertical_scroll_bar
))
4741 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4742 erase_gc
, left
, line
, right
, line
);
4743 unread_command_event
= obj
;
4745 XFreeGC (FRAME_X_DISPLAY (f
), line_gc
);
4746 XFreeGC (FRAME_X_DISPLAY (f
), erase_gc
);
4752 while (x_mouse_y
== previous_y
);
4755 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4756 erase_gc
, left
, line
, right
, line
);
4763 /* These keep track of the rectangle following the pointer. */
4764 int mouse_track_top
, mouse_track_left
, mouse_track_width
;
4766 /* Offset in buffer of character under the pointer, or 0. */
4767 int mouse_buffer_offset
;
4769 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 0, 0, 0,
4770 "Track the pointer.")
4773 static Cursor current_pointer_shape
;
4774 FRAME_PTR f
= x_mouse_frame
;
4777 if (EQ (Vmouse_frame_part
, Qtext_part
)
4778 && (current_pointer_shape
!= f
->output_data
.x
->nontext_cursor
))
4783 current_pointer_shape
= f
->output_data
.x
->nontext_cursor
;
4784 XDefineCursor (FRAME_X_DISPLAY (f
),
4786 current_pointer_shape
);
4788 buf
= XBUFFER (XWINDOW (Vmouse_window
)->buffer
);
4789 c
= *(BUF_CHAR_ADDRESS (buf
, mouse_buffer_offset
));
4791 else if (EQ (Vmouse_frame_part
, Qmodeline_part
)
4792 && (current_pointer_shape
!= f
->output_data
.x
->modeline_cursor
))
4794 current_pointer_shape
= f
->output_data
.x
->modeline_cursor
;
4795 XDefineCursor (FRAME_X_DISPLAY (f
),
4797 current_pointer_shape
);
4800 XFlush (FRAME_X_DISPLAY (f
));
4806 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 1, 1, "e",
4807 "Draw rectangle around character under mouse pointer, if there is one.")
4811 struct window
*w
= XWINDOW (Vmouse_window
);
4812 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4813 struct buffer
*b
= XBUFFER (w
->buffer
);
4816 if (! EQ (Vmouse_window
, selected_window
))
4819 if (EQ (event
, Qnil
))
4823 x_read_mouse_position (selected_frame
, &x
, &y
);
4827 mouse_track_width
= 0;
4828 mouse_track_left
= mouse_track_top
= -1;
4832 if ((x_mouse_x
!= mouse_track_left
4833 && (x_mouse_x
< mouse_track_left
4834 || x_mouse_x
> (mouse_track_left
+ mouse_track_width
)))
4835 || x_mouse_y
!= mouse_track_top
)
4837 int hp
= 0; /* Horizontal position */
4838 int len
= FRAME_CURRENT_GLYPHS (f
)->used
[x_mouse_y
];
4839 int p
= FRAME_CURRENT_GLYPHS (f
)->bufp
[x_mouse_y
];
4840 int tab_width
= XINT (b
->tab_width
);
4841 int ctl_arrow_p
= !NILP (b
->ctl_arrow
);
4843 int mode_line_vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
4844 int in_mode_line
= 0;
4846 if (! FRAME_CURRENT_GLYPHS (f
)->enable
[x_mouse_y
])
4849 /* Erase previous rectangle. */
4850 if (mouse_track_width
)
4852 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4853 mouse_track_left
, mouse_track_top
,
4854 mouse_track_width
, 1);
4856 if ((mouse_track_left
== f
->phys_cursor_x
4857 || mouse_track_left
== f
->phys_cursor_x
- 1)
4858 && mouse_track_top
== f
->phys_cursor_y
)
4860 x_display_cursor (f
, 1);
4864 mouse_track_left
= x_mouse_x
;
4865 mouse_track_top
= x_mouse_y
;
4866 mouse_track_width
= 0;
4868 if (mouse_track_left
> len
) /* Past the end of line. */
4871 if (mouse_track_top
== mode_line_vpos
)
4877 if (tab_width
<= 0 || tab_width
> 20) tab_width
= 8;
4881 if (len
== f
->width
&& hp
== len
- 1 && c
!= '\n')
4887 mouse_track_width
= tab_width
- (hp
% tab_width
);
4889 hp
+= mouse_track_width
;
4892 mouse_track_left
= hp
- mouse_track_width
;
4898 mouse_track_width
= -1;
4902 if (ctl_arrow_p
&& (c
< 040 || c
== 0177))
4907 mouse_track_width
= 2;
4912 mouse_track_left
= hp
- mouse_track_width
;
4918 mouse_track_width
= 1;
4925 while (hp
<= x_mouse_x
);
4928 if (mouse_track_width
) /* Over text; use text pointer shape. */
4930 XDefineCursor (FRAME_X_DISPLAY (f
),
4932 f
->output_data
.x
->text_cursor
);
4933 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4934 mouse_track_left
, mouse_track_top
,
4935 mouse_track_width
, 1);
4937 else if (in_mode_line
)
4938 XDefineCursor (FRAME_X_DISPLAY (f
),
4940 f
->output_data
.x
->modeline_cursor
);
4942 XDefineCursor (FRAME_X_DISPLAY (f
),
4944 f
->output_data
.x
->nontext_cursor
);
4947 XFlush (FRAME_X_DISPLAY (f
));
4950 obj
= read_char (-1, 0, 0, Qnil
, 0);
4953 while (CONSP (obj
) /* Mouse event */
4954 && EQ (Fcar (Fcdr (Fcdr (obj
))), Qnil
) /* Not scroll bar */
4955 && EQ (Vmouse_depressed
, Qnil
) /* Only motion events */
4956 && EQ (Vmouse_window
, selected_window
) /* In this window */
4959 unread_command_event
= obj
;
4961 if (mouse_track_width
)
4963 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4964 mouse_track_left
, mouse_track_top
,
4965 mouse_track_width
, 1);
4966 mouse_track_width
= 0;
4967 if ((mouse_track_left
== f
->phys_cursor_x
4968 || mouse_track_left
- 1 == f
->phys_cursor_x
)
4969 && mouse_track_top
== f
->phys_cursor_y
)
4971 x_display_cursor (f
, 1);
4974 XDefineCursor (FRAME_X_DISPLAY (f
),
4976 f
->output_data
.x
->nontext_cursor
);
4977 XFlush (FRAME_X_DISPLAY (f
));
4987 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
4988 on the frame F at position X, Y. */
4990 x_draw_pixmap (f
, x
, y
, image_data
, width
, height
)
4992 int x
, y
, width
, height
;
4997 image
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
4998 FRAME_X_WINDOW (f
), image_data
,
5000 XCopyPlane (FRAME_X_DISPLAY (f
), image
, FRAME_X_WINDOW (f
),
5001 f
->output_data
.x
->normal_gc
, 0, 0, width
, height
, x
, y
);
5005 #if 0 /* I'm told these functions are superfluous
5006 given the ability to bind function keys. */
5009 DEFUN ("x-rebind-key", Fx_rebind_key
, Sx_rebind_key
, 3, 3, 0,
5010 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
5011 KEYSYM is a string which conforms to the X keysym definitions found\n\
5012 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
5013 list of strings specifying modifier keys such as Control_L, which must\n\
5014 also be depressed for NEWSTRING to appear.")
5015 (x_keysym
, modifiers
, newstring
)
5016 register Lisp_Object x_keysym
;
5017 register Lisp_Object modifiers
;
5018 register Lisp_Object newstring
;
5021 register KeySym keysym
;
5022 KeySym modifier_list
[16];
5025 CHECK_STRING (x_keysym
, 1);
5026 CHECK_STRING (newstring
, 3);
5028 keysym
= XStringToKeysym ((char *) XSTRING (x_keysym
)->data
);
5029 if (keysym
== NoSymbol
)
5030 error ("Keysym does not exist");
5032 if (NILP (modifiers
))
5033 XRebindKeysym (x_current_display
, keysym
, modifier_list
, 0,
5034 XSTRING (newstring
)->data
,
5035 STRING_BYTES (XSTRING (newstring
)));
5038 register Lisp_Object rest
, mod
;
5041 for (rest
= modifiers
; !NILP (rest
); rest
= Fcdr (rest
))
5044 error ("Can't have more than 16 modifiers");
5047 CHECK_STRING (mod
, 3);
5048 modifier_list
[i
] = XStringToKeysym ((char *) XSTRING (mod
)->data
);
5050 if (modifier_list
[i
] == NoSymbol
5051 || !(IsModifierKey (modifier_list
[i
])
5052 || ((unsigned)(modifier_list
[i
]) == XK_Mode_switch
)
5053 || ((unsigned)(modifier_list
[i
]) == XK_Num_Lock
)))
5055 if (modifier_list
[i
] == NoSymbol
5056 || !IsModifierKey (modifier_list
[i
]))
5058 error ("Element is not a modifier keysym");
5062 XRebindKeysym (x_current_display
, keysym
, modifier_list
, i
,
5063 XSTRING (newstring
)->data
,
5064 STRING_BYTES (XSTRING (newstring
)));
5070 DEFUN ("x-rebind-keys", Fx_rebind_keys
, Sx_rebind_keys
, 2, 2, 0,
5071 "Rebind KEYCODE to list of strings STRINGS.\n\
5072 STRINGS should be a list of 16 elements, one for each shift combination.\n\
5073 nil as element means don't change.\n\
5074 See the documentation of `x-rebind-key' for more information.")
5076 register Lisp_Object keycode
;
5077 register Lisp_Object strings
;
5079 register Lisp_Object item
;
5080 register unsigned char *rawstring
;
5081 KeySym rawkey
, modifier
[1];
5083 register unsigned i
;
5086 CHECK_NUMBER (keycode
, 1);
5087 CHECK_CONS (strings
, 2);
5088 rawkey
= (KeySym
) ((unsigned) (XINT (keycode
))) & 255;
5089 for (i
= 0; i
<= 15; strings
= Fcdr (strings
), i
++)
5091 item
= Fcar (strings
);
5094 CHECK_STRING (item
, 2);
5095 strsize
= STRING_BYTES (XSTRING (item
));
5096 rawstring
= (unsigned char *) xmalloc (strsize
);
5097 bcopy (XSTRING (item
)->data
, rawstring
, strsize
);
5098 modifier
[1] = 1 << i
;
5099 XRebindKeysym (x_current_display
, rawkey
, modifier
, 1,
5100 rawstring
, strsize
);
5105 #endif /* HAVE_X11 */
5108 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5110 XScreenNumberOfScreen (scr
)
5111 register Screen
*scr
;
5113 register Display
*dpy
;
5114 register Screen
*dpyscr
;
5118 dpyscr
= dpy
->screens
;
5120 for (i
= 0; i
< dpy
->nscreens
; i
++, dpyscr
++)
5126 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5129 select_visual (dpy
, screen
, depth
)
5132 unsigned int *depth
;
5135 XVisualInfo
*vinfo
, vinfo_template
;
5138 v
= DefaultVisualOfScreen (screen
);
5141 vinfo_template
.visualid
= XVisualIDFromVisual (v
);
5143 vinfo_template
.visualid
= v
->visualid
;
5146 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5148 vinfo
= XGetVisualInfo (dpy
,
5149 VisualIDMask
| VisualScreenMask
, &vinfo_template
,
5152 fatal ("Can't get proper X visual info");
5154 if ((1 << vinfo
->depth
) == vinfo
->colormap_size
)
5155 *depth
= vinfo
->depth
;
5159 int n
= vinfo
->colormap_size
- 1;
5168 XFree ((char *) vinfo
);
5172 /* Return the X display structure for the display named NAME.
5173 Open a new connection if necessary. */
5175 struct x_display_info
*
5176 x_display_info_for_name (name
)
5180 struct x_display_info
*dpyinfo
;
5182 CHECK_STRING (name
, 0);
5184 if (! EQ (Vwindow_system
, intern ("x")))
5185 error ("Not using X Windows");
5187 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5189 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
5192 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
5197 /* Use this general default value to start with. */
5198 Vx_resource_name
= Vinvocation_name
;
5200 validate_x_resource_name ();
5202 dpyinfo
= x_term_init (name
, (unsigned char *)0,
5203 (char *) XSTRING (Vx_resource_name
)->data
);
5206 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5209 XSETFASTINT (Vwindow_system_version
, 11);
5214 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5215 1, 3, 0, "Open a connection to an X server.\n\
5216 DISPLAY is the name of the display to connect to.\n\
5217 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5218 If the optional third arg MUST-SUCCEED is non-nil,\n\
5219 terminate Emacs if we can't open the connection.")
5220 (display
, xrm_string
, must_succeed
)
5221 Lisp_Object display
, xrm_string
, must_succeed
;
5223 unsigned char *xrm_option
;
5224 struct x_display_info
*dpyinfo
;
5226 CHECK_STRING (display
, 0);
5227 if (! NILP (xrm_string
))
5228 CHECK_STRING (xrm_string
, 1);
5230 if (! EQ (Vwindow_system
, intern ("x")))
5231 error ("Not using X Windows");
5233 if (! NILP (xrm_string
))
5234 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5236 xrm_option
= (unsigned char *) 0;
5238 validate_x_resource_name ();
5240 /* This is what opens the connection and sets x_current_display.
5241 This also initializes many symbols, such as those used for input. */
5242 dpyinfo
= x_term_init (display
, xrm_option
,
5243 (char *) XSTRING (Vx_resource_name
)->data
);
5247 if (!NILP (must_succeed
))
5248 fatal ("Cannot connect to X server %s.\n\
5249 Check the DISPLAY environment variable or use `-d'.\n\
5250 Also use the `xhost' program to verify that it is set to permit\n\
5251 connections from your machine.\n",
5252 XSTRING (display
)->data
);
5254 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5259 XSETFASTINT (Vwindow_system_version
, 11);
5263 DEFUN ("x-close-connection", Fx_close_connection
,
5264 Sx_close_connection
, 1, 1, 0,
5265 "Close the connection to DISPLAY's X server.\n\
5266 For DISPLAY, specify either a frame or a display name (a string).\n\
5267 If DISPLAY is nil, that stands for the selected frame's display.")
5269 Lisp_Object display
;
5271 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5274 if (dpyinfo
->reference_count
> 0)
5275 error ("Display still has frames on it");
5278 /* Free the fonts in the font table. */
5279 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5280 if (dpyinfo
->font_table
[i
].name
)
5282 xfree (dpyinfo
->font_table
[i
].name
);
5283 /* Don't free the full_name string;
5284 it is always shared with something else. */
5285 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5288 x_destroy_all_bitmaps (dpyinfo
);
5289 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5291 #ifdef USE_X_TOOLKIT
5292 XtCloseDisplay (dpyinfo
->display
);
5294 XCloseDisplay (dpyinfo
->display
);
5297 x_delete_display (dpyinfo
);
5303 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5304 "Return the list of display names that Emacs has connections to.")
5307 Lisp_Object tail
, result
;
5310 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
5311 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
5316 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5317 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5318 If ON is nil, allow buffering of requests.\n\
5319 Turning on synchronization prohibits the Xlib routines from buffering\n\
5320 requests and seriously degrades performance, but makes debugging much\n\
5322 The optional second argument DISPLAY specifies which display to act on.\n\
5323 DISPLAY should be either a frame or a display name (a string).\n\
5324 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5326 Lisp_Object display
, on
;
5328 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5330 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5335 /* Wait for responses to all X commands issued so far for frame F. */
5342 XSync (FRAME_X_DISPLAY (f
), False
);
5347 /***********************************************************************
5349 ***********************************************************************/
5351 /* Value is the number of elements of vector VECTOR. */
5353 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5355 /* List of supported image types. Use define_image_type to add new
5356 types. Use lookup_image_type to find a type for a given symbol. */
5358 static struct image_type
*image_types
;
5360 /* A list of symbols, one for each supported image type. */
5362 Lisp_Object Vimage_types
;
5364 /* The symbol `image' which is the car of the lists used to represent
5367 extern Lisp_Object Qimage
;
5369 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5375 Lisp_Object QCtype
, QCdata
, QCfile
, QCascent
, QCmargin
, QCrelief
;
5376 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
;
5377 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5378 extern Lisp_Object QCimage
;
5380 /* Other symbols. */
5382 Lisp_Object Qlaplace
;
5384 /* Time in seconds after which images should be removed from the cache
5385 if not displayed. */
5387 Lisp_Object Vimage_eviction_seconds
;
5389 /* Function prototypes. */
5391 static void define_image_type
P_ ((struct image_type
*type
));
5392 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5393 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5394 static void x_laplace
P_ ((struct frame
*, struct image
*));
5395 static int x_build_heuristic_mask
P_ ((struct frame
*, Lisp_Object
,
5396 struct image
*, Lisp_Object
));
5399 /* Define a new image type from TYPE. This adds a copy of TYPE to
5400 image_types and adds the symbol *TYPE->type to Vimage_types. */
5403 define_image_type (type
)
5404 struct image_type
*type
;
5406 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5407 The initialized data segment is read-only. */
5408 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5409 bcopy (type
, p
, sizeof *p
);
5410 p
->next
= image_types
;
5412 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5416 /* Look up image type SYMBOL, and return a pointer to its image_type
5417 structure. Value is null if SYMBOL is not a known image type. */
5419 static INLINE
struct image_type
*
5420 lookup_image_type (symbol
)
5423 struct image_type
*type
;
5425 for (type
= image_types
; type
; type
= type
->next
)
5426 if (EQ (symbol
, *type
->type
))
5433 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5434 valid image specification is a list whose car is the symbol
5435 `image', and whose rest is a property list. The property list must
5436 contain a value for key `:type'. That value must be the name of a
5437 supported image type. The rest of the property list depends on the
5441 valid_image_p (object
)
5446 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5448 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5449 struct image_type
*type
= lookup_image_type (symbol
);
5452 valid_p
= type
->valid_p (object
);
5459 /* Display an error message with format string FORMAT and argument
5460 ARG. Signaling an error, e.g. when an image cannot be loaded,
5461 is not a good idea because this would interrupt redisplay, and
5462 the error message display would lead to another redisplay. This
5463 function therefore simply displays a message. */
5466 image_error (format
, arg1
, arg2
)
5468 Lisp_Object arg1
, arg2
;
5470 Lisp_Object args
[3];
5472 args
[0] = build_string (format
);
5475 Fmessage (make_number (DIM (args
)), args
);
5480 /***********************************************************************
5481 Image specifications
5482 ***********************************************************************/
5484 enum image_value_type
5486 IMAGE_DONT_CHECK_VALUE_TYPE
,
5489 IMAGE_POSITIVE_INTEGER_VALUE
,
5490 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5491 IMAGE_INTEGER_VALUE
,
5492 IMAGE_FUNCTION_VALUE
,
5497 /* Structure used when parsing image specifications. */
5499 struct image_keyword
5501 /* Name of keyword. */
5504 /* The type of value allowed. */
5505 enum image_value_type type
;
5507 /* Non-zero means key must be present. */
5510 /* Used to recognize duplicate keywords in a property list. */
5513 /* The value that was found. */
5518 static int parse_image_spec
P_ ((Lisp_Object spec
,
5519 struct image_keyword
*keywords
,
5520 int nkeywords
, Lisp_Object type
,
5521 int allow_other_keys_p
));
5522 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5525 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5526 has the format (image KEYWORD VALUE ...). One of the keyword/
5527 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5528 image_keywords structures of size NKEYWORDS describing other
5529 allowed keyword/value pairs. ALLOW_OTHER_KEYS_P non-zero means
5530 allow KEYWORD/VALUE pairs other than those described by KEYWORDS
5531 without checking them. Value is non-zero if SPEC is valid. */
5534 parse_image_spec (spec
, keywords
, nkeywords
, type
, allow_other_keys_p
)
5536 struct image_keyword
*keywords
;
5539 int allow_other_keys_p
;
5544 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5547 plist
= XCDR (spec
);
5548 while (CONSP (plist
))
5550 Lisp_Object key
, value
;
5552 /* First element of a pair must be a symbol. */
5554 plist
= XCDR (plist
);
5558 /* There must follow a value. */
5561 value
= XCAR (plist
);
5562 plist
= XCDR (plist
);
5564 /* Find key in KEYWORDS. Error if not found. */
5565 for (i
= 0; i
< nkeywords
; ++i
)
5566 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5571 if (!allow_other_keys_p
)
5576 /* Record that we recognized the keyword. If a keywords
5577 was found more than once, it's an error. */
5578 keywords
[i
].value
= value
;
5579 ++keywords
[i
].count
;
5581 if (keywords
[i
].count
> 1)
5584 /* Check type of value against allowed type. */
5585 switch (keywords
[i
].type
)
5587 case IMAGE_STRING_VALUE
:
5588 if (!STRINGP (value
))
5592 case IMAGE_SYMBOL_VALUE
:
5593 if (!SYMBOLP (value
))
5597 case IMAGE_POSITIVE_INTEGER_VALUE
:
5598 if (!INTEGERP (value
) || XINT (value
) <= 0)
5602 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5603 if (!INTEGERP (value
) || XINT (value
) < 0)
5607 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5610 case IMAGE_FUNCTION_VALUE
:
5611 value
= indirect_function (value
);
5613 || COMPILEDP (value
)
5614 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5618 case IMAGE_NUMBER_VALUE
:
5619 if (!INTEGERP (value
) && !FLOATP (value
))
5623 case IMAGE_INTEGER_VALUE
:
5624 if (!INTEGERP (value
))
5628 case IMAGE_BOOL_VALUE
:
5629 if (!NILP (value
) && !EQ (value
, Qt
))
5638 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5642 /* Check that all mandatory fields are present. */
5643 for (i
= 0; i
< nkeywords
; ++i
)
5644 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5647 return NILP (plist
);
5651 /* Return the value of KEY in image specification SPEC. Value is nil
5652 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5653 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5656 image_spec_value (spec
, key
, found
)
5657 Lisp_Object spec
, key
;
5662 xassert (valid_image_p (spec
));
5664 for (tail
= XCDR (spec
);
5665 CONSP (tail
) && CONSP (XCDR (tail
));
5666 tail
= XCDR (XCDR (tail
)))
5668 if (EQ (XCAR (tail
), key
))
5672 return XCAR (XCDR (tail
));
5684 /***********************************************************************
5685 Image type independent image structures
5686 ***********************************************************************/
5688 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5689 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5692 /* Allocate and return a new image structure for image specification
5693 SPEC. SPEC has a hash value of HASH. */
5695 static struct image
*
5696 make_image (spec
, hash
)
5700 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5702 xassert (valid_image_p (spec
));
5703 bzero (img
, sizeof *img
);
5704 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5705 xassert (img
->type
!= NULL
);
5707 img
->data
.lisp_val
= Qnil
;
5708 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5714 /* Free image IMG which was used on frame F, including its resources. */
5723 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5725 /* Remove IMG from the hash table of its cache. */
5727 img
->prev
->next
= img
->next
;
5729 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5732 img
->next
->prev
= img
->prev
;
5734 c
->images
[img
->id
] = NULL
;
5736 /* Free resources, then free IMG. */
5737 img
->type
->free (f
, img
);
5743 /* Prepare image IMG for display on frame F. Must be called before
5744 drawing an image. */
5747 prepare_image_for_display (f
, img
)
5753 /* We're about to display IMG, so set its timestamp to `now'. */
5755 img
->timestamp
= EMACS_SECS (t
);
5757 /* If IMG doesn't have a pixmap yet, load it now, using the image
5758 type dependent loader function. */
5759 if (img
->pixmap
== 0)
5760 img
->type
->load (f
, img
);
5765 /***********************************************************************
5766 Helper functions for X image types
5767 ***********************************************************************/
5769 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5770 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5772 Lisp_Object color_name
,
5773 unsigned long dflt
));
5775 /* Free X resources of image IMG which is used on frame F. */
5778 x_clear_image (f
, img
)
5785 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5792 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
5794 /* If display has an immutable color map, freeing colors is not
5795 necessary and some servers don't allow it. So don't do it. */
5796 if (class != StaticColor
5797 && class != StaticGray
5798 && class != TrueColor
)
5802 cmap
= DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f
)->screen
);
5803 XFreeColors (FRAME_X_DISPLAY (f
), cmap
, img
->colors
,
5808 xfree (img
->colors
);
5815 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5816 cannot be allocated, use DFLT. Add a newly allocated color to
5817 IMG->colors, so that it can be freed again. Value is the pixel
5820 static unsigned long
5821 x_alloc_image_color (f
, img
, color_name
, dflt
)
5824 Lisp_Object color_name
;
5828 unsigned long result
;
5830 xassert (STRINGP (color_name
));
5832 if (defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5834 /* This isn't called frequently so we get away with simply
5835 reallocating the color vector to the needed size, here. */
5838 (unsigned long *) xrealloc (img
->colors
,
5839 img
->ncolors
* sizeof *img
->colors
);
5840 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5841 result
= color
.pixel
;
5851 /***********************************************************************
5853 ***********************************************************************/
5855 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5858 /* Return a new, initialized image cache that is allocated from the
5859 heap. Call free_image_cache to free an image cache. */
5861 struct image_cache
*
5864 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5867 bzero (c
, sizeof *c
);
5869 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5870 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5871 c
->buckets
= (struct image
**) xmalloc (size
);
5872 bzero (c
->buckets
, size
);
5877 /* Free image cache of frame F. Be aware that X frames share images
5881 free_image_cache (f
)
5884 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5889 /* Cache should not be referenced by any frame when freed. */
5890 xassert (c
->refcount
== 0);
5892 for (i
= 0; i
< c
->used
; ++i
)
5893 free_image (f
, c
->images
[i
]);
5897 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5902 /* Clear image cache of frame F. FORCE_P non-zero means free all
5903 images. FORCE_P zero means clear only images that haven't been
5904 displayed for some time. Should be called from time to time to
5905 reduce the number of loaded images. If image-eviction-seconds is
5906 non-nil, this frees images in the cache which weren't displayed for
5907 at least that many seconds. */
5910 clear_image_cache (f
, force_p
)
5914 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5916 if (c
&& INTEGERP (Vimage_eviction_seconds
))
5920 int i
, any_freed_p
= 0;
5923 old
= EMACS_SECS (t
) - XFASTINT (Vimage_eviction_seconds
);
5925 for (i
= 0; i
< c
->used
; ++i
)
5927 struct image
*img
= c
->images
[i
];
5930 || (img
->timestamp
> old
)))
5932 free_image (f
, img
);
5937 /* We may be clearing the image cache because, for example,
5938 Emacs was iconified for a longer period of time. In that
5939 case, current matrices may still contain references to
5940 images freed above. So, clear these matrices. */
5943 clear_current_matrices (f
);
5944 ++windows_or_buffers_changed
;
5950 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5952 "Clear the image cache of FRAME.\n\
5953 FRAME nil or omitted means use the selected frame.\n\
5954 FRAME t means clear the image caches of all frames.")
5962 FOR_EACH_FRAME (tail
, frame
)
5963 if (FRAME_X_P (XFRAME (frame
)))
5964 clear_image_cache (XFRAME (frame
), 1);
5967 clear_image_cache (check_x_frame (frame
), 1);
5973 /* Return the id of image with Lisp specification SPEC on frame F.
5974 SPEC must be a valid Lisp image specification (see valid_image_p). */
5977 lookup_image (f
, spec
)
5981 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5985 struct gcpro gcpro1
;
5987 /* F must be a window-system frame, and SPEC must be a valid image
5989 xassert (FRAME_WINDOW_P (f
));
5990 xassert (valid_image_p (spec
));
5994 /* Look up SPEC in the hash table of the image cache. */
5995 hash
= sxhash (spec
, 0);
5996 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5998 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
5999 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6002 /* If not found, create a new image and cache it. */
6005 extern Lisp_Object QCenable
, QCselect
;
6007 int loading_failed_p
;
6009 img
= make_image (spec
, hash
);
6010 cache_image (f
, img
);
6011 loading_failed_p
= img
->type
->load (f
, img
) == 0;
6013 /* If we can't load the image, and we don't have a width and
6014 height, use some arbitrary width and height so that we can
6015 draw a rectangle for it. */
6016 if (loading_failed_p
)
6020 value
= image_spec_value (spec
, QCwidth
, NULL
);
6021 img
->width
= (INTEGERP (value
)
6022 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6023 value
= image_spec_value (spec
, QCheight
, NULL
);
6024 img
->height
= (INTEGERP (value
)
6025 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6029 /* Handle image type independent image attributes
6030 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
6031 Lisp_Object ascent
, margin
, relief
, algorithm
, heuristic_mask
;
6034 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6035 if (INTEGERP (ascent
))
6036 img
->ascent
= XFASTINT (ascent
);
6038 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6039 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6040 img
->margin
= XFASTINT (margin
);
6042 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6043 if (INTEGERP (relief
))
6045 img
->relief
= XINT (relief
);
6046 img
->margin
+= abs (img
->relief
);
6049 /* Should we apply a Laplace edge-detection algorithm? */
6050 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
6051 if (img
->pixmap
&& EQ (algorithm
, Qlaplace
))
6054 /* Should we built a mask heuristically? */
6055 heuristic_mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6056 if (img
->pixmap
&& !img
->mask
&& !NILP (heuristic_mask
))
6058 file
= image_spec_value (spec
, QCfile
, NULL
);
6059 x_build_heuristic_mask (f
, file
, img
, heuristic_mask
);
6066 /* Value is the image id. */
6071 /* Cache image IMG in the image cache of frame F. */
6074 cache_image (f
, img
)
6078 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6081 /* Find a free slot in c->images. */
6082 for (i
= 0; i
< c
->used
; ++i
)
6083 if (c
->images
[i
] == NULL
)
6086 /* If no free slot found, maybe enlarge c->images. */
6087 if (i
== c
->used
&& c
->used
== c
->size
)
6090 c
->images
= (struct image
**) xrealloc (c
->images
,
6091 c
->size
* sizeof *c
->images
);
6094 /* Add IMG to c->images, and assign IMG an id. */
6100 /* Add IMG to the cache's hash table. */
6101 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6102 img
->next
= c
->buckets
[i
];
6104 img
->next
->prev
= img
;
6106 c
->buckets
[i
] = img
;
6110 /* Call FN on every image in the image cache of frame F. Used to mark
6111 Lisp Objects in the image cache. */
6114 forall_images_in_image_cache (f
, fn
)
6116 void (*fn
) P_ ((struct image
*img
));
6118 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6120 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6124 for (i
= 0; i
< c
->used
; ++i
)
6133 /***********************************************************************
6135 ***********************************************************************/
6137 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, Lisp_Object
,
6138 int, int, int, XImage
**,
6140 static void x_destroy_x_image
P_ ((XImage
*));
6141 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6144 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6145 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6146 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6147 via xmalloc. Print error messages via image_error if an error
6148 occurs. FILE is the name of an image file being processed, for
6149 error messages. Value is non-zero if successful. */
6152 x_create_x_image_and_pixmap (f
, file
, width
, height
, depth
, ximg
, pixmap
)
6155 int width
, height
, depth
;
6159 Display
*display
= FRAME_X_DISPLAY (f
);
6160 Screen
*screen
= FRAME_X_SCREEN (f
);
6161 Window window
= FRAME_X_WINDOW (f
);
6163 xassert (interrupt_input_blocked
);
6166 depth
= DefaultDepthOfScreen (screen
);
6167 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6168 depth
, ZPixmap
, 0, NULL
, width
, height
,
6169 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6172 image_error ("Unable to allocate X image for %s", file
, Qnil
);
6176 /* Allocate image raster. */
6177 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6179 /* Allocate a pixmap of the same size. */
6180 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6183 x_destroy_x_image (*ximg
);
6185 image_error ("Unable to create pixmap for `%s'", file
, Qnil
);
6193 /* Destroy XImage XIMG. Free XIMG->data. */
6196 x_destroy_x_image (ximg
)
6199 xassert (interrupt_input_blocked
);
6204 XDestroyImage (ximg
);
6209 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6210 are width and height of both the image and pixmap. */
6213 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6220 xassert (interrupt_input_blocked
);
6221 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6222 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6223 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6228 /***********************************************************************
6230 ***********************************************************************/
6232 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6234 /* Find image file FILE. Look in data-directory, then
6235 x-bitmap-file-path. Value is the full name of the file found, or
6236 nil if not found. */
6239 x_find_image_file (file
)
6242 Lisp_Object file_found
, search_path
;
6243 struct gcpro gcpro1
, gcpro2
;
6247 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6248 GCPRO2 (file_found
, search_path
);
6250 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6251 fd
= openp (search_path
, file
, "", &file_found
, 0);
6264 /***********************************************************************
6266 ***********************************************************************/
6268 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6269 static int xbm_load_image_from_file
P_ ((struct frame
*f
, struct image
*img
,
6271 static int xbm_image_p
P_ ((Lisp_Object object
));
6272 static int xbm_read_bitmap_file_data
P_ ((char *, int *, int *,
6274 static int xbm_read_hexint
P_ ((FILE *));
6277 /* Indices of image specification fields in xbm_format, below. */
6279 enum xbm_keyword_index
6296 /* Vector of image_keyword structures describing the format
6297 of valid XBM image specifications. */
6299 static struct image_keyword xbm_format
[XBM_LAST
] =
6301 {":type", IMAGE_SYMBOL_VALUE
, 1},
6302 {":file", IMAGE_STRING_VALUE
, 0},
6303 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6304 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6305 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6306 {":foreground", IMAGE_STRING_VALUE
, 0},
6307 {":background", IMAGE_STRING_VALUE
, 0},
6308 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6309 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6310 {":relief", IMAGE_INTEGER_VALUE
, 0},
6311 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6312 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6315 /* Structure describing the image type XBM. */
6317 static struct image_type xbm_type
=
6326 /* Tokens returned from xbm_scan. */
6335 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6336 A valid specification is a list starting with the symbol `image'
6337 The rest of the list is a property list which must contain an
6340 If the specification specifies a file to load, it must contain
6341 an entry `:file FILENAME' where FILENAME is a string.
6343 If the specification is for a bitmap loaded from memory it must
6344 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6345 WIDTH and HEIGHT are integers > 0. DATA may be:
6347 1. a string large enough to hold the bitmap data, i.e. it must
6348 have a size >= (WIDTH + 7) / 8 * HEIGHT
6350 2. a bool-vector of size >= WIDTH * HEIGHT
6352 3. a vector of strings or bool-vectors, one for each line of the
6355 Both the file and data forms may contain the additional entries
6356 `:background COLOR' and `:foreground COLOR'. If not present,
6357 foreground and background of the frame on which the image is
6358 displayed, is used. */
6361 xbm_image_p (object
)
6364 struct image_keyword kw
[XBM_LAST
];
6366 bcopy (xbm_format
, kw
, sizeof kw
);
6367 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
, 0))
6370 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6372 if (kw
[XBM_FILE
].count
)
6374 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6382 /* Entries for `:width', `:height' and `:data' must be present. */
6383 if (!kw
[XBM_WIDTH
].count
6384 || !kw
[XBM_HEIGHT
].count
6385 || !kw
[XBM_DATA
].count
)
6388 data
= kw
[XBM_DATA
].value
;
6389 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6390 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6392 /* Check type of data, and width and height against contents of
6398 /* Number of elements of the vector must be >= height. */
6399 if (XVECTOR (data
)->size
< height
)
6402 /* Each string or bool-vector in data must be large enough
6403 for one line of the image. */
6404 for (i
= 0; i
< height
; ++i
)
6406 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6410 if (XSTRING (elt
)->size
6411 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6414 else if (BOOL_VECTOR_P (elt
))
6416 if (XBOOL_VECTOR (elt
)->size
< width
)
6423 else if (STRINGP (data
))
6425 if (XSTRING (data
)->size
6426 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6429 else if (BOOL_VECTOR_P (data
))
6431 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6438 /* Baseline must be a value between 0 and 100 (a percentage). */
6439 if (kw
[XBM_ASCENT
].count
6440 && XFASTINT (kw
[XBM_ASCENT
].value
) > 100)
6447 /* Scan a bitmap file. FP is the stream to read from. Value is
6448 either an enumerator from enum xbm_token, or a character for a
6449 single-character token, or 0 at end of file. If scanning an
6450 identifier, store the lexeme of the identifier in SVAL. If
6451 scanning a number, store its value in *IVAL. */
6454 xbm_scan (fp
, sval
, ival
)
6461 /* Skip white space. */
6462 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
6467 else if (isdigit (c
))
6469 int value
= 0, digit
;
6474 if (c
== 'x' || c
== 'X')
6476 while ((c
= fgetc (fp
)) != EOF
)
6480 else if (c
>= 'a' && c
<= 'f')
6481 digit
= c
- 'a' + 10;
6482 else if (c
>= 'A' && c
<= 'F')
6483 digit
= c
- 'A' + 10;
6486 value
= 16 * value
+ digit
;
6489 else if (isdigit (c
))
6492 while ((c
= fgetc (fp
)) != EOF
6494 value
= 8 * value
+ c
- '0';
6500 while ((c
= fgetc (fp
)) != EOF
6502 value
= 10 * value
+ c
- '0';
6510 else if (isalpha (c
) || c
== '_')
6513 while ((c
= fgetc (fp
)) != EOF
6514 && (isalnum (c
) || c
== '_'))
6526 /* Replacement for XReadBitmapFileData which isn't available under old
6527 X versions. FILE is the name of the bitmap file to read. Set
6528 *WIDTH and *HEIGHT to the width and height of the image. Return in
6529 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
6533 xbm_read_bitmap_file_data (file
, width
, height
, data
)
6535 int *width
, *height
;
6536 unsigned char **data
;
6539 char buffer
[BUFSIZ
];
6542 int bytes_per_line
, i
, nbytes
;
6548 LA1 = xbm_scan (fp, buffer, &value)
6550 #define expect(TOKEN) \
6551 if (LA1 != (TOKEN)) \
6556 #define expect_ident(IDENT) \
6557 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6562 fp
= fopen (file
, "r");
6566 *width
= *height
= -1;
6568 LA1
= xbm_scan (fp
, buffer
, &value
);
6570 /* Parse defines for width, height and hot-spots. */
6576 expect_ident ("define");
6577 expect (XBM_TK_IDENT
);
6579 if (LA1
== XBM_TK_NUMBER
);
6581 char *p
= strrchr (buffer
, '_');
6582 p
= p
? p
+ 1 : buffer
;
6583 if (strcmp (p
, "width") == 0)
6585 else if (strcmp (p
, "height") == 0)
6588 expect (XBM_TK_NUMBER
);
6591 if (*width
< 0 || *height
< 0)
6594 /* Parse bits. Must start with `static'. */
6595 expect_ident ("static");
6596 if (LA1
== XBM_TK_IDENT
)
6598 if (strcmp (buffer
, "unsigned") == 0)
6601 expect_ident ("char");
6603 else if (strcmp (buffer
, "short") == 0)
6607 if (*width
% 16 && *width
% 16 < 9)
6610 else if (strcmp (buffer
, "char") == 0)
6618 expect (XBM_TK_IDENT
);
6624 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6625 nbytes
= bytes_per_line
* *height
;
6626 p
= *data
= (char *) xmalloc (nbytes
);
6631 for (i
= 0; i
< nbytes
; i
+= 2)
6634 expect (XBM_TK_NUMBER
);
6637 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6640 if (LA1
== ',' || LA1
== '}')
6648 for (i
= 0; i
< nbytes
; ++i
)
6651 expect (XBM_TK_NUMBER
);
6655 if (LA1
== ',' || LA1
== '}')
6681 /* Load XBM image IMG which will be displayed on frame F from file
6682 SPECIFIED_FILE. Value is non-zero if successful. */
6685 xbm_load_image_from_file (f
, img
, specified_file
)
6688 Lisp_Object specified_file
;
6691 unsigned char *data
;
6694 struct gcpro gcpro1
;
6696 xassert (STRINGP (specified_file
));
6700 file
= x_find_image_file (specified_file
);
6701 if (!STRINGP (file
))
6703 image_error ("Cannot find image file %s", specified_file
, Qnil
);
6708 rc
= xbm_read_bitmap_file_data (XSTRING (file
)->data
, &img
->width
,
6709 &img
->height
, &data
);
6712 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6713 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6714 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6717 xassert (img
->width
> 0 && img
->height
> 0);
6719 /* Get foreground and background colors, maybe allocate colors. */
6720 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6722 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6724 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6726 background
= x_alloc_image_color (f
, img
, value
, background
);
6730 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6733 img
->width
, img
->height
,
6734 foreground
, background
,
6738 if (img
->pixmap
== 0)
6740 x_clear_image (f
, img
);
6741 image_error ("Unable to create X pixmap for `%s'", file
, Qnil
);
6749 image_error ("Error loading XBM image %s", img
->spec
, Qnil
);
6756 /* Fill image IMG which is used on frame F with pixmap data. Value is
6757 non-zero if successful. */
6765 Lisp_Object file_name
;
6767 xassert (xbm_image_p (img
->spec
));
6769 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6770 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6771 if (STRINGP (file_name
))
6772 success_p
= xbm_load_image_from_file (f
, img
, file_name
);
6775 struct image_keyword fmt
[XBM_LAST
];
6778 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6779 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6783 /* Parse the list specification. */
6784 bcopy (xbm_format
, fmt
, sizeof fmt
);
6785 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
, 0);
6788 /* Get specified width, and height. */
6789 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6790 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6791 xassert (img
->width
> 0 && img
->height
> 0);
6795 if (fmt
[XBM_ASCENT
].count
)
6796 img
->ascent
= XFASTINT (fmt
[XBM_ASCENT
].value
);
6798 /* Get foreground and background colors, maybe allocate colors. */
6799 if (fmt
[XBM_FOREGROUND
].count
)
6800 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6802 if (fmt
[XBM_BACKGROUND
].count
)
6803 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6806 /* Set bits to the bitmap image data. */
6807 data
= fmt
[XBM_DATA
].value
;
6812 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6814 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6815 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6817 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6819 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6821 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6824 else if (STRINGP (data
))
6825 bits
= XSTRING (data
)->data
;
6827 bits
= XBOOL_VECTOR (data
)->data
;
6829 /* Create the pixmap. */
6830 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6832 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6835 img
->width
, img
->height
,
6836 foreground
, background
,
6842 image_error ("Unable to create pixmap for XBM image", Qnil
, Qnil
);
6843 x_clear_image (f
, img
);
6854 /***********************************************************************
6856 ***********************************************************************/
6860 static int xpm_image_p
P_ ((Lisp_Object object
));
6861 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6862 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6864 #include "X11/xpm.h"
6866 /* The symbol `xpm' identifying XPM-format images. */
6870 /* Indices of image specification fields in xpm_format, below. */
6872 enum xpm_keyword_index
6886 /* Vector of image_keyword structures describing the format
6887 of valid XPM image specifications. */
6889 static struct image_keyword xpm_format
[XPM_LAST
] =
6891 {":type", IMAGE_SYMBOL_VALUE
, 1},
6892 {":file", IMAGE_STRING_VALUE
, 0},
6893 {":data", IMAGE_STRING_VALUE
, 0},
6894 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6895 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6896 {":relief", IMAGE_INTEGER_VALUE
, 0},
6897 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6898 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6899 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6902 /* Structure describing the image type XBM. */
6904 static struct image_type xpm_type
=
6914 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6915 for XPM images. Such a list must consist of conses whose car and
6919 xpm_valid_color_symbols_p (color_symbols
)
6920 Lisp_Object color_symbols
;
6922 while (CONSP (color_symbols
))
6924 Lisp_Object sym
= XCAR (color_symbols
);
6926 || !STRINGP (XCAR (sym
))
6927 || !STRINGP (XCDR (sym
)))
6929 color_symbols
= XCDR (color_symbols
);
6932 return NILP (color_symbols
);
6936 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6939 xpm_image_p (object
)
6942 struct image_keyword fmt
[XPM_LAST
];
6943 bcopy (xpm_format
, fmt
, sizeof fmt
);
6944 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
, 0)
6945 /* Either `:file' or `:data' must be present. */
6946 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
6947 /* Either no `:color-symbols' or it's a list of conses
6948 whose car and cdr are strings. */
6949 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
6950 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
))
6951 && (fmt
[XPM_ASCENT
].count
== 0
6952 || XFASTINT (fmt
[XPM_ASCENT
].value
) < 100));
6956 /* Load image IMG which will be displayed on frame F. Value is
6957 non-zero if successful. */
6965 XpmAttributes attrs
;
6966 Lisp_Object specified_file
, color_symbols
;
6968 /* Configure the XPM lib. Use the visual of frame F. Allocate
6969 close colors. Return colors allocated. */
6970 bzero (&attrs
, sizeof attrs
);
6971 attrs
.visual
= FRAME_X_DISPLAY_INFO (f
)->visual
;
6972 attrs
.valuemask
|= XpmVisual
;
6973 attrs
.valuemask
|= XpmReturnAllocPixels
;
6974 attrs
.alloc_close_colors
= 1;
6975 attrs
.valuemask
|= XpmAllocCloseColors
;
6977 /* If image specification contains symbolic color definitions, add
6978 these to `attrs'. */
6979 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
6980 if (CONSP (color_symbols
))
6983 XpmColorSymbol
*xpm_syms
;
6986 attrs
.valuemask
|= XpmColorSymbols
;
6988 /* Count number of symbols. */
6989 attrs
.numsymbols
= 0;
6990 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
6993 /* Allocate an XpmColorSymbol array. */
6994 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
6995 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
6996 bzero (xpm_syms
, size
);
6997 attrs
.colorsymbols
= xpm_syms
;
6999 /* Fill the color symbol array. */
7000 for (tail
= color_symbols
, i
= 0;
7002 ++i
, tail
= XCDR (tail
))
7004 Lisp_Object name
= XCAR (XCAR (tail
));
7005 Lisp_Object color
= XCDR (XCAR (tail
));
7006 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7007 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7008 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7009 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7013 /* Create a pixmap for the image, either from a file, or from a
7014 string buffer containing data in the same format as an XPM file. */
7016 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7017 if (STRINGP (specified_file
))
7019 Lisp_Object file
= x_find_image_file (specified_file
);
7020 if (!STRINGP (file
))
7022 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7026 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7027 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7032 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7033 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7034 XSTRING (buffer
)->data
,
7035 &img
->pixmap
, &img
->mask
,
7040 if (rc
== XpmSuccess
)
7042 /* Remember allocated colors. */
7043 img
->ncolors
= attrs
.nalloc_pixels
;
7044 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7045 * sizeof *img
->colors
);
7046 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7047 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7049 img
->width
= attrs
.width
;
7050 img
->height
= attrs
.height
;
7051 xassert (img
->width
> 0 && img
->height
> 0);
7053 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7055 XpmFreeAttributes (&attrs
);
7063 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7066 case XpmFileInvalid
:
7067 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7071 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7074 case XpmColorFailed
:
7075 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7079 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7084 return rc
== XpmSuccess
;
7087 #endif /* HAVE_XPM != 0 */
7090 /***********************************************************************
7092 ***********************************************************************/
7094 /* An entry in the color table mapping an RGB color to a pixel color. */
7099 unsigned long pixel
;
7101 /* Next in color table collision list. */
7102 struct ct_color
*next
;
7105 /* The bucket vector size to use. Must be prime. */
7109 /* Value is a hash of the RGB color given by R, G, and B. */
7111 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7113 /* The color hash table. */
7115 struct ct_color
**ct_table
;
7117 /* Number of entries in the color table. */
7119 int ct_colors_allocated
;
7121 /* Function prototypes. */
7123 static void init_color_table
P_ ((void));
7124 static void free_color_table
P_ ((void));
7125 static unsigned long *colors_in_color_table
P_ ((int *n
));
7126 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
7127 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
7130 /* Initialize the color table. */
7135 int size
= CT_SIZE
* sizeof (*ct_table
);
7136 ct_table
= (struct ct_color
**) xmalloc (size
);
7137 bzero (ct_table
, size
);
7138 ct_colors_allocated
= 0;
7142 /* Free memory associated with the color table. */
7148 struct ct_color
*p
, *next
;
7150 for (i
= 0; i
< CT_SIZE
; ++i
)
7151 for (p
= ct_table
[i
]; p
; p
= next
)
7162 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7163 entry for that color already is in the color table, return the
7164 pixel color of that entry. Otherwise, allocate a new color for R,
7165 G, B, and make an entry in the color table. */
7167 static unsigned long
7168 lookup_rgb_color (f
, r
, g
, b
)
7172 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7173 int i
= hash
% CT_SIZE
;
7176 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7177 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7191 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7192 rc
= x_alloc_nearest_color (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN (f
),
7198 ++ct_colors_allocated
;
7200 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7204 p
->pixel
= color
.pixel
;
7205 p
->next
= ct_table
[i
];
7209 return FRAME_FOREGROUND_PIXEL (f
);
7216 /* Look up pixel color PIXEL which is used on frame F in the color
7217 table. If not already present, allocate it. Value is PIXEL. */
7219 static unsigned long
7220 lookup_pixel_color (f
, pixel
)
7222 unsigned long pixel
;
7224 int i
= pixel
% CT_SIZE
;
7227 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7228 if (p
->pixel
== pixel
)
7239 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7240 color
.pixel
= pixel
;
7241 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7242 rc
= x_alloc_nearest_color (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN (f
),
7248 ++ct_colors_allocated
;
7250 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7255 p
->next
= ct_table
[i
];
7259 return FRAME_FOREGROUND_PIXEL (f
);
7266 /* Value is a vector of all pixel colors contained in the color table,
7267 allocated via xmalloc. Set *N to the number of colors. */
7269 static unsigned long *
7270 colors_in_color_table (n
)
7275 unsigned long *colors
;
7277 if (ct_colors_allocated
== 0)
7284 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7286 *n
= ct_colors_allocated
;
7288 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7289 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7290 colors
[j
++] = p
->pixel
;
7298 /***********************************************************************
7300 ***********************************************************************/
7302 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7303 int, XImage
*, int));
7304 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7305 XColor
*, int, XImage
*, int));
7308 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7309 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7310 the width of one row in the image. */
7313 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
7323 for (x
= 0; x
< width
; ++x
)
7324 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
7326 XQueryColors (FRAME_X_DISPLAY (f
), cmap
, colors
, width
);
7330 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7331 containing the pixel colors to write. F is the frame we are
7335 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
7344 for (x
= 0; x
< width
; ++x
)
7345 XPutPixel (ximg
, x
, y
, pixels
[x
]);
7349 /* Transform image IMG which is used on frame F with a Laplace
7350 edge-detection algorithm. The result is an image that can be used
7351 to draw disabled buttons, for example. */
7358 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7359 XImage
*ximg
, *oimg
;
7365 int in_y
, out_y
, rc
;
7370 /* Get the X image IMG->pixmap. */
7371 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7372 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7374 /* Allocate 3 input rows, and one output row of colors. */
7375 for (i
= 0; i
< 3; ++i
)
7376 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
7377 out
= (long *) alloca (img
->width
* sizeof (long));
7379 /* Create an X image for output. */
7380 rc
= x_create_x_image_and_pixmap (f
, Qnil
, img
->width
, img
->height
, 0,
7383 /* Fill first two rows. */
7384 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
7385 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
7388 /* Write first row, all zeros. */
7389 init_color_table ();
7390 pixel
= lookup_rgb_color (f
, 0, 0, 0);
7391 for (x
= 0; x
< img
->width
; ++x
)
7393 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
7396 for (y
= 2; y
< img
->height
; ++y
)
7399 int rowb
= (y
+ 2) % 3;
7401 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
7403 for (x
= 0; x
< img
->width
- 2; ++x
)
7405 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
7406 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
7407 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
7409 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
7413 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
7416 /* Write last line, all zeros. */
7417 for (x
= 0; x
< img
->width
; ++x
)
7419 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
7421 /* Free the input image, and free resources of IMG. */
7422 XDestroyImage (ximg
);
7423 x_clear_image (f
, img
);
7425 /* Put the output image into pixmap, and destroy it. */
7426 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7427 x_destroy_x_image (oimg
);
7429 /* Remember new pixmap and colors in IMG. */
7430 img
->pixmap
= pixmap
;
7431 img
->colors
= colors_in_color_table (&img
->ncolors
);
7432 free_color_table ();
7438 /* Build a mask for image IMG which is used on frame F. FILE is the
7439 name of an image file, for error messages. HOW determines how to
7440 determine the background color of IMG. If it is an integer, take
7441 that as the pixel value of the background. Otherwise, determine
7442 the background color of IMG heuristically. Value is non-zero
7446 x_build_heuristic_mask (f
, file
, img
, how
)
7452 Display
*dpy
= FRAME_X_DISPLAY (f
);
7453 Window win
= FRAME_X_WINDOW (f
);
7454 XImage
*ximg
, *mask_img
;
7460 /* Create an image and pixmap serving as mask. */
7461 rc
= x_create_x_image_and_pixmap (f
, file
, img
->width
, img
->height
, 1,
7462 &mask_img
, &img
->mask
);
7469 /* Get the X image of IMG->pixmap. */
7470 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7473 /* Determine the background color of ximg. If HOW is an integer,
7474 take that as a pixel color. Otherwise, try to determine the
7475 color heuristically. */
7477 bg
= XFASTINT (how
);
7480 unsigned long corners
[4];
7483 /* Get the colors at the corners of ximg. */
7484 corners
[0] = XGetPixel (ximg
, 0, 0);
7485 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7486 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7487 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7489 /* Choose the most frequently found color as background. */
7490 for (i
= best_count
= 0; i
< 4; ++i
)
7494 for (j
= n
= 0; j
< 4; ++j
)
7495 if (corners
[i
] == corners
[j
])
7499 bg
= corners
[i
], best_count
= n
;
7503 /* Set all bits in mask_img to 1 whose color in ximg is different
7504 from the background color bg. */
7505 for (y
= 0; y
< img
->height
; ++y
)
7506 for (x
= 0; x
< img
->width
; ++x
)
7507 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7509 /* Put mask_img into img->mask. */
7510 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7511 x_destroy_x_image (mask_img
);
7512 XDestroyImage (ximg
);
7520 /***********************************************************************
7521 PBM (mono, gray, color)
7522 ***********************************************************************/
7524 static int pbm_image_p
P_ ((Lisp_Object object
));
7525 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7526 static int pbm_scan_number
P_ ((FILE *fp
));
7528 /* The symbol `pbm' identifying images of this type. */
7532 /* Indices of image specification fields in gs_format, below. */
7534 enum pbm_keyword_index
7546 /* Vector of image_keyword structures describing the format
7547 of valid user-defined image specifications. */
7549 static struct image_keyword pbm_format
[PBM_LAST
] =
7551 {":type", IMAGE_SYMBOL_VALUE
, 1},
7552 {":file", IMAGE_STRING_VALUE
, 1},
7553 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7554 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7555 {":relief", IMAGE_INTEGER_VALUE
, 0},
7556 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7557 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7560 /* Structure describing the image type `pbm'. */
7562 static struct image_type pbm_type
=
7572 /* Return non-zero if OBJECT is a valid PBM image specification. */
7575 pbm_image_p (object
)
7578 struct image_keyword fmt
[PBM_LAST
];
7580 bcopy (pbm_format
, fmt
, sizeof fmt
);
7582 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
, 0)
7583 || (fmt
[PBM_ASCENT
].count
7584 && XFASTINT (fmt
[PBM_ASCENT
].value
) > 100))
7590 /* Scan a decimal number from PBM input file FP and return it. Value
7591 is -1 at end of file or if an error occurs. */
7594 pbm_scan_number (fp
)
7601 /* Skip white-space. */
7602 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
7607 /* Skip comment to end of line. */
7608 while ((c
= fgetc (fp
)) != EOF
&& c
!= '\n')
7611 else if (isdigit (c
))
7613 /* Read decimal number. */
7615 while ((c
= fgetc (fp
)) != EOF
&& isdigit (c
))
7616 val
= 10 * val
+ c
- '0';
7627 /* Load PBM image IMG for use on frame F. */
7637 int width
, height
, max_color_idx
= 0, value
;
7639 Lisp_Object file
, specified_file
;
7640 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
7641 struct gcpro gcpro1
;
7643 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7644 file
= x_find_image_file (specified_file
);
7646 if (!STRINGP (file
))
7648 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7653 fp
= fopen (XSTRING (file
)->data
, "r");
7660 /* Read first two characters. */
7661 if (fread (magic
, sizeof *magic
, 2, fp
) != 2)
7664 image_error ("Not a PBM image file: %s", file
, Qnil
);
7672 image_error ("Not a PBM image file: %s", file
, Qnil
);
7680 raw_p
= 0, type
= PBM_MONO
;
7684 raw_p
= 0, type
= PBM_GRAY
;
7688 raw_p
= 0, type
= PBM_COLOR
;
7692 raw_p
= 1, type
= PBM_MONO
;
7696 raw_p
= 1, type
= PBM_GRAY
;
7700 raw_p
= 1, type
= PBM_COLOR
;
7705 image_error ("Not a PBM image file: %s", file
, Qnil
);
7710 /* Read width, height, maximum color-component. Characters
7711 starting with `#' up to the end of a line are ignored. */
7712 width
= pbm_scan_number (fp
);
7713 height
= pbm_scan_number (fp
);
7715 if (type
!= PBM_MONO
)
7717 max_color_idx
= pbm_scan_number (fp
);
7718 if (raw_p
&& max_color_idx
> 255)
7719 max_color_idx
= 255;
7722 if (width
< 0 || height
< 0
7723 || (type
!= PBM_MONO
&& max_color_idx
< 0))
7731 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0,
7732 &ximg
, &img
->pixmap
))
7740 /* Initialize the color hash table. */
7741 init_color_table ();
7743 if (type
== PBM_MONO
)
7747 for (y
= 0; y
< height
; ++y
)
7748 for (x
= 0; x
< width
; ++x
)
7758 g
= pbm_scan_number (fp
);
7760 XPutPixel (ximg
, x
, y
, (g
7761 ? FRAME_FOREGROUND_PIXEL (f
)
7762 : FRAME_BACKGROUND_PIXEL (f
)));
7767 for (y
= 0; y
< height
; ++y
)
7768 for (x
= 0; x
< width
; ++x
)
7772 if (type
== PBM_GRAY
)
7773 r
= g
= b
= raw_p
? fgetc (fp
) : pbm_scan_number (fp
);
7782 r
= pbm_scan_number (fp
);
7783 g
= pbm_scan_number (fp
);
7784 b
= pbm_scan_number (fp
);
7787 if (r
< 0 || g
< 0 || b
< 0)
7792 XDestroyImage (ximg
);
7794 image_error ("Invalid pixel value in file `%s'",
7800 /* RGB values are now in the range 0..max_color_idx.
7801 Scale this to the range 0..0xffff supported by X. */
7802 r
= (double) r
* 65535 / max_color_idx
;
7803 g
= (double) g
* 65535 / max_color_idx
;
7804 b
= (double) b
* 65535 / max_color_idx
;
7805 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
7811 /* Store in IMG->colors the colors allocated for the image, and
7812 free the color table. */
7813 img
->colors
= colors_in_color_table (&img
->ncolors
);
7814 free_color_table ();
7816 /* Put the image into a pixmap. */
7817 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7818 x_destroy_x_image (ximg
);
7822 img
->height
= height
;
7830 /***********************************************************************
7832 ***********************************************************************/
7838 /* Function prototypes. */
7840 static int png_image_p
P_ ((Lisp_Object object
));
7841 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
7843 /* The symbol `png' identifying images of this type. */
7847 /* Indices of image specification fields in png_format, below. */
7849 enum png_keyword_index
7861 /* Vector of image_keyword structures describing the format
7862 of valid user-defined image specifications. */
7864 static struct image_keyword png_format
[PNG_LAST
] =
7866 {":type", IMAGE_SYMBOL_VALUE
, 1},
7867 {":file", IMAGE_STRING_VALUE
, 1},
7868 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7869 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7870 {":relief", IMAGE_INTEGER_VALUE
, 0},
7871 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7872 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7875 /* Structure describing the image type `gif'. */
7877 static struct image_type png_type
=
7887 /* Return non-zero if OBJECT is a valid PNG image specification. */
7890 png_image_p (object
)
7893 struct image_keyword fmt
[PNG_LAST
];
7894 bcopy (png_format
, fmt
, sizeof fmt
);
7896 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
, 1)
7897 || (fmt
[PNG_ASCENT
].count
7898 && XFASTINT (fmt
[PNG_ASCENT
].value
) > 100))
7904 /* Error and warning handlers installed when the PNG library
7908 my_png_error (png_ptr
, msg
)
7909 png_struct
*png_ptr
;
7912 xassert (png_ptr
!= NULL
);
7913 image_error ("PNG error: %s", build_string (msg
), Qnil
);
7914 longjmp (png_ptr
->jmpbuf
, 1);
7919 my_png_warning (png_ptr
, msg
)
7920 png_struct
*png_ptr
;
7923 xassert (png_ptr
!= NULL
);
7924 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
7928 /* Load PNG image IMG for use on frame F. Value is non-zero if
7936 Lisp_Object file
, specified_file
;
7938 XImage
*ximg
, *mask_img
= NULL
;
7939 struct gcpro gcpro1
;
7940 png_struct
*png_ptr
= NULL
;
7941 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
7944 png_byte
*pixels
= NULL
;
7945 png_byte
**rows
= NULL
;
7946 png_uint_32 width
, height
;
7947 int bit_depth
, color_type
, interlace_type
;
7949 png_uint_32 row_bytes
;
7952 double screen_gamma
, image_gamma
;
7955 /* Find out what file to load. */
7956 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7957 file
= x_find_image_file (specified_file
);
7959 if (!STRINGP (file
))
7961 image_error ("Cannot find image file %s", specified_file
, Qnil
);
7966 /* Open the image file. */
7967 fp
= fopen (XSTRING (file
)->data
, "rb");
7970 image_error ("Cannot open image file %s", file
, Qnil
);
7976 /* Check PNG signature. */
7977 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
7978 || !png_check_sig (sig
, sizeof sig
))
7980 image_error ("Not a PNG file: %s", file
, Qnil
);
7986 /* Initialize read and info structs for PNG lib. */
7987 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
7988 my_png_error
, my_png_warning
);
7996 info_ptr
= png_create_info_struct (png_ptr
);
7999 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8005 end_info
= png_create_info_struct (png_ptr
);
8008 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8014 /* Set error jump-back. We come back here when the PNG library
8015 detects an error. */
8016 if (setjmp (png_ptr
->jmpbuf
))
8020 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8029 /* Read image info. */
8030 png_init_io (png_ptr
, fp
);
8031 png_set_sig_bytes (png_ptr
, sizeof sig
);
8032 png_read_info (png_ptr
, info_ptr
);
8033 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8034 &interlace_type
, NULL
, NULL
);
8036 /* If image contains simply transparency data, we prefer to
8037 construct a clipping mask. */
8038 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8043 /* This function is easier to write if we only have to handle
8044 one data format: RGB or RGBA with 8 bits per channel. Let's
8045 transform other formats into that format. */
8047 /* Strip more than 8 bits per channel. */
8048 if (bit_depth
== 16)
8049 png_set_strip_16 (png_ptr
);
8051 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8053 png_set_expand (png_ptr
);
8055 /* Convert grayscale images to RGB. */
8056 if (color_type
== PNG_COLOR_TYPE_GRAY
8057 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8058 png_set_gray_to_rgb (png_ptr
);
8060 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8061 gamma_str
= getenv ("SCREEN_GAMMA");
8062 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8064 /* Tell the PNG lib to handle gamma correction for us. */
8066 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8067 /* There is a special chunk in the image specifying the gamma. */
8068 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8069 else if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8070 /* Image contains gamma information. */
8071 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8073 /* Use a default of 0.5 for the image gamma. */
8074 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8076 /* Handle alpha channel by combining the image with a background
8077 color. Do this only if a real alpha channel is supplied. For
8078 simple transparency, we prefer a clipping mask. */
8081 png_color_16
*image_background
;
8083 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8084 /* Image contains a background color with which to
8085 combine the image. */
8086 png_set_background (png_ptr
, image_background
,
8087 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8090 /* Image does not contain a background color with which
8091 to combine the image data via an alpha channel. Use
8092 the frame's background instead. */
8095 png_color_16 frame_background
;
8098 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
8099 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8100 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
8103 bzero (&frame_background
, sizeof frame_background
);
8104 frame_background
.red
= color
.red
;
8105 frame_background
.green
= color
.green
;
8106 frame_background
.blue
= color
.blue
;
8108 png_set_background (png_ptr
, &frame_background
,
8109 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8113 /* Update info structure. */
8114 png_read_update_info (png_ptr
, info_ptr
);
8116 /* Get number of channels. Valid values are 1 for grayscale images
8117 and images with a palette, 2 for grayscale images with transparency
8118 information (alpha channel), 3 for RGB images, and 4 for RGB
8119 images with alpha channel, i.e. RGBA. If conversions above were
8120 sufficient we should only have 3 or 4 channels here. */
8121 channels
= png_get_channels (png_ptr
, info_ptr
);
8122 xassert (channels
== 3 || channels
== 4);
8124 /* Number of bytes needed for one row of the image. */
8125 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8127 /* Allocate memory for the image. */
8128 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8129 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8130 for (i
= 0; i
< height
; ++i
)
8131 rows
[i
] = pixels
+ i
* row_bytes
;
8133 /* Read the entire image. */
8134 png_read_image (png_ptr
, rows
);
8135 png_read_end (png_ptr
, info_ptr
);
8141 /* Create the X image and pixmap. */
8142 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8149 /* Create an image and pixmap serving as mask if the PNG image
8150 contains an alpha channel. */
8153 && !x_create_x_image_and_pixmap (f
, file
, width
, height
, 1,
8154 &mask_img
, &img
->mask
))
8156 x_destroy_x_image (ximg
);
8157 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8163 /* Fill the X image and mask from PNG data. */
8164 init_color_table ();
8166 for (y
= 0; y
< height
; ++y
)
8168 png_byte
*p
= rows
[y
];
8170 for (x
= 0; x
< width
; ++x
)
8177 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8179 /* An alpha channel, aka mask channel, associates variable
8180 transparency with an image. Where other image formats
8181 support binary transparency---fully transparent or fully
8182 opaque---PNG allows up to 254 levels of partial transparency.
8183 The PNG library implements partial transparency by combining
8184 the image with a specified background color.
8186 I'm not sure how to handle this here nicely: because the
8187 background on which the image is displayed may change, for
8188 real alpha channel support, it would be necessary to create
8189 a new image for each possible background.
8191 What I'm doing now is that a mask is created if we have
8192 boolean transparency information. Otherwise I'm using
8193 the frame's background color to combine the image with. */
8198 XPutPixel (mask_img
, x
, y
, *p
> 0);
8204 /* Remember colors allocated for this image. */
8205 img
->colors
= colors_in_color_table (&img
->ncolors
);
8206 free_color_table ();
8209 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8214 img
->height
= height
;
8216 /* Put the image into the pixmap, then free the X image and its buffer. */
8217 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8218 x_destroy_x_image (ximg
);
8220 /* Same for the mask. */
8223 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8224 x_destroy_x_image (mask_img
);
8232 #endif /* HAVE_PNG != 0 */
8236 /***********************************************************************
8238 ***********************************************************************/
8242 #include <jpeglib.h>
8246 static int jpeg_image_p
P_ ((Lisp_Object object
));
8247 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8249 /* The symbol `jpeg' identifying images of this type. */
8253 /* Indices of image specification fields in gs_format, below. */
8255 enum jpeg_keyword_index
8263 JPEG_HEURISTIC_MASK
,
8267 /* Vector of image_keyword structures describing the format
8268 of valid user-defined image specifications. */
8270 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8272 {":type", IMAGE_SYMBOL_VALUE
, 1},
8273 {":file", IMAGE_STRING_VALUE
, 1},
8274 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8275 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8276 {":relief", IMAGE_INTEGER_VALUE
, 0},
8277 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8278 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8281 /* Structure describing the image type `jpeg'. */
8283 static struct image_type jpeg_type
=
8293 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8296 jpeg_image_p (object
)
8299 struct image_keyword fmt
[JPEG_LAST
];
8301 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8303 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
, 0)
8304 || (fmt
[JPEG_ASCENT
].count
8305 && XFASTINT (fmt
[JPEG_ASCENT
].value
) > 100))
8310 struct my_jpeg_error_mgr
8312 struct jpeg_error_mgr pub
;
8313 jmp_buf setjmp_buffer
;
8317 my_error_exit (cinfo
)
8320 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8321 longjmp (mgr
->setjmp_buffer
, 1);
8324 /* Load image IMG for use on frame F. Patterned after example.c
8325 from the JPEG lib. */
8332 struct jpeg_decompress_struct cinfo
;
8333 struct my_jpeg_error_mgr mgr
;
8334 Lisp_Object file
, specified_file
;
8337 int row_stride
, x
, y
;
8338 XImage
*ximg
= NULL
;
8340 unsigned long *colors
;
8342 struct gcpro gcpro1
;
8344 /* Open the JPEG file. */
8345 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8346 file
= x_find_image_file (specified_file
);
8348 if (!STRINGP (file
))
8350 image_error ("Cannot find image file %s", specified_file
, Qnil
);
8355 fp
= fopen (XSTRING (file
)->data
, "r");
8358 image_error ("Cannot open `%s'", file
, Qnil
);
8363 /* Customize libjpeg's error handling to call my_error_exit
8364 when an error is detected. This function will perform
8366 mgr
.pub
.error_exit
= my_error_exit
;
8367 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8369 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8373 /* Called from my_error_exit. Display a JPEG error. */
8374 char buffer
[JMSG_LENGTH_MAX
];
8375 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8376 image_error ("Error reading JPEG file `%s': %s", file
,
8377 build_string (buffer
));
8380 /* Close the input file and destroy the JPEG object. */
8382 jpeg_destroy_decompress (&cinfo
);
8386 /* If we already have an XImage, free that. */
8387 x_destroy_x_image (ximg
);
8389 /* Free pixmap and colors. */
8390 x_clear_image (f
, img
);
8397 /* Create the JPEG decompression object. Let it read from fp.
8398 Read the JPEG image header. */
8399 jpeg_create_decompress (&cinfo
);
8400 jpeg_stdio_src (&cinfo
, fp
);
8401 jpeg_read_header (&cinfo
, TRUE
);
8403 /* Customize decompression so that color quantization will be used.
8404 Start decompression. */
8405 cinfo
.quantize_colors
= TRUE
;
8406 jpeg_start_decompress (&cinfo
);
8407 width
= img
->width
= cinfo
.output_width
;
8408 height
= img
->height
= cinfo
.output_height
;
8412 /* Create X image and pixmap. */
8413 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8417 longjmp (mgr
.setjmp_buffer
, 2);
8420 /* Allocate colors. When color quantization is used,
8421 cinfo.actual_number_of_colors has been set with the number of
8422 colors generated, and cinfo.colormap is a two-dimensional array
8423 of color indices in the range 0..cinfo.actual_number_of_colors.
8424 No more than 255 colors will be generated. */
8428 if (cinfo
.out_color_components
> 2)
8429 ir
= 0, ig
= 1, ib
= 2;
8430 else if (cinfo
.out_color_components
> 1)
8431 ir
= 0, ig
= 1, ib
= 0;
8433 ir
= 0, ig
= 0, ib
= 0;
8435 /* Use the color table mechanism because it handles colors that
8436 cannot be allocated nicely. Such colors will be replaced with
8437 a default color, and we don't have to care about which colors
8438 can be freed safely, and which can't. */
8439 init_color_table ();
8440 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8443 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8445 /* Multiply RGB values with 255 because X expects RGB values
8446 in the range 0..0xffff. */
8447 int r
= cinfo
.colormap
[ir
][i
] << 8;
8448 int g
= cinfo
.colormap
[ig
][i
] << 8;
8449 int b
= cinfo
.colormap
[ib
][i
] << 8;
8450 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8453 /* Remember those colors actually allocated. */
8454 img
->colors
= colors_in_color_table (&img
->ncolors
);
8455 free_color_table ();
8459 row_stride
= width
* cinfo
.output_components
;
8460 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
8462 for (y
= 0; y
< height
; ++y
)
8464 jpeg_read_scanlines (&cinfo
, buffer
, 1);
8465 for (x
= 0; x
< cinfo
.output_width
; ++x
)
8466 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
8470 jpeg_finish_decompress (&cinfo
);
8471 jpeg_destroy_decompress (&cinfo
);
8474 /* Put the image into the pixmap. */
8475 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8476 x_destroy_x_image (ximg
);
8482 #endif /* HAVE_JPEG */
8486 /***********************************************************************
8488 ***********************************************************************/
8492 #include <tiff34/tiffio.h>
8494 static int tiff_image_p
P_ ((Lisp_Object object
));
8495 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
8497 /* The symbol `tiff' identifying images of this type. */
8501 /* Indices of image specification fields in tiff_format, below. */
8503 enum tiff_keyword_index
8511 TIFF_HEURISTIC_MASK
,
8515 /* Vector of image_keyword structures describing the format
8516 of valid user-defined image specifications. */
8518 static struct image_keyword tiff_format
[TIFF_LAST
] =
8520 {":type", IMAGE_SYMBOL_VALUE
, 1},
8521 {":file", IMAGE_STRING_VALUE
, 1},
8522 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8523 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8524 {":relief", IMAGE_INTEGER_VALUE
, 0},
8525 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8526 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8529 /* Structure describing the image type `tiff'. */
8531 static struct image_type tiff_type
=
8541 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8544 tiff_image_p (object
)
8547 struct image_keyword fmt
[TIFF_LAST
];
8548 bcopy (tiff_format
, fmt
, sizeof fmt
);
8550 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
, 1)
8551 || (fmt
[TIFF_ASCENT
].count
8552 && XFASTINT (fmt
[TIFF_ASCENT
].value
) > 100))
8558 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8566 Lisp_Object file
, specified_file
;
8568 int width
, height
, x
, y
;
8572 struct gcpro gcpro1
;
8574 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8575 file
= x_find_image_file (specified_file
);
8577 if (!STRINGP (file
))
8579 image_error ("Cannot find image file %s", file
, Qnil
);
8584 /* Try to open the image file. */
8585 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
8588 image_error ("Cannot open `%s'", file
, Qnil
);
8593 /* Get width and height of the image, and allocate a raster buffer
8594 of width x height 32-bit values. */
8595 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
8596 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
8597 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8599 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8603 image_error ("Error reading `%s'", file
, Qnil
);
8611 /* Create the X image and pixmap. */
8612 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8621 /* Initialize the color table. */
8622 init_color_table ();
8624 /* Process the pixel raster. Origin is in the lower-left corner. */
8625 for (y
= 0; y
< height
; ++y
)
8627 uint32
*row
= buf
+ y
* width
;
8629 for (x
= 0; x
< width
; ++x
)
8631 uint32 abgr
= row
[x
];
8632 int r
= TIFFGetR (abgr
) << 8;
8633 int g
= TIFFGetG (abgr
) << 8;
8634 int b
= TIFFGetB (abgr
) << 8;
8635 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
8639 /* Remember the colors allocated for the image. Free the color table. */
8640 img
->colors
= colors_in_color_table (&img
->ncolors
);
8641 free_color_table ();
8643 /* Put the image into the pixmap, then free the X image and its buffer. */
8644 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8645 x_destroy_x_image (ximg
);
8650 img
->height
= height
;
8656 #endif /* HAVE_TIFF != 0 */
8660 /***********************************************************************
8662 ***********************************************************************/
8666 #include <gif_lib.h>
8668 static int gif_image_p
P_ ((Lisp_Object object
));
8669 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
8671 /* The symbol `gif' identifying images of this type. */
8675 /* Indices of image specification fields in gif_format, below. */
8677 enum gif_keyword_index
8690 /* Vector of image_keyword structures describing the format
8691 of valid user-defined image specifications. */
8693 static struct image_keyword gif_format
[GIF_LAST
] =
8695 {":type", IMAGE_SYMBOL_VALUE
, 1},
8696 {":file", IMAGE_STRING_VALUE
, 1},
8697 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8698 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8699 {":relief", IMAGE_INTEGER_VALUE
, 0},
8700 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8701 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8702 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
8705 /* Structure describing the image type `gif'. */
8707 static struct image_type gif_type
=
8717 /* Return non-zero if OBJECT is a valid GIF image specification. */
8720 gif_image_p (object
)
8723 struct image_keyword fmt
[GIF_LAST
];
8724 bcopy (gif_format
, fmt
, sizeof fmt
);
8726 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
, 1)
8727 || (fmt
[GIF_ASCENT
].count
8728 && XFASTINT (fmt
[GIF_ASCENT
].value
) > 100))
8734 /* Load GIF image IMG for use on frame F. Value is non-zero if
8742 Lisp_Object file
, specified_file
;
8743 int rc
, width
, height
, x
, y
, i
;
8745 ColorMapObject
*gif_color_map
;
8746 unsigned long pixel_colors
[256];
8748 struct gcpro gcpro1
;
8750 int ino
, image_left
, image_top
, image_width
, image_height
;
8753 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8754 file
= x_find_image_file (specified_file
);
8756 if (!STRINGP (file
))
8758 image_error ("Cannot find image file %s", specified_file
, Qnil
);
8763 /* Open the GIF file. */
8764 gif
= DGifOpenFileName (XSTRING (file
)->data
);
8767 image_error ("Cannot open `%s'", file
, Qnil
);
8772 /* Read entire contents. */
8773 rc
= DGifSlurp (gif
);
8774 if (rc
== GIF_ERROR
)
8776 image_error ("Error reading `%s'", file
, Qnil
);
8777 DGifCloseFile (gif
);
8782 image
= image_spec_value (img
->spec
, QCimage
, NULL
);
8783 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8784 if (ino
>= gif
->ImageCount
)
8786 image_error ("Invalid image number `%s'", image
, Qnil
);
8787 DGifCloseFile (gif
);
8792 width
= img
->width
= gif
->SWidth
;
8793 height
= img
->height
= gif
->SHeight
;
8797 /* Create the X image and pixmap. */
8798 if (!x_create_x_image_and_pixmap (f
, file
, width
, height
, 0, &ximg
,
8802 DGifCloseFile (gif
);
8807 /* Allocate colors. */
8808 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8810 gif_color_map
= gif
->SColorMap
;
8811 init_color_table ();
8812 bzero (pixel_colors
, sizeof pixel_colors
);
8814 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8816 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8817 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8818 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8819 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8822 img
->colors
= colors_in_color_table (&img
->ncolors
);
8823 free_color_table ();
8825 /* Clear the part of the screen image that are not covered by
8826 the image from the GIF file. Full animated GIF support
8827 requires more than can be done here (see the gif89 spec,
8828 disposal methods). Let's simply assume that the part
8829 not covered by a sub-image is in the frame's background color. */
8830 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
8831 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
8832 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8833 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8835 for (y
= 0; y
< image_top
; ++y
)
8836 for (x
= 0; x
< width
; ++x
)
8837 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8839 for (y
= image_top
+ image_height
; y
< height
; ++y
)
8840 for (x
= 0; x
< width
; ++x
)
8841 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8843 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
8845 for (x
= 0; x
< image_left
; ++x
)
8846 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8847 for (x
= image_left
+ image_width
; x
< width
; ++x
)
8848 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8851 /* Read the GIF image into the X image. */
8852 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8854 static int interlace_start
[] = {0, 4, 2, 1};
8855 static int interlace_increment
[] = {8, 8, 4, 2};
8858 for (pass
= 0; pass
< 4; ++pass
)
8860 inc
= interlace_increment
[pass
];
8861 for (y
= interlace_start
[pass
]; y
< image_height
; y
+= inc
)
8862 for (x
= 0; x
< image_width
; ++x
)
8864 unsigned i
= gif
->SavedImages
[ino
].RasterBits
[y
* image_width
+ x
];
8865 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
,
8872 for (y
= 0; y
< image_height
; ++y
)
8873 for (x
= 0; x
< image_width
; ++x
)
8875 unsigned i
= gif
->SavedImages
[ino
].RasterBits
[y
* image_width
+ x
];
8876 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
8880 DGifCloseFile (gif
);
8882 /* Put the image into the pixmap, then free the X image and its buffer. */
8883 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8884 x_destroy_x_image (ximg
);
8891 #endif /* HAVE_GIF != 0 */
8895 /***********************************************************************
8897 ***********************************************************************/
8899 static int gs_image_p
P_ ((Lisp_Object object
));
8900 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8901 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8903 /* The symbol `ghostscript' identifying images of this type. */
8905 Lisp_Object Qghostscript
;
8907 /* Keyword symbols. */
8909 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8911 /* Indices of image specification fields in gs_format, below. */
8913 enum gs_keyword_index
8929 /* Vector of image_keyword structures describing the format
8930 of valid user-defined image specifications. */
8932 static struct image_keyword gs_format
[GS_LAST
] =
8934 {":type", IMAGE_SYMBOL_VALUE
, 1},
8935 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8936 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8937 {":file", IMAGE_STRING_VALUE
, 1},
8938 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8939 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8940 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8941 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8942 {":relief", IMAGE_INTEGER_VALUE
, 0},
8943 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8944 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8947 /* Structure describing the image type `ghostscript'. */
8949 static struct image_type gs_type
=
8959 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8962 gs_clear_image (f
, img
)
8966 /* IMG->data.ptr_val may contain a recorded colormap. */
8967 xfree (img
->data
.ptr_val
);
8968 x_clear_image (f
, img
);
8972 /* Return non-zero if OBJECT is a valid Ghostscript image
8979 struct image_keyword fmt
[GS_LAST
];
8983 bcopy (gs_format
, fmt
, sizeof fmt
);
8985 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qghostscript
, 1)
8986 || (fmt
[GS_ASCENT
].count
8987 && XFASTINT (fmt
[GS_ASCENT
].value
) > 100))
8990 /* Bounding box must be a list or vector containing 4 integers. */
8991 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8994 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8995 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9000 else if (VECTORP (tem
))
9002 if (XVECTOR (tem
)->size
!= 4)
9004 for (i
= 0; i
< 4; ++i
)
9005 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9015 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9024 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9025 struct gcpro gcpro1
, gcpro2
;
9027 double in_width
, in_height
;
9028 Lisp_Object pixel_colors
= Qnil
;
9030 /* Compute pixel size of pixmap needed from the given size in the
9031 image specification. Sizes in the specification are in pt. 1 pt
9032 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9034 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9035 in_width
= XFASTINT (pt_width
) / 72.0;
9036 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9037 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9038 in_height
= XFASTINT (pt_height
) / 72.0;
9039 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9041 /* Create the pixmap. */
9043 xassert (img
->pixmap
== 0);
9044 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9045 img
->width
, img
->height
,
9046 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9051 image_error ("Unable to create pixmap for `%s'",
9052 image_spec_value (img
->spec
, QCfile
, NULL
), Qnil
);
9056 /* Call the loader to fill the pixmap. It returns a process object
9057 if successful. We do not record_unwind_protect here because
9058 other places in redisplay like calling window scroll functions
9059 don't either. Let the Lisp loader use `unwind-protect' instead. */
9060 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9062 sprintf (buffer
, "%lu %lu",
9063 (unsigned long) FRAME_X_WINDOW (f
),
9064 (unsigned long) img
->pixmap
);
9065 window_and_pixmap_id
= build_string (buffer
);
9067 sprintf (buffer
, "%lu %lu",
9068 FRAME_FOREGROUND_PIXEL (f
),
9069 FRAME_BACKGROUND_PIXEL (f
));
9070 pixel_colors
= build_string (buffer
);
9072 XSETFRAME (frame
, f
);
9073 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9075 loader
= intern ("gs-load-image");
9077 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9078 make_number (img
->width
),
9079 make_number (img
->height
),
9080 window_and_pixmap_id
,
9083 return PROCESSP (img
->data
.lisp_val
);
9087 /* Kill the Ghostscript process that was started to fill PIXMAP on
9088 frame F. Called from XTread_socket when receiving an event
9089 telling Emacs that Ghostscript has finished drawing. */
9092 x_kill_gs_process (pixmap
, f
)
9096 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9100 /* Find the image containing PIXMAP. */
9101 for (i
= 0; i
< c
->used
; ++i
)
9102 if (c
->images
[i
]->pixmap
== pixmap
)
9105 /* Kill the GS process. We should have found PIXMAP in the image
9106 cache and its image should contain a process object. */
9107 xassert (i
< c
->used
);
9109 xassert (PROCESSP (img
->data
.lisp_val
));
9110 Fkill_process (img
->data
.lisp_val
, Qnil
);
9111 img
->data
.lisp_val
= Qnil
;
9113 /* On displays with a mutable colormap, figure out the colors
9114 allocated for the image by looking at the pixels of an XImage for
9116 class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
9117 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9123 /* Try to get an XImage for img->pixmep. */
9124 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9125 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9130 /* Initialize the color table. */
9131 init_color_table ();
9133 /* For each pixel of the image, look its color up in the
9134 color table. After having done so, the color table will
9135 contain an entry for each color used by the image. */
9136 for (y
= 0; y
< img
->height
; ++y
)
9137 for (x
= 0; x
< img
->width
; ++x
)
9139 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9140 lookup_pixel_color (f
, pixel
);
9143 /* Record colors in the image. Free color table and XImage. */
9144 img
->colors
= colors_in_color_table (&img
->ncolors
);
9145 free_color_table ();
9146 XDestroyImage (ximg
);
9148 #if 0 /* This doesn't seem to be the case. If we free the colors
9149 here, we get a BadAccess later in x_clear_image when
9150 freeing the colors. */
9151 /* We have allocated colors once, but Ghostscript has also
9152 allocated colors on behalf of us. So, to get the
9153 reference counts right, free them once. */
9156 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9157 XFreeColors (FRAME_X_DISPLAY (f
), cmap
,
9158 img
->colors
, img
->ncolors
, 0);
9163 image_error ("Cannot get X image of `%s'; colors will not be freed",
9164 image_spec_value (img
->spec
, QCfile
, NULL
), Qnil
);
9172 /***********************************************************************
9174 ***********************************************************************/
9176 DEFUN ("x-change-window-property", Fx_change_window_property
,
9177 Sx_change_window_property
, 2, 3, 0,
9178 "Change window property PROP to VALUE on the X window of FRAME.\n\
9179 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9180 selected frame. Value is VALUE.")
9181 (prop
, value
, frame
)
9182 Lisp_Object frame
, prop
, value
;
9184 struct frame
*f
= check_x_frame (frame
);
9187 CHECK_STRING (prop
, 1);
9188 CHECK_STRING (value
, 2);
9191 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9192 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9193 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9194 XSTRING (value
)->data
, XSTRING (value
)->size
);
9196 /* Make sure the property is set when we return. */
9197 XFlush (FRAME_X_DISPLAY (f
));
9204 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9205 Sx_delete_window_property
, 1, 2, 0,
9206 "Remove window property PROP from X window of FRAME.\n\
9207 FRAME nil or omitted means use the selected frame. Value is PROP.")
9209 Lisp_Object prop
, frame
;
9211 struct frame
*f
= check_x_frame (frame
);
9214 CHECK_STRING (prop
, 1);
9216 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9217 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9219 /* Make sure the property is removed when we return. */
9220 XFlush (FRAME_X_DISPLAY (f
));
9227 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9229 "Value is the value of window property PROP on FRAME.\n\
9230 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9231 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9234 Lisp_Object prop
, frame
;
9236 struct frame
*f
= check_x_frame (frame
);
9239 Lisp_Object prop_value
= Qnil
;
9240 char *tmp_data
= NULL
;
9243 unsigned long actual_size
, bytes_remaining
;
9245 CHECK_STRING (prop
, 1);
9247 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9248 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9249 prop_atom
, 0, 0, False
, XA_STRING
,
9250 &actual_type
, &actual_format
, &actual_size
,
9251 &bytes_remaining
, (unsigned char **) &tmp_data
);
9254 int size
= bytes_remaining
;
9259 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9260 prop_atom
, 0, bytes_remaining
,
9262 &actual_type
, &actual_format
,
9263 &actual_size
, &bytes_remaining
,
9264 (unsigned char **) &tmp_data
);
9266 prop_value
= make_string (tmp_data
, size
);
9277 /***********************************************************************
9279 ***********************************************************************/
9281 /* The implementation partly follows a patch from
9282 F.Pierresteguy@frcl.bull.fr dated 1994. */
9284 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
9285 the next X event is read and we enter XTread_socket again. Setting
9286 it to 1 inhibits busy-cursor display for direct commands. */
9288 int inhibit_busy_cursor
;
9290 /* Incremented with each call to x-display-busy-cursor.
9291 Decremented in x-undisplay-busy-cursor. */
9293 static int busy_count
;
9296 DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor
,
9297 Sx_show_busy_cursor
, 0, 0, 0,
9298 "Show a busy cursor, if not already shown.\n\
9299 Each call to this function must be matched by a call to\n\
9300 x-undisplay-busy-cursor to make the busy pointer disappear again.")
9304 if (busy_count
== 1)
9306 Lisp_Object rest
, frame
;
9308 FOR_EACH_FRAME (rest
, frame
)
9309 if (FRAME_X_P (XFRAME (frame
)))
9311 struct frame
*f
= XFRAME (frame
);
9314 f
->output_data
.x
->busy_p
= 1;
9316 if (!f
->output_data
.x
->busy_window
)
9318 unsigned long mask
= CWCursor
;
9319 XSetWindowAttributes attrs
;
9321 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
9322 f
->output_data
.x
->busy_window
9323 = XCreateWindow (FRAME_X_DISPLAY (f
),
9324 FRAME_OUTER_WINDOW (f
),
9325 0, 0, 32000, 32000, 0, 0,
9326 InputOnly
, CopyFromParent
,
9330 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9339 DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor
,
9340 Sx_hide_busy_cursor
, 0, 1, 0,
9341 "Hide a busy-cursor.\n\
9342 A busy-cursor will actually be undisplayed when a matching\n\
9343 `x-undisplay-busy-cursor' is called for each `x-display-busy-cursor'\n\
9344 issued. FORCE non-nil means undisplay the busy-cursor forcibly,\n\
9345 not counting calls.")
9349 Lisp_Object rest
, frame
;
9351 if (busy_count
== 0)
9354 if (!NILP (force
) && busy_count
!= 0)
9358 if (busy_count
!= 0)
9361 FOR_EACH_FRAME (rest
, frame
)
9363 struct frame
*f
= XFRAME (frame
);
9366 /* Watch out for newly created frames. */
9367 && f
->output_data
.x
->busy_window
)
9371 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9372 /* Sync here because XTread_socket looks at the busy_p flag
9373 that is reset to zero below. */
9374 XSync (FRAME_X_DISPLAY (f
), False
);
9376 f
->output_data
.x
->busy_p
= 0;
9385 /***********************************************************************
9387 ***********************************************************************/
9389 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
9392 /* The frame of a currently visible tooltip, or null. */
9394 struct frame
*tip_frame
;
9396 /* If non-nil, a timer started that hides the last tooltip when it
9399 Lisp_Object tip_timer
;
9402 /* Create a frame for a tooltip on the display described by DPYINFO.
9403 PARMS is a list of frame parameters. Value is the frame. */
9406 x_create_tip_frame (dpyinfo
, parms
)
9407 struct x_display_info
*dpyinfo
;
9411 Lisp_Object frame
, tem
;
9413 int minibuffer_only
= 0;
9414 long window_prompting
= 0;
9416 int count
= specpdl_ptr
- specpdl
;
9417 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
9422 /* Use this general default value to start with until we know if
9423 this frame has a specified name. */
9424 Vx_resource_name
= Vinvocation_name
;
9427 kb
= dpyinfo
->kboard
;
9429 kb
= &the_only_kboard
;
9432 /* Get the name of the frame to use for resource lookup. */
9433 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
9435 && !EQ (name
, Qunbound
)
9437 error ("Invalid frame name--not a string or nil");
9438 Vx_resource_name
= name
;
9441 GCPRO3 (parms
, name
, frame
);
9442 tip_frame
= f
= make_frame (1);
9443 XSETFRAME (frame
, f
);
9444 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
9446 f
->output_method
= output_x_window
;
9447 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
9448 bzero (f
->output_data
.x
, sizeof (struct x_output
));
9449 f
->output_data
.x
->icon_bitmap
= -1;
9450 f
->output_data
.x
->fontset
= -1;
9451 f
->icon_name
= Qnil
;
9452 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
9454 FRAME_KBOARD (f
) = kb
;
9456 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9457 f
->output_data
.x
->explicit_parent
= 0;
9459 /* Set the name; the functions to which we pass f expect the name to
9461 if (EQ (name
, Qunbound
) || NILP (name
))
9463 f
->name
= build_string (dpyinfo
->x_id_name
);
9464 f
->explicit_name
= 0;
9469 f
->explicit_name
= 1;
9470 /* use the frame's title when getting resources for this frame. */
9471 specbind (Qx_resource_name
, name
);
9474 /* Create fontsets from `global_fontset_alist' before handling fonts. */
9475 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
9476 fs_register_fontset (f
, XCONS (tem
)->car
);
9478 /* Extract the window parameters from the supplied values
9479 that are needed to determine window geometry. */
9483 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
9486 /* First, try whatever font the caller has specified. */
9489 tem
= Fquery_fontset (font
, Qnil
);
9491 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
9493 font
= x_new_font (f
, XSTRING (font
)->data
);
9496 /* Try out a font which we hope has bold and italic variations. */
9497 if (!STRINGP (font
))
9498 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9499 if (!STRINGP (font
))
9500 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9501 if (! STRINGP (font
))
9502 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9503 if (! STRINGP (font
))
9504 /* This was formerly the first thing tried, but it finds too many fonts
9505 and takes too long. */
9506 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9507 /* If those didn't work, look for something which will at least work. */
9508 if (! STRINGP (font
))
9509 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9511 if (! STRINGP (font
))
9512 font
= build_string ("fixed");
9514 x_default_parameter (f
, parms
, Qfont
, font
,
9515 "font", "Font", RES_TYPE_STRING
);
9518 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
9519 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
9521 /* This defaults to 2 in order to match xterm. We recognize either
9522 internalBorderWidth or internalBorder (which is what xterm calls
9524 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9528 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
9529 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
9530 if (! EQ (value
, Qunbound
))
9531 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
9535 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
9536 "internalBorderWidth", "internalBorderWidth",
9539 /* Also do the stuff which must be set before the window exists. */
9540 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
9541 "foreground", "Foreground", RES_TYPE_STRING
);
9542 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
9543 "background", "Background", RES_TYPE_STRING
);
9544 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
9545 "pointerColor", "Foreground", RES_TYPE_STRING
);
9546 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
9547 "cursorColor", "Foreground", RES_TYPE_STRING
);
9548 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
9549 "borderColor", "BorderColor", RES_TYPE_STRING
);
9551 /* Init faces before x_default_parameter is called for scroll-bar
9552 parameters because that function calls x_set_scroll_bar_width,
9553 which calls change_frame_size, which calls Fset_window_buffer,
9554 which runs hooks, which call Fvertical_motion. At the end, we
9555 end up in init_iterator with a null face cache, which should not
9557 init_frame_faces (f
);
9559 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9560 window_prompting
= x_figure_window_size (f
, parms
);
9562 if (window_prompting
& XNegative
)
9564 if (window_prompting
& YNegative
)
9565 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
9567 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
9571 if (window_prompting
& YNegative
)
9572 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
9574 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9577 f
->output_data
.x
->size_hint_flags
= window_prompting
;
9579 XSetWindowAttributes attrs
;
9583 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
9584 /* Window managers looks at the override-redirect flag to
9585 determine whether or net to give windows a decoration (Xlib
9587 attrs
.override_redirect
= True
;
9588 attrs
.save_under
= True
;
9589 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
9590 /* Arrange for getting MapNotify and UnmapNotify events. */
9591 attrs
.event_mask
= StructureNotifyMask
;
9593 = FRAME_X_WINDOW (f
)
9594 = XCreateWindow (FRAME_X_DISPLAY (f
),
9595 FRAME_X_DISPLAY_INFO (f
)->root_window
,
9596 /* x, y, width, height */
9600 CopyFromParent
, InputOutput
, CopyFromParent
,
9607 /* We need to do this after creating the X window, so that the
9608 icon-creation functions can say whose icon they're describing. */
9609 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
9610 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
9612 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
9613 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9614 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
9615 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9616 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
9617 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
9619 /* Dimensions, especially f->height, must be done via change_frame_size.
9620 Change will not be effected unless different from the current
9625 SET_FRAME_WIDTH (f
, 0);
9626 change_frame_size (f
, height
, width
, 1, 0);
9632 /* It is now ok to make the frame official even if we get an error
9633 below. And the frame needs to be on Vframe_list or making it
9634 visible won't work. */
9635 Vframe_list
= Fcons (frame
, Vframe_list
);
9637 /* Now that the frame is official, it counts as a reference to
9639 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
9641 return unbind_to (count
, frame
);
9645 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 4, 0,
9646 "Show tooltip STRING on frame FRAME.\n\
9647 FRAME nil or omitted means use the selected frame.\n\
9648 PARMS is an optional list of frame parameters which can be\n\
9649 used to change the tooltip's appearance.\n\
9650 Automatically hide the tooltip after TIMEOUT seconds.\n\
9651 TIMEOUT nil means use the default timeout of 5 seconds.")
9652 (string
, frame
, parms
, timeout
)
9653 Lisp_Object string
, frame
, parms
;
9660 struct buffer
*old_buffer
;
9661 struct text_pos pos
;
9662 int i
, width
, height
;
9663 int root_x
, root_y
, win_x
, win_y
;
9665 struct gcpro gcpro1
, gcpro2
, gcpro3
;
9666 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
9667 int count
= specpdl_ptr
- specpdl
;
9669 specbind (Qinhibit_redisplay
, Qt
);
9671 GCPRO3 (string
, parms
, frame
);
9673 CHECK_STRING (string
, 0);
9674 f
= check_x_frame (frame
);
9676 timeout
= make_number (5);
9678 CHECK_NATNUM (timeout
, 2);
9680 /* Hide a previous tip, if any. */
9683 /* Add default values to frame parameters. */
9684 if (NILP (Fassq (Qname
, parms
)))
9685 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
9686 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9687 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
9688 if (NILP (Fassq (Qborder_width
, parms
)))
9689 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
9690 if (NILP (Fassq (Qborder_color
, parms
)))
9691 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
9692 if (NILP (Fassq (Qbackground_color
, parms
)))
9693 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
9696 /* Create a frame for the tooltip, and record it in the global
9697 variable tip_frame. */
9698 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
9699 tip_frame
= f
= XFRAME (frame
);
9701 /* Set up the frame's root window. Currently we use a size of 80
9702 columns x 40 lines. If someone wants to show a larger tip, he
9703 will loose. I don't think this is a realistic case. */
9704 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
9705 w
->left
= w
->top
= make_number (0);
9709 w
->pseudo_window_p
= 1;
9711 /* Display the tooltip text in a temporary buffer. */
9712 buffer
= Fget_buffer_create (build_string (" *tip*"));
9713 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
9714 old_buffer
= current_buffer
;
9715 set_buffer_internal_1 (XBUFFER (buffer
));
9717 Finsert (make_number (1), &string
);
9718 clear_glyph_matrix (w
->desired_matrix
);
9719 clear_glyph_matrix (w
->current_matrix
);
9720 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
9721 try_window (FRAME_ROOT_WINDOW (f
), pos
);
9723 /* Compute width and height of the tooltip. */
9725 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
9727 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
9731 /* Stop at the first empty row at the end. */
9732 if (!row
->enabled_p
|| !row
->displays_text_p
)
9735 /* Let the row go over the full width of the frame, not
9736 including internal borders. */
9737 row
->full_width_p
= row
->internal_border_p
= 1;
9739 /* There's a glyph at the end of rows that is use to place
9740 the cursor there. Don't include the width of this glyph. */
9741 if (row
->used
[TEXT_AREA
])
9743 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
9744 row_width
= row
->pixel_width
- last
->pixel_width
;
9747 row_width
= row
->pixel_width
;
9749 height
+= row
->height
;
9750 width
= max (width
, row_width
);
9753 /* Add the frame's internal border to the width and height the X
9754 window should have. */
9755 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9756 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
9758 /* Move the tooltip window where the mouse pointer is. Resize and
9761 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
9762 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
9763 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9764 root_x
+ 5, root_y
- height
- 5, width
, height
);
9765 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9768 /* Draw into the window. */
9769 w
->must_be_updated_p
= 1;
9770 update_single_window (w
, 1);
9772 /* Restore original current buffer. */
9773 set_buffer_internal_1 (old_buffer
);
9774 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
9776 /* Let the tip disappear after timeout seconds. */
9777 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
9778 intern ("x-hide-tip"));
9780 return unbind_to (count
, Qnil
);
9784 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
9785 "Hide the current tooltip, if there is any.\n\
9786 Value is t is tooltip was open, nil otherwise.")
9789 int count
= specpdl_ptr
- specpdl
;
9792 specbind (Qinhibit_redisplay
, Qt
);
9794 if (!NILP (tip_timer
))
9796 call1 (intern ("cancel-timer"), tip_timer
);
9804 XSETFRAME (frame
, tip_frame
);
9805 Fdelete_frame (frame
, Qt
);
9810 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
9815 /***********************************************************************
9816 File selection dialog
9817 ***********************************************************************/
9821 /* Callback for "OK" and "Cancel" on file selection dialog. */
9824 file_dialog_cb (widget
, client_data
, call_data
)
9826 XtPointer call_data
, client_data
;
9828 int *result
= (int *) client_data
;
9829 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
9830 *result
= cb
->reason
;
9834 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
9835 "Read file name, prompting with PROMPT in directory DIR.\n\
9836 Use a file selection dialog.\n\
9837 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
9838 specified. Don't let the user enter a file name in the file\n\
9839 selection dialog's entry field, if MUSTMATCH is non-nil.")
9840 (prompt
, dir
, default_filename
, mustmatch
)
9841 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
9844 struct frame
*f
= selected_frame
;
9845 Lisp_Object file
= Qnil
;
9846 Widget dialog
, text
, list
, help
;
9849 extern XtAppContext Xt_app_con
;
9851 XmString dir_xmstring
, pattern_xmstring
;
9852 int popup_activated_flag
;
9853 int count
= specpdl_ptr
- specpdl
;
9854 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
9856 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
9857 CHECK_STRING (prompt
, 0);
9858 CHECK_STRING (dir
, 1);
9860 /* Prevent redisplay. */
9861 specbind (Qinhibit_redisplay
, Qt
);
9865 /* Create the dialog with PROMPT as title, using DIR as initial
9866 directory and using "*" as pattern. */
9867 dir
= Fexpand_file_name (dir
, Qnil
);
9868 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
9869 pattern_xmstring
= XmStringCreateLocalized ("*");
9871 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
9872 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
9873 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
9874 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
9875 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
9876 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
9878 XmStringFree (dir_xmstring
);
9879 XmStringFree (pattern_xmstring
);
9881 /* Add callbacks for OK and Cancel. */
9882 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
9883 (XtPointer
) &result
);
9884 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
9885 (XtPointer
) &result
);
9887 /* Disable the help button since we can't display help. */
9888 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
9889 XtSetSensitive (help
, False
);
9891 /* Mark OK button as default. */
9892 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
9893 XmNshowAsDefault
, True
, NULL
);
9895 /* If MUSTMATCH is non-nil, disable the file entry field of the
9896 dialog, so that the user must select a file from the files list
9897 box. We can't remove it because we wouldn't have a way to get at
9898 the result file name, then. */
9899 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
9900 if (!NILP (mustmatch
))
9903 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
9904 XtSetSensitive (text
, False
);
9905 XtSetSensitive (label
, False
);
9908 /* Manage the dialog, so that list boxes get filled. */
9909 XtManageChild (dialog
);
9911 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
9912 must include the path for this to work. */
9913 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
9914 if (STRINGP (default_filename
))
9916 XmString default_xmstring
;
9920 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
9922 if (!XmListItemExists (list
, default_xmstring
))
9924 /* Add a new item if DEFAULT_FILENAME is not in the list. */
9925 XmListAddItem (list
, default_xmstring
, 0);
9929 item_pos
= XmListItemPos (list
, default_xmstring
);
9930 XmStringFree (default_xmstring
);
9932 /* Select the item and scroll it into view. */
9933 XmListSelectPos (list
, item_pos
, True
);
9934 XmListSetPos (list
, item_pos
);
9937 /* Process all events until the user presses Cancel or OK. */
9938 for (result
= 0; result
== 0;)
9941 Widget widget
, parent
;
9943 XtAppNextEvent (Xt_app_con
, &event
);
9945 /* See if the receiver of the event is one of the widgets of
9946 the file selection dialog. If so, dispatch it. If not,
9948 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
9950 while (parent
&& parent
!= dialog
)
9951 parent
= XtParent (parent
);
9953 if (parent
== dialog
9954 || (event
.type
== Expose
9955 && !process_expose_from_menu (event
)))
9956 XtDispatchEvent (&event
);
9959 /* Get the result. */
9960 if (result
== XmCR_OK
)
9965 XtVaGetValues (dialog
, XmNtextString
, &text
, 0);
9966 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
9967 XmStringFree (text
);
9968 file
= build_string (data
);
9975 XtUnmanageChild (dialog
);
9976 XtDestroyWidget (dialog
);
9980 /* Make "Cancel" equivalent to C-g. */
9982 Fsignal (Qquit
, Qnil
);
9984 return unbind_to (count
, file
);
9987 #endif /* USE_MOTIF */
9990 /***********************************************************************
9992 ***********************************************************************/
9996 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9997 "Value is non-nil if SPEC is a valid image specification.")
10001 return valid_image_p (spec
) ? Qt
: Qnil
;
10005 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
10011 if (valid_image_p (spec
))
10012 id
= lookup_image (selected_frame
, spec
);
10014 debug_print (spec
);
10015 return make_number (id
);
10018 #endif /* GLYPH_DEBUG != 0 */
10022 /***********************************************************************
10024 ***********************************************************************/
10029 /* This is zero if not using X windows. */
10032 /* The section below is built by the lisp expression at the top of the file,
10033 just above where these variables are declared. */
10034 /*&&& init symbols here &&&*/
10035 Qauto_raise
= intern ("auto-raise");
10036 staticpro (&Qauto_raise
);
10037 Qauto_lower
= intern ("auto-lower");
10038 staticpro (&Qauto_lower
);
10039 Qbar
= intern ("bar");
10041 Qborder_color
= intern ("border-color");
10042 staticpro (&Qborder_color
);
10043 Qborder_width
= intern ("border-width");
10044 staticpro (&Qborder_width
);
10045 Qbox
= intern ("box");
10047 Qcursor_color
= intern ("cursor-color");
10048 staticpro (&Qcursor_color
);
10049 Qcursor_type
= intern ("cursor-type");
10050 staticpro (&Qcursor_type
);
10051 Qgeometry
= intern ("geometry");
10052 staticpro (&Qgeometry
);
10053 Qicon_left
= intern ("icon-left");
10054 staticpro (&Qicon_left
);
10055 Qicon_top
= intern ("icon-top");
10056 staticpro (&Qicon_top
);
10057 Qicon_type
= intern ("icon-type");
10058 staticpro (&Qicon_type
);
10059 Qicon_name
= intern ("icon-name");
10060 staticpro (&Qicon_name
);
10061 Qinternal_border_width
= intern ("internal-border-width");
10062 staticpro (&Qinternal_border_width
);
10063 Qleft
= intern ("left");
10064 staticpro (&Qleft
);
10065 Qright
= intern ("right");
10066 staticpro (&Qright
);
10067 Qmouse_color
= intern ("mouse-color");
10068 staticpro (&Qmouse_color
);
10069 Qnone
= intern ("none");
10070 staticpro (&Qnone
);
10071 Qparent_id
= intern ("parent-id");
10072 staticpro (&Qparent_id
);
10073 Qscroll_bar_width
= intern ("scroll-bar-width");
10074 staticpro (&Qscroll_bar_width
);
10075 Qsuppress_icon
= intern ("suppress-icon");
10076 staticpro (&Qsuppress_icon
);
10077 Qundefined_color
= intern ("undefined-color");
10078 staticpro (&Qundefined_color
);
10079 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10080 staticpro (&Qvertical_scroll_bars
);
10081 Qvisibility
= intern ("visibility");
10082 staticpro (&Qvisibility
);
10083 Qwindow_id
= intern ("window-id");
10084 staticpro (&Qwindow_id
);
10085 Qouter_window_id
= intern ("outer-window-id");
10086 staticpro (&Qouter_window_id
);
10087 Qx_frame_parameter
= intern ("x-frame-parameter");
10088 staticpro (&Qx_frame_parameter
);
10089 Qx_resource_name
= intern ("x-resource-name");
10090 staticpro (&Qx_resource_name
);
10091 Quser_position
= intern ("user-position");
10092 staticpro (&Quser_position
);
10093 Quser_size
= intern ("user-size");
10094 staticpro (&Quser_size
);
10095 Qdisplay
= intern ("display");
10096 staticpro (&Qdisplay
);
10097 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10098 staticpro (&Qscroll_bar_foreground
);
10099 Qscroll_bar_background
= intern ("scroll-bar-background");
10100 staticpro (&Qscroll_bar_background
);
10101 /* This is the end of symbol initialization. */
10103 Qlaplace
= intern ("laplace");
10104 staticpro (&Qlaplace
);
10106 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10107 staticpro (&Qface_set_after_frame_default
);
10109 Fput (Qundefined_color
, Qerror_conditions
,
10110 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10111 Fput (Qundefined_color
, Qerror_message
,
10112 build_string ("Undefined color"));
10114 init_x_parm_symbols ();
10116 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10117 "List of directories to search for bitmap files for X.");
10118 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
10120 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10121 "The shape of the pointer when over text.\n\
10122 Changing the value does not affect existing frames\n\
10123 unless you set the mouse color.");
10124 Vx_pointer_shape
= Qnil
;
10126 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
10127 "The name Emacs uses to look up X resources.\n\
10128 `x-get-resource' uses this as the first component of the instance name\n\
10129 when requesting resource values.\n\
10130 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10131 was invoked, or to the value specified with the `-name' or `-rn'\n\
10132 switches, if present.\n\
10134 It may be useful to bind this variable locally around a call\n\
10135 to `x-get-resource'. See also the variable `x-resource-class'.");
10136 Vx_resource_name
= Qnil
;
10138 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
10139 "The class Emacs uses to look up X resources.\n\
10140 `x-get-resource' uses this as the first component of the instance class\n\
10141 when requesting resource values.\n\
10142 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10144 Setting this variable permanently is not a reasonable thing to do,\n\
10145 but binding this variable locally around a call to `x-get-resource'\n\
10146 is a reasonable practice. See also the variable `x-resource-name'.");
10147 Vx_resource_class
= build_string (EMACS_CLASS
);
10149 #if 0 /* This doesn't really do anything. */
10150 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
10151 "The shape of the pointer when not over text.\n\
10152 This variable takes effect when you create a new frame\n\
10153 or when you set the mouse color.");
10155 Vx_nontext_pointer_shape
= Qnil
;
10157 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
10158 "The shape of the pointer when Emacs is busy.\n\
10159 This variable takes effect when you create a new frame\n\
10160 or when you set the mouse color.");
10161 Vx_busy_pointer_shape
= Qnil
;
10163 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
10164 "Non-zero means Emacs displays a busy cursor on window systems.");
10165 display_busy_cursor_p
= 1;
10167 #if 0 /* This doesn't really do anything. */
10168 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
10169 "The shape of the pointer when over the mode line.\n\
10170 This variable takes effect when you create a new frame\n\
10171 or when you set the mouse color.");
10173 Vx_mode_pointer_shape
= Qnil
;
10175 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10176 &Vx_sensitive_text_pointer_shape
,
10177 "The shape of the pointer when over mouse-sensitive text.\n\
10178 This variable takes effect when you create a new frame\n\
10179 or when you set the mouse color.");
10180 Vx_sensitive_text_pointer_shape
= Qnil
;
10182 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
10183 "A string indicating the foreground color of the cursor box.");
10184 Vx_cursor_fore_pixel
= Qnil
;
10186 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
10187 "Non-nil if no X window manager is in use.\n\
10188 Emacs doesn't try to figure this out; this is always nil\n\
10189 unless you set it to something else.");
10190 /* We don't have any way to find this out, so set it to nil
10191 and maybe the user would like to set it to t. */
10192 Vx_no_window_manager
= Qnil
;
10194 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10195 &Vx_pixel_size_width_font_regexp
,
10196 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10198 Since Emacs gets width of a font matching with this regexp from\n\
10199 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10200 such a font. This is especially effective for such large fonts as\n\
10201 Chinese, Japanese, and Korean.");
10202 Vx_pixel_size_width_font_regexp
= Qnil
;
10204 DEFVAR_LISP ("image-eviction-seconds", &Vimage_eviction_seconds
,
10205 "Time after which cached images are removed from the cache.\n\
10206 When an image has not been displayed this many seconds, remove it\n\
10207 from the image cache. Value must be an integer or nil with nil\n\
10208 meaning don't clear the cache.");
10209 Vimage_eviction_seconds
= make_number (30 * 60);
10211 DEFVAR_LISP ("image-types", &Vimage_types
,
10212 "List of supported image types.\n\
10213 Each element of the list is a symbol for a supported image type.");
10214 Vimage_types
= Qnil
;
10216 #ifdef USE_X_TOOLKIT
10217 Fprovide (intern ("x-toolkit"));
10220 Fprovide (intern ("motif"));
10223 defsubr (&Sx_get_resource
);
10225 /* X window properties. */
10226 defsubr (&Sx_change_window_property
);
10227 defsubr (&Sx_delete_window_property
);
10228 defsubr (&Sx_window_property
);
10231 defsubr (&Sx_draw_rectangle
);
10232 defsubr (&Sx_erase_rectangle
);
10233 defsubr (&Sx_contour_region
);
10234 defsubr (&Sx_uncontour_region
);
10236 defsubr (&Sx_display_color_p
);
10237 defsubr (&Sx_display_grayscale_p
);
10238 defsubr (&Sx_color_defined_p
);
10239 defsubr (&Sx_color_values
);
10240 defsubr (&Sx_server_max_request_size
);
10241 defsubr (&Sx_server_vendor
);
10242 defsubr (&Sx_server_version
);
10243 defsubr (&Sx_display_pixel_width
);
10244 defsubr (&Sx_display_pixel_height
);
10245 defsubr (&Sx_display_mm_width
);
10246 defsubr (&Sx_display_mm_height
);
10247 defsubr (&Sx_display_screens
);
10248 defsubr (&Sx_display_planes
);
10249 defsubr (&Sx_display_color_cells
);
10250 defsubr (&Sx_display_visual_class
);
10251 defsubr (&Sx_display_backing_store
);
10252 defsubr (&Sx_display_save_under
);
10254 defsubr (&Sx_rebind_key
);
10255 defsubr (&Sx_rebind_keys
);
10256 defsubr (&Sx_track_pointer
);
10257 defsubr (&Sx_grab_pointer
);
10258 defsubr (&Sx_ungrab_pointer
);
10260 defsubr (&Sx_parse_geometry
);
10261 defsubr (&Sx_create_frame
);
10263 defsubr (&Sx_horizontal_line
);
10265 defsubr (&Sx_open_connection
);
10266 defsubr (&Sx_close_connection
);
10267 defsubr (&Sx_display_list
);
10268 defsubr (&Sx_synchronize
);
10270 /* Setting callback functions for fontset handler. */
10271 get_font_info_func
= x_get_font_info
;
10273 #if 0 /* This function pointer doesn't seem to be used anywhere.
10274 And the pointer assigned has the wrong type, anyway. */
10275 list_fonts_func
= x_list_fonts
;
10278 load_font_func
= x_load_font
;
10279 find_ccl_program_func
= x_find_ccl_program
;
10280 query_font_func
= x_query_font
;
10281 set_frame_fontset_func
= x_set_font
;
10282 check_window_system_func
= check_x
;
10285 Qxbm
= intern ("xbm");
10287 QCtype
= intern (":type");
10288 staticpro (&QCtype
);
10289 QCfile
= intern (":file");
10290 staticpro (&QCfile
);
10291 QCalgorithm
= intern (":algorithm");
10292 staticpro (&QCalgorithm
);
10293 QCheuristic_mask
= intern (":heuristic-mask");
10294 staticpro (&QCheuristic_mask
);
10295 QCcolor_symbols
= intern (":color-symbols");
10296 staticpro (&QCcolor_symbols
);
10297 QCdata
= intern (":data");
10298 staticpro (&QCdata
);
10299 QCascent
= intern (":ascent");
10300 staticpro (&QCascent
);
10301 QCmargin
= intern (":margin");
10302 staticpro (&QCmargin
);
10303 QCrelief
= intern (":relief");
10304 staticpro (&QCrelief
);
10305 Qghostscript
= intern ("ghostscript");
10306 staticpro (&Qghostscript
);
10307 QCloader
= intern (":loader");
10308 staticpro (&QCloader
);
10309 QCbounding_box
= intern (":bounding-box");
10310 staticpro (&QCbounding_box
);
10311 QCpt_width
= intern (":pt-width");
10312 staticpro (&QCpt_width
);
10313 QCpt_height
= intern (":pt-height");
10314 staticpro (&QCpt_height
);
10315 Qpbm
= intern ("pbm");
10319 Qxpm
= intern ("xpm");
10324 Qjpeg
= intern ("jpeg");
10325 staticpro (&Qjpeg
);
10329 Qtiff
= intern ("tiff");
10330 staticpro (&Qtiff
);
10334 Qgif
= intern ("gif");
10339 Qpng
= intern ("png");
10343 defsubr (&Sclear_image_cache
);
10346 defsubr (&Simagep
);
10347 defsubr (&Slookup_image
);
10351 defsubr (&Sx_show_busy_cursor
);
10352 defsubr (&Sx_hide_busy_cursor
);
10354 inhibit_busy_cursor
= 0;
10356 defsubr (&Sx_show_tip
);
10357 defsubr (&Sx_hide_tip
);
10358 staticpro (&tip_timer
);
10362 defsubr (&Sx_file_dialog
);
10370 image_types
= NULL
;
10371 Vimage_types
= Qnil
;
10373 define_image_type (&xbm_type
);
10374 define_image_type (&gs_type
);
10375 define_image_type (&pbm_type
);
10378 define_image_type (&xpm_type
);
10382 define_image_type (&jpeg_type
);
10386 define_image_type (&tiff_type
);
10390 define_image_type (&gif_type
);
10394 define_image_type (&png_type
);
10398 #endif /* HAVE_X_WINDOWS */