1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
36 #include "intervals.h"
37 #include "dispextern.h"
39 #include "blockinput.h"
45 #include "termhooks.h"
51 #include <sys/types.h>
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
58 #include <X11/bitmaps/gray>
61 #include "[.bitmaps]gray.xbm"
65 #include <X11/Shell.h>
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
82 #include "../lwlib/lwlib.h"
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick
;
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct
*xlwmenu_default_font
;
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #endif /* USE_X_TOOLKIT */
112 #define min(a,b) ((a) < (b) ? (a) : (b))
113 #define max(a,b) ((a) > (b) ? (a) : (b))
116 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
118 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
121 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
122 it, and including `bitmaps/gray' more than once is a problem when
123 config.h defines `static' as an empty replacement string. */
125 int gray_bitmap_width
= gray_width
;
126 int gray_bitmap_height
= gray_height
;
127 unsigned char *gray_bitmap_bits
= gray_bits
;
129 /* The name we're using in resource queries. Most often "emacs". */
131 Lisp_Object Vx_resource_name
;
133 /* The application class we're using in resource queries.
136 Lisp_Object Vx_resource_class
;
138 /* Non-zero means we're allowed to display a busy cursor. */
140 int display_busy_cursor_p
;
142 /* The background and shape of the mouse pointer, and shape when not
143 over text or in the modeline. */
145 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
146 Lisp_Object Vx_busy_pointer_shape
;
148 /* The shape when over mouse-sensitive text. */
150 Lisp_Object Vx_sensitive_text_pointer_shape
;
152 /* Color of chars displayed in cursor box. */
154 Lisp_Object Vx_cursor_fore_pixel
;
156 /* Nonzero if using X. */
160 /* Non nil if no window manager is in use. */
162 Lisp_Object Vx_no_window_manager
;
164 /* Search path for bitmap files. */
166 Lisp_Object Vx_bitmap_file_path
;
168 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
170 Lisp_Object Vx_pixel_size_width_font_regexp
;
172 /* Evaluate this expression to rebuild the section of syms_of_xfns
173 that initializes and staticpros the symbols declared below. Note
174 that Emacs 18 has a bug that keeps C-x C-e from being able to
175 evaluate this expression.
178 ;; Accumulate a list of the symbols we want to initialize from the
179 ;; declarations at the top of the file.
180 (goto-char (point-min))
181 (search-forward "/\*&&& symbols declared here &&&*\/\n")
183 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
185 (cons (buffer-substring (match-beginning 1) (match-end 1))
188 (setq symbol-list (nreverse symbol-list))
189 ;; Delete the section of syms_of_... where we initialize the symbols.
190 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
191 (let ((start (point)))
192 (while (looking-at "^ Q")
194 (kill-region start (point)))
195 ;; Write a new symbol initialization section.
197 (insert (format " %s = intern (\"" (car symbol-list)))
198 (let ((start (point)))
199 (insert (substring (car symbol-list) 1))
200 (subst-char-in-region start (point) ?_ ?-))
201 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
202 (setq symbol-list (cdr symbol-list)))))
206 /*&&& symbols declared here &&&*/
207 Lisp_Object Qauto_raise
;
208 Lisp_Object Qauto_lower
;
210 Lisp_Object Qborder_color
;
211 Lisp_Object Qborder_width
;
213 Lisp_Object Qcursor_color
;
214 Lisp_Object Qcursor_type
;
215 Lisp_Object Qgeometry
;
216 Lisp_Object Qicon_left
;
217 Lisp_Object Qicon_top
;
218 Lisp_Object Qicon_type
;
219 Lisp_Object Qicon_name
;
220 Lisp_Object Qinternal_border_width
;
223 Lisp_Object Qmouse_color
;
225 Lisp_Object Qouter_window_id
;
226 Lisp_Object Qparent_id
;
227 Lisp_Object Qscroll_bar_width
;
228 Lisp_Object Qsuppress_icon
;
229 extern Lisp_Object Qtop
;
230 Lisp_Object Qundefined_color
;
231 Lisp_Object Qvertical_scroll_bars
;
232 Lisp_Object Qvisibility
;
233 Lisp_Object Qwindow_id
;
234 Lisp_Object Qx_frame_parameter
;
235 Lisp_Object Qx_resource_name
;
236 Lisp_Object Quser_position
;
237 Lisp_Object Quser_size
;
238 extern Lisp_Object Qdisplay
;
239 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
240 Lisp_Object Qscreen_gamma
, Qline_spacing
, Qcenter
;
241 Lisp_Object Qcompound_text
;
243 /* The below are defined in frame.c. */
245 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
246 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
247 extern Lisp_Object Qtool_bar_lines
;
249 extern Lisp_Object Vwindow_system_version
;
251 Lisp_Object Qface_set_after_frame_default
;
254 /* Error if we are not connected to X. */
260 error ("X windows are not in use or not initialized");
263 /* Nonzero if we can use mouse menus.
264 You should not call this unless HAVE_MENUS is defined. */
272 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
273 and checking validity for X. */
276 check_x_frame (frame
)
282 frame
= selected_frame
;
283 CHECK_LIVE_FRAME (frame
, 0);
286 error ("Non-X frame used");
290 /* Let the user specify an X display with a frame.
291 nil stands for the selected frame--or, if that is not an X frame,
292 the first X display on the list. */
294 static struct x_display_info
*
295 check_x_display_info (frame
)
300 struct frame
*sf
= XFRAME (selected_frame
);
302 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
303 return FRAME_X_DISPLAY_INFO (sf
);
304 else if (x_display_list
!= 0)
305 return x_display_list
;
307 error ("X windows are not in use or not initialized");
309 else if (STRINGP (frame
))
310 return x_display_info_for_name (frame
);
315 CHECK_LIVE_FRAME (frame
, 0);
318 error ("Non-X frame used");
319 return FRAME_X_DISPLAY_INFO (f
);
324 /* Return the Emacs frame-object corresponding to an X window.
325 It could be the frame's main window or an icon window. */
327 /* This function can be called during GC, so use GC_xxx type test macros. */
330 x_window_to_frame (dpyinfo
, wdesc
)
331 struct x_display_info
*dpyinfo
;
334 Lisp_Object tail
, frame
;
337 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
340 if (!GC_FRAMEP (frame
))
343 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
345 if (f
->output_data
.x
->busy_window
== wdesc
)
348 if ((f
->output_data
.x
->edit_widget
349 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
350 /* A tooltip frame? */
351 || (!f
->output_data
.x
->edit_widget
352 && FRAME_X_WINDOW (f
) == wdesc
)
353 || f
->output_data
.x
->icon_desc
== wdesc
)
355 #else /* not USE_X_TOOLKIT */
356 if (FRAME_X_WINDOW (f
) == wdesc
357 || f
->output_data
.x
->icon_desc
== wdesc
)
359 #endif /* not USE_X_TOOLKIT */
365 /* Like x_window_to_frame but also compares the window with the widget's
369 x_any_window_to_frame (dpyinfo
, wdesc
)
370 struct x_display_info
*dpyinfo
;
373 Lisp_Object tail
, frame
;
374 struct frame
*f
, *found
;
378 for (tail
= Vframe_list
; GC_CONSP (tail
) && !found
; tail
= XCDR (tail
))
381 if (!GC_FRAMEP (frame
))
385 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
387 /* This frame matches if the window is any of its widgets. */
388 x
= f
->output_data
.x
;
389 if (x
->busy_window
== wdesc
)
393 if (wdesc
== XtWindow (x
->widget
)
394 || wdesc
== XtWindow (x
->column_widget
)
395 || wdesc
== XtWindow (x
->edit_widget
))
397 /* Match if the window is this frame's menubar. */
398 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
401 else if (FRAME_X_WINDOW (f
) == wdesc
)
402 /* 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
= XCDR (tail
))
424 if (!GC_FRAMEP (frame
))
427 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
429 x
= f
->output_data
.x
;
430 /* This frame matches if the window is any of its widgets. */
431 if (x
->busy_window
== wdesc
)
435 if (wdesc
== XtWindow (x
->widget
)
436 || wdesc
== XtWindow (x
->column_widget
)
437 || wdesc
== XtWindow (x
->edit_widget
))
440 else if (FRAME_X_WINDOW (f
) == wdesc
)
441 /* A tooltip frame. */
447 /* Likewise, but consider only the menu bar widget. */
450 x_menubar_window_to_frame (dpyinfo
, wdesc
)
451 struct x_display_info
*dpyinfo
;
454 Lisp_Object tail
, frame
;
458 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
461 if (!GC_FRAMEP (frame
))
464 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
466 x
= f
->output_data
.x
;
467 /* Match if the window is this frame's menubar. */
468 if (x
->menubar_widget
469 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
475 /* Return the frame whose principal (outermost) window is WDESC.
476 If WDESC is some other (smaller) window, we return 0. */
479 x_top_window_to_frame (dpyinfo
, wdesc
)
480 struct x_display_info
*dpyinfo
;
483 Lisp_Object tail
, frame
;
487 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
490 if (!GC_FRAMEP (frame
))
493 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
495 x
= f
->output_data
.x
;
499 /* This frame matches if the window is its topmost widget. */
500 if (wdesc
== XtWindow (x
->widget
))
502 #if 0 /* I don't know why it did this,
503 but it seems logically wrong,
504 and it causes trouble for MapNotify events. */
505 /* Match if the window is this frame's menubar. */
506 if (x
->menubar_widget
507 && wdesc
== XtWindow (x
->menubar_widget
))
511 else if (FRAME_X_WINDOW (f
) == wdesc
)
517 #endif /* USE_X_TOOLKIT */
521 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
522 id, which is just an int that this section returns. Bitmaps are
523 reference counted so they can be shared among frames.
525 Bitmap indices are guaranteed to be > 0, so a negative number can
526 be used to indicate no bitmap.
528 If you use x_create_bitmap_from_data, then you must keep track of
529 the bitmaps yourself. That is, creating a bitmap from the same
530 data more than once will not be caught. */
533 /* Functions to access the contents of a bitmap, given an id. */
536 x_bitmap_height (f
, id
)
540 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
544 x_bitmap_width (f
, id
)
548 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
552 x_bitmap_pixmap (f
, id
)
556 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
560 /* Allocate a new bitmap record. Returns index of new record. */
563 x_allocate_bitmap_record (f
)
566 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
569 if (dpyinfo
->bitmaps
== NULL
)
571 dpyinfo
->bitmaps_size
= 10;
573 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
574 dpyinfo
->bitmaps_last
= 1;
578 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
579 return ++dpyinfo
->bitmaps_last
;
581 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
582 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
585 dpyinfo
->bitmaps_size
*= 2;
587 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
588 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
589 return ++dpyinfo
->bitmaps_last
;
592 /* Add one reference to the reference count of the bitmap with id ID. */
595 x_reference_bitmap (f
, id
)
599 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
602 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
605 x_create_bitmap_from_data (f
, bits
, width
, height
)
608 unsigned int width
, height
;
610 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
614 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
615 bits
, width
, height
);
620 id
= x_allocate_bitmap_record (f
);
621 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
622 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
623 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
624 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
625 dpyinfo
->bitmaps
[id
- 1].height
= height
;
626 dpyinfo
->bitmaps
[id
- 1].width
= width
;
631 /* Create bitmap from file FILE for frame F. */
634 x_create_bitmap_from_file (f
, file
)
638 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
639 unsigned int width
, height
;
641 int xhot
, yhot
, result
, id
;
646 /* Look for an existing bitmap with the same name. */
647 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
649 if (dpyinfo
->bitmaps
[id
].refcount
650 && dpyinfo
->bitmaps
[id
].file
651 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
653 ++dpyinfo
->bitmaps
[id
].refcount
;
658 /* Search bitmap-file-path for the file, if appropriate. */
659 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
662 /* XReadBitmapFile won't handle magic file names. */
667 filename
= (char *) XSTRING (found
)->data
;
669 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
670 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
671 if (result
!= BitmapSuccess
)
674 id
= x_allocate_bitmap_record (f
);
675 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
676 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
677 dpyinfo
->bitmaps
[id
- 1].file
678 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
679 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
680 dpyinfo
->bitmaps
[id
- 1].height
= height
;
681 dpyinfo
->bitmaps
[id
- 1].width
= width
;
682 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
687 /* Remove reference to bitmap with id number ID. */
690 x_destroy_bitmap (f
, id
)
694 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
698 --dpyinfo
->bitmaps
[id
- 1].refcount
;
699 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
702 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
703 if (dpyinfo
->bitmaps
[id
- 1].file
)
705 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
706 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
713 /* Free all the bitmaps for the display specified by DPYINFO. */
716 x_destroy_all_bitmaps (dpyinfo
)
717 struct x_display_info
*dpyinfo
;
720 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
721 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
723 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
724 if (dpyinfo
->bitmaps
[i
].file
)
725 xfree (dpyinfo
->bitmaps
[i
].file
);
727 dpyinfo
->bitmaps_last
= 0;
730 /* Connect the frame-parameter names for X frames
731 to the ways of passing the parameter values to the window system.
733 The name of a parameter, as a Lisp symbol,
734 has an `x-frame-parameter' property which is an integer in Lisp
735 that is an index in this table. */
737 struct x_frame_parm_table
740 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 static void x_create_im
P_ ((struct frame
*));
744 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 static void x_set_line_spacing
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
750 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
751 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
752 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
755 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
757 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
760 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
762 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
763 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
764 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
765 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
766 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
767 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
768 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
770 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
772 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
777 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
779 static struct x_frame_parm_table x_frame_parms
[] =
781 "auto-raise", x_set_autoraise
,
782 "auto-lower", x_set_autolower
,
783 "background-color", x_set_background_color
,
784 "border-color", x_set_border_color
,
785 "border-width", x_set_border_width
,
786 "cursor-color", x_set_cursor_color
,
787 "cursor-type", x_set_cursor_type
,
789 "foreground-color", x_set_foreground_color
,
790 "icon-name", x_set_icon_name
,
791 "icon-type", x_set_icon_type
,
792 "internal-border-width", x_set_internal_border_width
,
793 "menu-bar-lines", x_set_menu_bar_lines
,
794 "mouse-color", x_set_mouse_color
,
795 "name", x_explicitly_set_name
,
796 "scroll-bar-width", x_set_scroll_bar_width
,
797 "title", x_set_title
,
798 "unsplittable", x_set_unsplittable
,
799 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
800 "visibility", x_set_visibility
,
801 "tool-bar-lines", x_set_tool_bar_lines
,
802 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
803 "scroll-bar-background", x_set_scroll_bar_background
,
804 "screen-gamma", x_set_screen_gamma
,
805 "line-spacing", x_set_line_spacing
808 /* Attach the `x-frame-parameter' properties to
809 the Lisp symbol names of parameters relevant to X. */
812 init_x_parm_symbols ()
816 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
817 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
821 /* Change the parameters of frame F as specified by ALIST.
822 If a parameter is not specially recognized, do nothing special;
823 otherwise call the `x_set_...' function for that parameter.
824 Except for certain geometry properties, always call store_frame_param
825 to store the new value in the parameter alist. */
828 x_set_frame_parameters (f
, alist
)
834 /* If both of these parameters are present, it's more efficient to
835 set them both at once. So we wait until we've looked at the
836 entire list before we set them. */
840 Lisp_Object left
, top
;
842 /* Same with these. */
843 Lisp_Object icon_left
, icon_top
;
845 /* Record in these vectors all the parms specified. */
849 int left_no_change
= 0, top_no_change
= 0;
850 int icon_left_no_change
= 0, icon_top_no_change
= 0;
852 struct gcpro gcpro1
, gcpro2
;
855 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
858 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
859 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
861 /* Extract parm names and values into those vectors. */
864 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
869 parms
[i
] = Fcar (elt
);
870 values
[i
] = Fcdr (elt
);
873 /* TAIL and ALIST are not used again below here. */
876 GCPRO2 (*parms
, *values
);
880 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
881 because their values appear in VALUES and strings are not valid. */
882 top
= left
= Qunbound
;
883 icon_left
= icon_top
= Qunbound
;
885 /* Provide default values for HEIGHT and WIDTH. */
886 if (FRAME_NEW_WIDTH (f
))
887 width
= FRAME_NEW_WIDTH (f
);
889 width
= FRAME_WIDTH (f
);
891 if (FRAME_NEW_HEIGHT (f
))
892 height
= FRAME_NEW_HEIGHT (f
);
894 height
= FRAME_HEIGHT (f
);
896 /* Process foreground_color and background_color before anything else.
897 They are independent of other properties, but other properties (e.g.,
898 cursor_color) are dependent upon them. */
899 for (p
= 0; p
< i
; p
++)
901 Lisp_Object prop
, val
;
905 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
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 /* Now process them in reverse of specified order. */
920 for (i
--; i
>= 0; i
--)
922 Lisp_Object prop
, val
;
927 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
928 width
= XFASTINT (val
);
929 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
930 height
= XFASTINT (val
);
931 else if (EQ (prop
, Qtop
))
933 else if (EQ (prop
, Qleft
))
935 else if (EQ (prop
, Qicon_top
))
937 else if (EQ (prop
, Qicon_left
))
939 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
940 /* Processed above. */
944 register Lisp_Object param_index
, old_value
;
946 param_index
= Fget (prop
, Qx_frame_parameter
);
947 old_value
= get_frame_param (f
, prop
);
948 store_frame_param (f
, prop
, val
);
949 if (NATNUMP (param_index
)
950 && (XFASTINT (param_index
)
951 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
952 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
956 /* Don't die if just one of these was set. */
957 if (EQ (left
, Qunbound
))
960 if (f
->output_data
.x
->left_pos
< 0)
961 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
963 XSETINT (left
, f
->output_data
.x
->left_pos
);
965 if (EQ (top
, Qunbound
))
968 if (f
->output_data
.x
->top_pos
< 0)
969 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
971 XSETINT (top
, f
->output_data
.x
->top_pos
);
974 /* If one of the icon positions was not set, preserve or default it. */
975 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
977 icon_left_no_change
= 1;
978 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
979 if (NILP (icon_left
))
980 XSETINT (icon_left
, 0);
982 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
984 icon_top_no_change
= 1;
985 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
987 XSETINT (icon_top
, 0);
990 /* Don't set these parameters unless they've been explicitly
991 specified. The window might be mapped or resized while we're in
992 this function, and we don't want to override that unless the lisp
993 code has asked for it.
995 Don't set these parameters unless they actually differ from the
996 window's current parameters; the window may not actually exist
1001 check_frame_size (f
, &height
, &width
);
1003 XSETFRAME (frame
, f
);
1005 if (width
!= FRAME_WIDTH (f
)
1006 || height
!= FRAME_HEIGHT (f
)
1007 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
1008 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1010 if ((!NILP (left
) || !NILP (top
))
1011 && ! (left_no_change
&& top_no_change
)
1012 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1013 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1018 /* Record the signs. */
1019 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1020 if (EQ (left
, Qminus
))
1021 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1022 else if (INTEGERP (left
))
1024 leftpos
= XINT (left
);
1026 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1028 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1029 && CONSP (XCDR (left
))
1030 && INTEGERP (XCAR (XCDR (left
))))
1032 leftpos
= - XINT (XCAR (XCDR (left
)));
1033 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1035 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1036 && CONSP (XCDR (left
))
1037 && INTEGERP (XCAR (XCDR (left
))))
1039 leftpos
= XINT (XCAR (XCDR (left
)));
1042 if (EQ (top
, Qminus
))
1043 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1044 else if (INTEGERP (top
))
1046 toppos
= XINT (top
);
1048 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1050 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1051 && CONSP (XCDR (top
))
1052 && INTEGERP (XCAR (XCDR (top
))))
1054 toppos
= - XINT (XCAR (XCDR (top
)));
1055 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1057 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1058 && CONSP (XCDR (top
))
1059 && INTEGERP (XCAR (XCDR (top
))))
1061 toppos
= XINT (XCAR (XCDR (top
)));
1065 /* Store the numeric value of the position. */
1066 f
->output_data
.x
->top_pos
= toppos
;
1067 f
->output_data
.x
->left_pos
= leftpos
;
1069 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1071 /* Actually set that position, and convert to absolute. */
1072 x_set_offset (f
, leftpos
, toppos
, -1);
1075 if ((!NILP (icon_left
) || !NILP (icon_top
))
1076 && ! (icon_left_no_change
&& icon_top_no_change
))
1077 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1083 /* Store the screen positions of frame F into XPTR and YPTR.
1084 These are the positions of the containing window manager window,
1085 not Emacs's own window. */
1088 x_real_positions (f
, xptr
, yptr
)
1095 /* This is pretty gross, but seems to be the easiest way out of
1096 the problem that arises when restarting window-managers. */
1098 #ifdef USE_X_TOOLKIT
1099 Window outer
= (f
->output_data
.x
->widget
1100 ? XtWindow (f
->output_data
.x
->widget
)
1101 : FRAME_X_WINDOW (f
));
1103 Window outer
= f
->output_data
.x
->window_desc
;
1105 Window tmp_root_window
;
1106 Window
*tmp_children
;
1107 unsigned int tmp_nchildren
;
1111 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1112 Window outer_window
;
1114 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1115 &f
->output_data
.x
->parent_desc
,
1116 &tmp_children
, &tmp_nchildren
);
1117 XFree ((char *) tmp_children
);
1121 /* Find the position of the outside upper-left corner of
1122 the inner window, with respect to the outer window. */
1123 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1124 outer_window
= f
->output_data
.x
->parent_desc
;
1126 outer_window
= outer
;
1128 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1130 /* From-window, to-window. */
1132 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1134 /* From-position, to-position. */
1135 0, 0, &win_x
, &win_y
,
1140 /* It is possible for the window returned by the XQueryNotify
1141 to become invalid by the time we call XTranslateCoordinates.
1142 That can happen when you restart some window managers.
1143 If so, we get an error in XTranslateCoordinates.
1144 Detect that and try the whole thing over. */
1145 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1147 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1151 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1158 /* Insert a description of internally-recorded parameters of frame X
1159 into the parameter alist *ALISTPTR that is to be given to the user.
1160 Only parameters that are specific to the X window system
1161 and whose values are not correctly recorded in the frame's
1162 param_alist need to be considered here. */
1165 x_report_frame_params (f
, alistptr
)
1167 Lisp_Object
*alistptr
;
1172 /* Represent negative positions (off the top or left screen edge)
1173 in a way that Fmodify_frame_parameters will understand correctly. */
1174 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1175 if (f
->output_data
.x
->left_pos
>= 0)
1176 store_in_alist (alistptr
, Qleft
, tem
);
1178 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1180 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1181 if (f
->output_data
.x
->top_pos
>= 0)
1182 store_in_alist (alistptr
, Qtop
, tem
);
1184 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1186 store_in_alist (alistptr
, Qborder_width
,
1187 make_number (f
->output_data
.x
->border_width
));
1188 store_in_alist (alistptr
, Qinternal_border_width
,
1189 make_number (f
->output_data
.x
->internal_border_width
));
1190 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1191 store_in_alist (alistptr
, Qwindow_id
,
1192 build_string (buf
));
1193 #ifdef USE_X_TOOLKIT
1194 /* Tooltip frame may not have this widget. */
1195 if (f
->output_data
.x
->widget
)
1197 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1198 store_in_alist (alistptr
, Qouter_window_id
,
1199 build_string (buf
));
1200 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1201 FRAME_SAMPLE_VISIBILITY (f
);
1202 store_in_alist (alistptr
, Qvisibility
,
1203 (FRAME_VISIBLE_P (f
) ? Qt
1204 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1205 store_in_alist (alistptr
, Qdisplay
,
1206 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1208 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1211 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1212 store_in_alist (alistptr
, Qparent_id
, tem
);
1217 /* Gamma-correct COLOR on frame F. */
1220 gamma_correct (f
, color
)
1226 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1227 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1228 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1233 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1234 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1235 allocate the color. Value is zero if COLOR_NAME is invalid, or
1236 no color could be allocated. */
1239 x_defined_color (f
, color_name
, color
, alloc_p
)
1246 Display
*dpy
= FRAME_X_DISPLAY (f
);
1247 Colormap cmap
= FRAME_X_COLORMAP (f
);
1250 success_p
= XParseColor (dpy
, cmap
, color_name
, color
);
1251 if (success_p
&& alloc_p
)
1252 success_p
= x_alloc_nearest_color (f
, cmap
, color
);
1259 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1260 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1261 Signal an error if color can't be allocated. */
1264 x_decode_color (f
, color_name
, mono_color
)
1266 Lisp_Object color_name
;
1271 CHECK_STRING (color_name
, 0);
1273 #if 0 /* Don't do this. It's wrong when we're not using the default
1274 colormap, it makes freeing difficult, and it's probably not
1275 an important optimization. */
1276 if (strcmp (XSTRING (color_name
)->data
, "black") == 0)
1277 return BLACK_PIX_DEFAULT (f
);
1278 else if (strcmp (XSTRING (color_name
)->data
, "white") == 0)
1279 return WHITE_PIX_DEFAULT (f
);
1282 /* Return MONO_COLOR for monochrome frames. */
1283 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1286 /* x_defined_color is responsible for coping with failures
1287 by looking for a near-miss. */
1288 if (x_defined_color (f
, XSTRING (color_name
)->data
, &cdef
, 1))
1291 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
1292 Fcons (color_name
, Qnil
)));
1297 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1298 the previous value of that parameter, NEW_VALUE is the new value. */
1301 x_set_line_spacing (f
, new_value
, old_value
)
1303 Lisp_Object new_value
, old_value
;
1305 if (NILP (new_value
))
1306 f
->extra_line_spacing
= 0;
1307 else if (NATNUMP (new_value
))
1308 f
->extra_line_spacing
= XFASTINT (new_value
);
1310 Fsignal (Qerror
, Fcons (build_string ("Invalid line-spacing"),
1311 Fcons (new_value
, Qnil
)));
1312 if (FRAME_VISIBLE_P (f
))
1317 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1318 the previous value of that parameter, NEW_VALUE is the new value. */
1321 x_set_screen_gamma (f
, new_value
, old_value
)
1323 Lisp_Object new_value
, old_value
;
1325 if (NILP (new_value
))
1327 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1328 /* The value 0.4545 is the normal viewing gamma. */
1329 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1331 Fsignal (Qerror
, Fcons (build_string ("Invalid screen-gamma"),
1332 Fcons (new_value
, Qnil
)));
1334 clear_face_cache (0);
1338 /* Functions called only from `x_set_frame_param'
1339 to set individual parameters.
1341 If FRAME_X_WINDOW (f) is 0,
1342 the frame is being created and its X-window does not exist yet.
1343 In that case, just record the parameter's new value
1344 in the standard place; do not attempt to change the window. */
1347 x_set_foreground_color (f
, arg
, oldval
)
1349 Lisp_Object arg
, oldval
;
1352 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1354 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
1355 f
->output_data
.x
->foreground_pixel
= pixel
;
1357 if (FRAME_X_WINDOW (f
) != 0)
1360 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1361 f
->output_data
.x
->foreground_pixel
);
1362 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1363 f
->output_data
.x
->foreground_pixel
);
1365 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1366 if (FRAME_VISIBLE_P (f
))
1372 x_set_background_color (f
, arg
, oldval
)
1374 Lisp_Object arg
, oldval
;
1377 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1379 unload_color (f
, f
->output_data
.x
->background_pixel
);
1380 f
->output_data
.x
->background_pixel
= pixel
;
1382 if (FRAME_X_WINDOW (f
) != 0)
1385 /* The main frame area. */
1386 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1387 f
->output_data
.x
->background_pixel
);
1388 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1389 f
->output_data
.x
->background_pixel
);
1390 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1391 f
->output_data
.x
->background_pixel
);
1392 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1393 f
->output_data
.x
->background_pixel
);
1396 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1397 bar
= XSCROLL_BAR (bar
)->next
)
1398 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1399 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1400 f
->output_data
.x
->background_pixel
);
1404 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1406 if (FRAME_VISIBLE_P (f
))
1412 x_set_mouse_color (f
, arg
, oldval
)
1414 Lisp_Object arg
, oldval
;
1416 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1419 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1420 unsigned long mask_color
= f
->output_data
.x
->background_pixel
;
1422 /* Don't let pointers be invisible. */
1423 if (mask_color
== pixel
1424 && mask_color
== f
->output_data
.x
->background_pixel
)
1425 pixel
= f
->output_data
.x
->foreground_pixel
;
1427 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
1428 f
->output_data
.x
->mouse_pixel
= pixel
;
1432 /* It's not okay to crash if the user selects a screwy cursor. */
1433 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1435 if (!EQ (Qnil
, Vx_pointer_shape
))
1437 CHECK_NUMBER (Vx_pointer_shape
, 0);
1438 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1441 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1442 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1444 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1446 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1447 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1448 XINT (Vx_nontext_pointer_shape
));
1451 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1452 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1454 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
1456 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
1457 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1458 XINT (Vx_busy_pointer_shape
));
1461 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_watch
);
1462 x_check_errors (FRAME_X_DISPLAY (f
), "bad busy pointer cursor: %s");
1464 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1465 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1467 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1468 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1469 XINT (Vx_mode_pointer_shape
));
1472 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1473 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1475 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1477 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1479 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1480 XINT (Vx_sensitive_text_pointer_shape
));
1483 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1485 /* Check and report errors with the above calls. */
1486 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1487 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1490 XColor fore_color
, back_color
;
1492 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1493 back_color
.pixel
= mask_color
;
1494 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
1496 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
1498 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1499 &fore_color
, &back_color
);
1500 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1501 &fore_color
, &back_color
);
1502 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1503 &fore_color
, &back_color
);
1504 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1505 &fore_color
, &back_color
);
1506 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1507 &fore_color
, &back_color
);
1510 if (FRAME_X_WINDOW (f
) != 0)
1511 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1513 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1514 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1515 f
->output_data
.x
->text_cursor
= cursor
;
1517 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1518 && f
->output_data
.x
->nontext_cursor
!= 0)
1519 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1520 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1522 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1523 && f
->output_data
.x
->busy_cursor
!= 0)
1524 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1525 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1527 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1528 && f
->output_data
.x
->modeline_cursor
!= 0)
1529 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1530 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1532 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1533 && f
->output_data
.x
->cross_cursor
!= 0)
1534 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1535 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1537 XFlush (FRAME_X_DISPLAY (f
));
1540 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1544 x_set_cursor_color (f
, arg
, oldval
)
1546 Lisp_Object arg
, oldval
;
1548 unsigned long fore_pixel
, pixel
;
1549 int fore_pixel_allocated_p
= 0, pixel_allocated_p
= 0;
1551 if (!NILP (Vx_cursor_fore_pixel
))
1553 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1554 WHITE_PIX_DEFAULT (f
));
1555 fore_pixel_allocated_p
= 1;
1558 fore_pixel
= f
->output_data
.x
->background_pixel
;
1560 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1561 pixel_allocated_p
= 1;
1563 /* Make sure that the cursor color differs from the background color. */
1564 if (pixel
== f
->output_data
.x
->background_pixel
)
1566 if (pixel_allocated_p
)
1568 x_free_colors (f
, &pixel
, 1);
1569 pixel_allocated_p
= 0;
1572 pixel
= f
->output_data
.x
->mouse_pixel
;
1573 if (pixel
== fore_pixel
)
1575 if (fore_pixel_allocated_p
)
1577 x_free_colors (f
, &fore_pixel
, 1);
1578 fore_pixel_allocated_p
= 0;
1580 fore_pixel
= f
->output_data
.x
->background_pixel
;
1584 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1585 if (!fore_pixel_allocated_p
)
1586 fore_pixel
= x_copy_color (f
, fore_pixel
);
1587 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1589 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1590 if (!pixel_allocated_p
)
1591 pixel
= x_copy_color (f
, pixel
);
1592 f
->output_data
.x
->cursor_pixel
= pixel
;
1594 if (FRAME_X_WINDOW (f
) != 0)
1597 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1598 f
->output_data
.x
->cursor_pixel
);
1599 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1603 if (FRAME_VISIBLE_P (f
))
1605 x_update_cursor (f
, 0);
1606 x_update_cursor (f
, 1);
1610 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1613 /* Set the border-color of frame F to value described by ARG.
1614 ARG can be a string naming a color.
1615 The border-color is used for the border that is drawn by the X server.
1616 Note that this does not fully take effect if done before
1617 F has an x-window; it must be redone when the window is created.
1619 Note: this is done in two routines because of the way X10 works.
1621 Note: under X11, this is normally the province of the window manager,
1622 and so emacs' border colors may be overridden. */
1625 x_set_border_color (f
, arg
, oldval
)
1627 Lisp_Object arg
, oldval
;
1631 CHECK_STRING (arg
, 0);
1632 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1633 x_set_border_pixel (f
, pix
);
1634 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1637 /* Set the border-color of frame F to pixel value PIX.
1638 Note that this does not fully take effect if done before
1639 F has an x-window. */
1642 x_set_border_pixel (f
, pix
)
1646 unload_color (f
, f
->output_data
.x
->border_pixel
);
1647 f
->output_data
.x
->border_pixel
= pix
;
1649 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1652 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1653 (unsigned long)pix
);
1656 if (FRAME_VISIBLE_P (f
))
1662 /* Value is the internal representation of the specified cursor type
1663 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1664 of the bar cursor. */
1666 enum text_cursor_kinds
1667 x_specified_cursor_type (arg
, width
)
1671 enum text_cursor_kinds type
;
1678 else if (CONSP (arg
)
1679 && EQ (XCAR (arg
), Qbar
)
1680 && INTEGERP (XCDR (arg
))
1681 && XINT (XCDR (arg
)) >= 0)
1684 *width
= XINT (XCDR (arg
));
1686 else if (NILP (arg
))
1689 /* Treat anything unknown as "box cursor".
1690 It was bad to signal an error; people have trouble fixing
1691 .Xdefaults with Emacs, when it has something bad in it. */
1692 type
= FILLED_BOX_CURSOR
;
1698 x_set_cursor_type (f
, arg
, oldval
)
1700 Lisp_Object arg
, oldval
;
1704 FRAME_DESIRED_CURSOR (f
) = x_specified_cursor_type (arg
, &width
);
1705 f
->output_data
.x
->cursor_width
= width
;
1707 /* Make sure the cursor gets redrawn. This is overkill, but how
1708 often do people change cursor types? */
1709 update_mode_lines
++;
1713 x_set_icon_type (f
, arg
, oldval
)
1715 Lisp_Object arg
, oldval
;
1721 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1724 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1729 result
= x_text_icon (f
,
1730 (char *) XSTRING ((!NILP (f
->icon_name
)
1734 result
= x_bitmap_icon (f
, arg
);
1739 error ("No icon window available");
1742 XFlush (FRAME_X_DISPLAY (f
));
1746 /* Return non-nil if frame F wants a bitmap icon. */
1754 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1762 x_set_icon_name (f
, arg
, oldval
)
1764 Lisp_Object arg
, oldval
;
1770 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1773 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1778 if (f
->output_data
.x
->icon_bitmap
!= 0)
1783 result
= x_text_icon (f
,
1784 (char *) XSTRING ((!NILP (f
->icon_name
)
1793 error ("No icon window available");
1796 XFlush (FRAME_X_DISPLAY (f
));
1801 x_set_font (f
, arg
, oldval
)
1803 Lisp_Object arg
, oldval
;
1806 Lisp_Object fontset_name
;
1809 CHECK_STRING (arg
, 1);
1811 fontset_name
= Fquery_fontset (arg
, Qnil
);
1814 result
= (STRINGP (fontset_name
)
1815 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1816 : x_new_font (f
, XSTRING (arg
)->data
));
1819 if (EQ (result
, Qnil
))
1820 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1821 else if (EQ (result
, Qt
))
1822 error ("The characters of the given font have varying widths");
1823 else if (STRINGP (result
))
1825 store_frame_param (f
, Qfont
, result
);
1826 recompute_basic_faces (f
);
1831 do_pending_window_change (0);
1833 /* Don't call `face-set-after-frame-default' when faces haven't been
1834 initialized yet. This is the case when called from
1835 Fx_create_frame. In that case, the X widget or window doesn't
1836 exist either, and we can end up in x_report_frame_params with a
1837 null widget which gives a segfault. */
1838 if (FRAME_FACE_CACHE (f
))
1840 XSETFRAME (frame
, f
);
1841 call1 (Qface_set_after_frame_default
, frame
);
1846 x_set_border_width (f
, arg
, oldval
)
1848 Lisp_Object arg
, oldval
;
1850 CHECK_NUMBER (arg
, 0);
1852 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1855 if (FRAME_X_WINDOW (f
) != 0)
1856 error ("Cannot change the border width of a window");
1858 f
->output_data
.x
->border_width
= XINT (arg
);
1862 x_set_internal_border_width (f
, arg
, oldval
)
1864 Lisp_Object arg
, oldval
;
1866 int old
= f
->output_data
.x
->internal_border_width
;
1868 CHECK_NUMBER (arg
, 0);
1869 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1870 if (f
->output_data
.x
->internal_border_width
< 0)
1871 f
->output_data
.x
->internal_border_width
= 0;
1873 #ifdef USE_X_TOOLKIT
1874 if (f
->output_data
.x
->edit_widget
)
1875 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1878 if (f
->output_data
.x
->internal_border_width
== old
)
1881 if (FRAME_X_WINDOW (f
) != 0)
1883 x_set_window_size (f
, 0, f
->width
, f
->height
);
1884 SET_FRAME_GARBAGED (f
);
1885 do_pending_window_change (0);
1890 x_set_visibility (f
, value
, oldval
)
1892 Lisp_Object value
, oldval
;
1895 XSETFRAME (frame
, f
);
1898 Fmake_frame_invisible (frame
, Qt
);
1899 else if (EQ (value
, Qicon
))
1900 Ficonify_frame (frame
);
1902 Fmake_frame_visible (frame
);
1906 x_set_menu_bar_lines_1 (window
, n
)
1910 struct window
*w
= XWINDOW (window
);
1912 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1913 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1915 if (INTEGERP (w
->orig_top
))
1916 XSETFASTINT (w
->orig_top
, XFASTINT (w
->orig_top
) + n
);
1917 if (INTEGERP (w
->orig_height
))
1918 XSETFASTINT (w
->orig_height
, XFASTINT (w
->orig_height
) - n
);
1920 /* Handle just the top child in a vertical split. */
1921 if (!NILP (w
->vchild
))
1922 x_set_menu_bar_lines_1 (w
->vchild
, n
);
1924 /* Adjust all children in a horizontal split. */
1925 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1927 w
= XWINDOW (window
);
1928 x_set_menu_bar_lines_1 (window
, n
);
1933 x_set_menu_bar_lines (f
, value
, oldval
)
1935 Lisp_Object value
, oldval
;
1938 #ifndef USE_X_TOOLKIT
1939 int olines
= FRAME_MENU_BAR_LINES (f
);
1942 /* Right now, menu bars don't work properly in minibuf-only frames;
1943 most of the commands try to apply themselves to the minibuffer
1944 frame itself, and get an error because you can't switch buffers
1945 in or split the minibuffer window. */
1946 if (FRAME_MINIBUF_ONLY_P (f
))
1949 if (INTEGERP (value
))
1950 nlines
= XINT (value
);
1954 /* Make sure we redisplay all windows in this frame. */
1955 windows_or_buffers_changed
++;
1957 #ifdef USE_X_TOOLKIT
1958 FRAME_MENU_BAR_LINES (f
) = 0;
1961 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1962 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1963 /* Make sure next redisplay shows the menu bar. */
1964 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1968 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1969 free_frame_menubar (f
);
1970 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1972 f
->output_data
.x
->menubar_widget
= 0;
1974 #else /* not USE_X_TOOLKIT */
1975 FRAME_MENU_BAR_LINES (f
) = nlines
;
1976 x_set_menu_bar_lines_1 (f
->root_window
, nlines
- olines
);
1977 #endif /* not USE_X_TOOLKIT */
1982 /* Set the number of lines used for the tool bar of frame F to VALUE.
1983 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1984 is the old number of tool bar lines. This function changes the
1985 height of all windows on frame F to match the new tool bar height.
1986 The frame's height doesn't change. */
1989 x_set_tool_bar_lines (f
, value
, oldval
)
1991 Lisp_Object value
, oldval
;
1995 /* Use VALUE only if an integer >= 0. */
1996 if (INTEGERP (value
) && XINT (value
) >= 0)
1997 nlines
= XFASTINT (value
);
2001 /* Make sure we redisplay all windows in this frame. */
2002 ++windows_or_buffers_changed
;
2004 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
2005 FRAME_TOOL_BAR_LINES (f
) = nlines
;
2006 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f
), delta
);
2011 /* Set the foreground color for scroll bars on frame F to VALUE.
2012 VALUE should be a string, a color name. If it isn't a string or
2013 isn't a valid color name, do nothing. OLDVAL is the old value of
2014 the frame parameter. */
2017 x_set_scroll_bar_foreground (f
, value
, oldval
)
2019 Lisp_Object value
, oldval
;
2021 unsigned long pixel
;
2023 if (STRINGP (value
))
2024 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2028 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2029 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2031 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2032 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2034 /* Remove all scroll bars because they have wrong colors. */
2035 if (condemn_scroll_bars_hook
)
2036 (*condemn_scroll_bars_hook
) (f
);
2037 if (judge_scroll_bars_hook
)
2038 (*judge_scroll_bars_hook
) (f
);
2040 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2046 /* Set the background color for scroll bars on frame F to VALUE VALUE
2047 should be a string, a color name. If it isn't a string or isn't a
2048 valid color name, do nothing. OLDVAL is the old value of the frame
2052 x_set_scroll_bar_background (f
, value
, oldval
)
2054 Lisp_Object value
, oldval
;
2056 unsigned long pixel
;
2058 if (STRINGP (value
))
2059 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2063 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2064 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2066 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2067 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2069 /* Remove all scroll bars because they have wrong colors. */
2070 if (condemn_scroll_bars_hook
)
2071 (*condemn_scroll_bars_hook
) (f
);
2072 if (judge_scroll_bars_hook
)
2073 (*judge_scroll_bars_hook
) (f
);
2075 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2081 /* Encode Lisp string STRING as a text in a format appropriate for
2082 XICCC (X Inter Client Communication Conventions).
2084 If STRING contains only ASCII characters, do no conversion and
2085 return the string data of STRING. Otherwise, encode the text by
2086 CODING_SYSTEM, and return a newly allocated memory area which
2087 should be freed by `xfree' by a caller.
2089 Store the byte length of resulting text in *TEXT_BYTES.
2091 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2092 which means that the `encoding' of the result can be `STRING'.
2093 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2094 the result should be `COMPOUND_TEXT'. */
2097 x_encode_text (string
, coding_system
, text_bytes
, stringp
)
2098 Lisp_Object string
, coding_system
;
2099 int *text_bytes
, *stringp
;
2101 unsigned char *str
= XSTRING (string
)->data
;
2102 int chars
= XSTRING (string
)->size
;
2103 int bytes
= STRING_BYTES (XSTRING (string
));
2107 struct coding_system coding
;
2109 charset_info
= find_charset_in_text (str
, chars
, bytes
, NULL
, Qnil
);
2110 if (charset_info
== 0)
2112 /* No multibyte character in OBJ. We need not encode it. */
2113 *text_bytes
= bytes
;
2118 setup_coding_system (coding_system
, &coding
);
2119 coding
.src_multibyte
= 1;
2120 coding
.dst_multibyte
= 0;
2121 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
2122 if (coding
.type
== coding_type_iso2022
)
2123 coding
.flags
|= CODING_FLAG_ISO_SAFE
;
2124 bufsize
= encoding_buffer_size (&coding
, bytes
);
2125 buf
= (unsigned char *) xmalloc (bufsize
);
2126 encode_coding (&coding
, str
, buf
, bytes
, bufsize
);
2127 *text_bytes
= coding
.produced
;
2128 *stringp
= (charset_info
== 1 || !EQ (coding_system
, Qcompound_text
));
2133 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2136 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2137 name; if NAME is a string, set F's name to NAME and set
2138 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2140 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2141 suggesting a new name, which lisp code should override; if
2142 F->explicit_name is set, ignore the new name; otherwise, set it. */
2145 x_set_name (f
, name
, explicit)
2150 /* Make sure that requests from lisp code override requests from
2151 Emacs redisplay code. */
2154 /* If we're switching from explicit to implicit, we had better
2155 update the mode lines and thereby update the title. */
2156 if (f
->explicit_name
&& NILP (name
))
2157 update_mode_lines
= 1;
2159 f
->explicit_name
= ! NILP (name
);
2161 else if (f
->explicit_name
)
2164 /* If NAME is nil, set the name to the x_id_name. */
2167 /* Check for no change needed in this very common case
2168 before we do any consing. */
2169 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2170 XSTRING (f
->name
)->data
))
2172 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2175 CHECK_STRING (name
, 0);
2177 /* Don't change the name if it's already NAME. */
2178 if (! NILP (Fstring_equal (name
, f
->name
)))
2183 /* For setting the frame title, the title parameter should override
2184 the name parameter. */
2185 if (! NILP (f
->title
))
2188 if (FRAME_X_WINDOW (f
))
2193 XTextProperty text
, icon
;
2195 Lisp_Object coding_system
;
2197 coding_system
= Vlocale_coding_system
;
2198 if (NILP (coding_system
))
2199 coding_system
= Qcompound_text
;
2200 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2201 text
.encoding
= (stringp
? XA_STRING
2202 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2204 text
.nitems
= bytes
;
2206 if (NILP (f
->icon_name
))
2212 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2214 icon
.encoding
= (stringp
? XA_STRING
2215 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2217 icon
.nitems
= bytes
;
2219 #ifdef USE_X_TOOLKIT
2220 XSetWMName (FRAME_X_DISPLAY (f
),
2221 XtWindow (f
->output_data
.x
->widget
), &text
);
2222 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2224 #else /* not USE_X_TOOLKIT */
2225 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2226 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2227 #endif /* not USE_X_TOOLKIT */
2228 if (!NILP (f
->icon_name
)
2229 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2231 if (text
.value
!= XSTRING (name
)->data
)
2234 #else /* not HAVE_X11R4 */
2235 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2236 XSTRING (name
)->data
);
2237 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2238 XSTRING (name
)->data
);
2239 #endif /* not HAVE_X11R4 */
2244 /* This function should be called when the user's lisp code has
2245 specified a name for the frame; the name will override any set by the
2248 x_explicitly_set_name (f
, arg
, oldval
)
2250 Lisp_Object arg
, oldval
;
2252 x_set_name (f
, arg
, 1);
2255 /* This function should be called by Emacs redisplay code to set the
2256 name; names set this way will never override names set by the user's
2259 x_implicitly_set_name (f
, arg
, oldval
)
2261 Lisp_Object arg
, oldval
;
2263 x_set_name (f
, arg
, 0);
2266 /* Change the title of frame F to NAME.
2267 If NAME is nil, use the frame name as the title.
2269 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2270 name; if NAME is a string, set F's name to NAME and set
2271 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2273 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2274 suggesting a new name, which lisp code should override; if
2275 F->explicit_name is set, ignore the new name; otherwise, set it. */
2278 x_set_title (f
, name
, old_name
)
2280 Lisp_Object name
, old_name
;
2282 /* Don't change the title if it's already NAME. */
2283 if (EQ (name
, f
->title
))
2286 update_mode_lines
= 1;
2293 CHECK_STRING (name
, 0);
2295 if (FRAME_X_WINDOW (f
))
2300 XTextProperty text
, icon
;
2302 Lisp_Object coding_system
;
2304 coding_system
= Vlocale_coding_system
;
2305 if (NILP (coding_system
))
2306 coding_system
= Qcompound_text
;
2307 text
.value
= x_encode_text (name
, coding_system
, &bytes
, &stringp
);
2308 text
.encoding
= (stringp
? XA_STRING
2309 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2311 text
.nitems
= bytes
;
2313 if (NILP (f
->icon_name
))
2319 icon
.value
= x_encode_text (f
->icon_name
, coding_system
,
2321 icon
.encoding
= (stringp
? XA_STRING
2322 : FRAME_X_DISPLAY_INFO (f
)->Xatom_COMPOUND_TEXT
);
2324 icon
.nitems
= bytes
;
2326 #ifdef USE_X_TOOLKIT
2327 XSetWMName (FRAME_X_DISPLAY (f
),
2328 XtWindow (f
->output_data
.x
->widget
), &text
);
2329 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2331 #else /* not USE_X_TOOLKIT */
2332 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2333 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2334 #endif /* not USE_X_TOOLKIT */
2335 if (!NILP (f
->icon_name
)
2336 && icon
.value
!= XSTRING (f
->icon_name
)->data
)
2338 if (text
.value
!= XSTRING (name
)->data
)
2341 #else /* not HAVE_X11R4 */
2342 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2343 XSTRING (name
)->data
);
2344 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2345 XSTRING (name
)->data
);
2346 #endif /* not HAVE_X11R4 */
2352 x_set_autoraise (f
, arg
, oldval
)
2354 Lisp_Object arg
, oldval
;
2356 f
->auto_raise
= !EQ (Qnil
, arg
);
2360 x_set_autolower (f
, arg
, oldval
)
2362 Lisp_Object arg
, oldval
;
2364 f
->auto_lower
= !EQ (Qnil
, arg
);
2368 x_set_unsplittable (f
, arg
, oldval
)
2370 Lisp_Object arg
, oldval
;
2372 f
->no_split
= !NILP (arg
);
2376 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2378 Lisp_Object arg
, oldval
;
2380 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2381 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2382 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2383 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2385 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2387 ? vertical_scroll_bar_none
2389 ? vertical_scroll_bar_right
2390 : vertical_scroll_bar_left
);
2392 /* We set this parameter before creating the X window for the
2393 frame, so we can get the geometry right from the start.
2394 However, if the window hasn't been created yet, we shouldn't
2395 call x_set_window_size. */
2396 if (FRAME_X_WINDOW (f
))
2397 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2398 do_pending_window_change (0);
2403 x_set_scroll_bar_width (f
, arg
, oldval
)
2405 Lisp_Object arg
, oldval
;
2407 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2411 #ifdef USE_TOOLKIT_SCROLL_BARS
2412 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2413 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2414 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2415 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2417 /* Make the actual width at least 14 pixels and a multiple of a
2419 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2421 /* Use all of that space (aside from required margins) for the
2423 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2426 if (FRAME_X_WINDOW (f
))
2427 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2428 do_pending_window_change (0);
2430 else if (INTEGERP (arg
) && XINT (arg
) > 0
2431 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2433 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2434 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2436 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2437 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2438 if (FRAME_X_WINDOW (f
))
2439 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2442 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2443 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2444 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2449 /* Subroutines of creating an X frame. */
2451 /* Make sure that Vx_resource_name is set to a reasonable value.
2452 Fix it up, or set it to `emacs' if it is too hopeless. */
2455 validate_x_resource_name ()
2458 /* Number of valid characters in the resource name. */
2460 /* Number of invalid characters in the resource name. */
2465 if (!STRINGP (Vx_resource_class
))
2466 Vx_resource_class
= build_string (EMACS_CLASS
);
2468 if (STRINGP (Vx_resource_name
))
2470 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2473 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2475 /* Only letters, digits, - and _ are valid in resource names.
2476 Count the valid characters and count the invalid ones. */
2477 for (i
= 0; i
< len
; i
++)
2480 if (! ((c
>= 'a' && c
<= 'z')
2481 || (c
>= 'A' && c
<= 'Z')
2482 || (c
>= '0' && c
<= '9')
2483 || c
== '-' || c
== '_'))
2490 /* Not a string => completely invalid. */
2491 bad_count
= 5, good_count
= 0;
2493 /* If name is valid already, return. */
2497 /* If name is entirely invalid, or nearly so, use `emacs'. */
2499 || (good_count
== 1 && bad_count
> 0))
2501 Vx_resource_name
= build_string ("emacs");
2505 /* Name is partly valid. Copy it and replace the invalid characters
2506 with underscores. */
2508 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2510 for (i
= 0; i
< len
; i
++)
2512 int c
= XSTRING (new)->data
[i
];
2513 if (! ((c
>= 'a' && c
<= 'z')
2514 || (c
>= 'A' && c
<= 'Z')
2515 || (c
>= '0' && c
<= '9')
2516 || c
== '-' || c
== '_'))
2517 XSTRING (new)->data
[i
] = '_';
2522 extern char *x_get_string_resource ();
2524 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2525 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2526 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2527 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2528 the name specified by the `-name' or `-rn' command-line arguments.\n\
2530 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2531 class, respectively. You must specify both of them or neither.\n\
2532 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2533 and the class is `Emacs.CLASS.SUBCLASS'.")
2534 (attribute
, class, component
, subclass
)
2535 Lisp_Object attribute
, class, component
, subclass
;
2537 register char *value
;
2543 CHECK_STRING (attribute
, 0);
2544 CHECK_STRING (class, 0);
2546 if (!NILP (component
))
2547 CHECK_STRING (component
, 1);
2548 if (!NILP (subclass
))
2549 CHECK_STRING (subclass
, 2);
2550 if (NILP (component
) != NILP (subclass
))
2551 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2553 validate_x_resource_name ();
2555 /* Allocate space for the components, the dots which separate them,
2556 and the final '\0'. Make them big enough for the worst case. */
2557 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2558 + (STRINGP (component
)
2559 ? STRING_BYTES (XSTRING (component
)) : 0)
2560 + STRING_BYTES (XSTRING (attribute
))
2563 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2564 + STRING_BYTES (XSTRING (class))
2565 + (STRINGP (subclass
)
2566 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2569 /* Start with emacs.FRAMENAME for the name (the specific one)
2570 and with `Emacs' for the class key (the general one). */
2571 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2572 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2574 strcat (class_key
, ".");
2575 strcat (class_key
, XSTRING (class)->data
);
2577 if (!NILP (component
))
2579 strcat (class_key
, ".");
2580 strcat (class_key
, XSTRING (subclass
)->data
);
2582 strcat (name_key
, ".");
2583 strcat (name_key
, XSTRING (component
)->data
);
2586 strcat (name_key
, ".");
2587 strcat (name_key
, XSTRING (attribute
)->data
);
2589 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2590 name_key
, class_key
);
2592 if (value
!= (char *) 0)
2593 return build_string (value
);
2598 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2601 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2602 struct x_display_info
*dpyinfo
;
2603 Lisp_Object attribute
, class, component
, subclass
;
2605 register char *value
;
2609 CHECK_STRING (attribute
, 0);
2610 CHECK_STRING (class, 0);
2612 if (!NILP (component
))
2613 CHECK_STRING (component
, 1);
2614 if (!NILP (subclass
))
2615 CHECK_STRING (subclass
, 2);
2616 if (NILP (component
) != NILP (subclass
))
2617 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2619 validate_x_resource_name ();
2621 /* Allocate space for the components, the dots which separate them,
2622 and the final '\0'. Make them big enough for the worst case. */
2623 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2624 + (STRINGP (component
)
2625 ? STRING_BYTES (XSTRING (component
)) : 0)
2626 + STRING_BYTES (XSTRING (attribute
))
2629 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2630 + STRING_BYTES (XSTRING (class))
2631 + (STRINGP (subclass
)
2632 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2635 /* Start with emacs.FRAMENAME for the name (the specific one)
2636 and with `Emacs' for the class key (the general one). */
2637 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2638 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2640 strcat (class_key
, ".");
2641 strcat (class_key
, XSTRING (class)->data
);
2643 if (!NILP (component
))
2645 strcat (class_key
, ".");
2646 strcat (class_key
, XSTRING (subclass
)->data
);
2648 strcat (name_key
, ".");
2649 strcat (name_key
, XSTRING (component
)->data
);
2652 strcat (name_key
, ".");
2653 strcat (name_key
, XSTRING (attribute
)->data
);
2655 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2657 if (value
!= (char *) 0)
2658 return build_string (value
);
2663 /* Used when C code wants a resource value. */
2666 x_get_resource_string (attribute
, class)
2667 char *attribute
, *class;
2671 struct frame
*sf
= SELECTED_FRAME ();
2673 /* Allocate space for the components, the dots which separate them,
2674 and the final '\0'. */
2675 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2676 + strlen (attribute
) + 2);
2677 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2678 + strlen (class) + 2);
2680 sprintf (name_key
, "%s.%s",
2681 XSTRING (Vinvocation_name
)->data
,
2683 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2685 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2686 name_key
, class_key
);
2689 /* Types we might convert a resource string into. */
2699 /* Return the value of parameter PARAM.
2701 First search ALIST, then Vdefault_frame_alist, then the X defaults
2702 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2704 Convert the resource to the type specified by desired_type.
2706 If no default is specified, return Qunbound. If you call
2707 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2708 and don't let it get stored in any Lisp-visible variables! */
2711 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2712 struct x_display_info
*dpyinfo
;
2713 Lisp_Object alist
, param
;
2716 enum resource_types type
;
2718 register Lisp_Object tem
;
2720 tem
= Fassq (param
, alist
);
2722 tem
= Fassq (param
, Vdefault_frame_alist
);
2728 tem
= display_x_get_resource (dpyinfo
,
2729 build_string (attribute
),
2730 build_string (class),
2738 case RES_TYPE_NUMBER
:
2739 return make_number (atoi (XSTRING (tem
)->data
));
2741 case RES_TYPE_FLOAT
:
2742 return make_float (atof (XSTRING (tem
)->data
));
2744 case RES_TYPE_BOOLEAN
:
2745 tem
= Fdowncase (tem
);
2746 if (!strcmp (XSTRING (tem
)->data
, "on")
2747 || !strcmp (XSTRING (tem
)->data
, "true"))
2752 case RES_TYPE_STRING
:
2755 case RES_TYPE_SYMBOL
:
2756 /* As a special case, we map the values `true' and `on'
2757 to Qt, and `false' and `off' to Qnil. */
2760 lower
= Fdowncase (tem
);
2761 if (!strcmp (XSTRING (lower
)->data
, "on")
2762 || !strcmp (XSTRING (lower
)->data
, "true"))
2764 else if (!strcmp (XSTRING (lower
)->data
, "off")
2765 || !strcmp (XSTRING (lower
)->data
, "false"))
2768 return Fintern (tem
, Qnil
);
2781 /* Like x_get_arg, but also record the value in f->param_alist. */
2784 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2786 Lisp_Object alist
, param
;
2789 enum resource_types type
;
2793 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2794 attribute
, class, type
);
2796 store_frame_param (f
, param
, value
);
2801 /* Record in frame F the specified or default value according to ALIST
2802 of the parameter named PROP (a Lisp symbol).
2803 If no value is specified for PROP, look for an X default for XPROP
2804 on the frame named NAME.
2805 If that is not found either, use the value DEFLT. */
2808 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2815 enum resource_types type
;
2819 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2820 if (EQ (tem
, Qunbound
))
2822 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2827 /* Record in frame F the specified or default value according to ALIST
2828 of the parameter named PROP (a Lisp symbol). If no value is
2829 specified for PROP, look for an X default for XPROP on the frame
2830 named NAME. If that is not found either, use the value DEFLT. */
2833 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2842 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2845 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2846 if (EQ (tem
, Qunbound
))
2848 #ifdef USE_TOOLKIT_SCROLL_BARS
2850 /* See if an X resource for the scroll bar color has been
2852 tem
= display_x_get_resource (dpyinfo
,
2853 build_string (foreground_p
2857 build_string ("verticalScrollBar"),
2861 /* If nothing has been specified, scroll bars will use a
2862 toolkit-dependent default. Because these defaults are
2863 difficult to get at without actually creating a scroll
2864 bar, use nil to indicate that no color has been
2869 #else /* not USE_TOOLKIT_SCROLL_BARS */
2873 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2876 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2882 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2883 "Parse an X-style geometry string STRING.\n\
2884 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2885 The properties returned may include `top', `left', `height', and `width'.\n\
2886 The value of `left' or `top' may be an integer,\n\
2887 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2888 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2893 unsigned int width
, height
;
2896 CHECK_STRING (string
, 0);
2898 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2899 &x
, &y
, &width
, &height
);
2902 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2903 error ("Must specify both x and y position, or neither");
2907 if (geometry
& XValue
)
2909 Lisp_Object element
;
2911 if (x
>= 0 && (geometry
& XNegative
))
2912 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2913 else if (x
< 0 && ! (geometry
& XNegative
))
2914 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2916 element
= Fcons (Qleft
, make_number (x
));
2917 result
= Fcons (element
, result
);
2920 if (geometry
& YValue
)
2922 Lisp_Object element
;
2924 if (y
>= 0 && (geometry
& YNegative
))
2925 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2926 else if (y
< 0 && ! (geometry
& YNegative
))
2927 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2929 element
= Fcons (Qtop
, make_number (y
));
2930 result
= Fcons (element
, result
);
2933 if (geometry
& WidthValue
)
2934 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2935 if (geometry
& HeightValue
)
2936 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2941 /* Calculate the desired size and position of this window,
2942 and return the flags saying which aspects were specified.
2944 This function does not make the coordinates positive. */
2946 #define DEFAULT_ROWS 40
2947 #define DEFAULT_COLS 80
2950 x_figure_window_size (f
, parms
)
2954 register Lisp_Object tem0
, tem1
, tem2
;
2955 long window_prompting
= 0;
2956 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2958 /* Default values if we fall through.
2959 Actually, if that happens we should get
2960 window manager prompting. */
2961 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2962 f
->height
= DEFAULT_ROWS
;
2963 /* Window managers expect that if program-specified
2964 positions are not (0,0), they're intentional, not defaults. */
2965 f
->output_data
.x
->top_pos
= 0;
2966 f
->output_data
.x
->left_pos
= 0;
2968 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
2969 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
2970 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
2971 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2973 if (!EQ (tem0
, Qunbound
))
2975 CHECK_NUMBER (tem0
, 0);
2976 f
->height
= XINT (tem0
);
2978 if (!EQ (tem1
, Qunbound
))
2980 CHECK_NUMBER (tem1
, 0);
2981 SET_FRAME_WIDTH (f
, XINT (tem1
));
2983 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2984 window_prompting
|= USSize
;
2986 window_prompting
|= PSize
;
2989 f
->output_data
.x
->vertical_scroll_bar_extra
2990 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2992 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2993 f
->output_data
.x
->flags_areas_extra
2994 = FRAME_FLAGS_AREA_WIDTH (f
);
2995 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2996 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2998 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
2999 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
3000 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
3001 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
3003 if (EQ (tem0
, Qminus
))
3005 f
->output_data
.x
->top_pos
= 0;
3006 window_prompting
|= YNegative
;
3008 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
3009 && CONSP (XCDR (tem0
))
3010 && INTEGERP (XCAR (XCDR (tem0
))))
3012 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
3013 window_prompting
|= YNegative
;
3015 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
3016 && CONSP (XCDR (tem0
))
3017 && INTEGERP (XCAR (XCDR (tem0
))))
3019 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
3021 else if (EQ (tem0
, Qunbound
))
3022 f
->output_data
.x
->top_pos
= 0;
3025 CHECK_NUMBER (tem0
, 0);
3026 f
->output_data
.x
->top_pos
= XINT (tem0
);
3027 if (f
->output_data
.x
->top_pos
< 0)
3028 window_prompting
|= YNegative
;
3031 if (EQ (tem1
, Qminus
))
3033 f
->output_data
.x
->left_pos
= 0;
3034 window_prompting
|= XNegative
;
3036 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
3037 && CONSP (XCDR (tem1
))
3038 && INTEGERP (XCAR (XCDR (tem1
))))
3040 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
3041 window_prompting
|= XNegative
;
3043 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
3044 && CONSP (XCDR (tem1
))
3045 && INTEGERP (XCAR (XCDR (tem1
))))
3047 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
3049 else if (EQ (tem1
, Qunbound
))
3050 f
->output_data
.x
->left_pos
= 0;
3053 CHECK_NUMBER (tem1
, 0);
3054 f
->output_data
.x
->left_pos
= XINT (tem1
);
3055 if (f
->output_data
.x
->left_pos
< 0)
3056 window_prompting
|= XNegative
;
3059 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
3060 window_prompting
|= USPosition
;
3062 window_prompting
|= PPosition
;
3065 return window_prompting
;
3068 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3071 XSetWMProtocols (dpy
, w
, protocols
, count
)
3078 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
3079 if (prop
== None
) return False
;
3080 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
3081 (unsigned char *) protocols
, count
);
3084 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3086 #ifdef USE_X_TOOLKIT
3088 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3089 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3090 already be present because of the toolkit (Motif adds some of them,
3091 for example, but Xt doesn't). */
3094 hack_wm_protocols (f
, widget
)
3098 Display
*dpy
= XtDisplay (widget
);
3099 Window w
= XtWindow (widget
);
3100 int need_delete
= 1;
3106 Atom type
, *atoms
= 0;
3108 unsigned long nitems
= 0;
3109 unsigned long bytes_after
;
3111 if ((XGetWindowProperty (dpy
, w
,
3112 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3113 (long)0, (long)100, False
, XA_ATOM
,
3114 &type
, &format
, &nitems
, &bytes_after
,
3115 (unsigned char **) &atoms
)
3117 && format
== 32 && type
== XA_ATOM
)
3121 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3123 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3125 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3128 if (atoms
) XFree ((char *) atoms
);
3134 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3136 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3138 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3140 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3141 XA_ATOM
, 32, PropModeAppend
,
3142 (unsigned char *) props
, count
);
3150 /* Support routines for XIC (X Input Context). */
3154 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3155 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3158 /* Supported XIM styles, ordered by preferenc. */
3160 static XIMStyle supported_xim_styles
[] =
3162 XIMPreeditPosition
| XIMStatusArea
,
3163 XIMPreeditPosition
| XIMStatusNothing
,
3164 XIMPreeditPosition
| XIMStatusNone
,
3165 XIMPreeditNothing
| XIMStatusArea
,
3166 XIMPreeditNothing
| XIMStatusNothing
,
3167 XIMPreeditNothing
| XIMStatusNone
,
3168 XIMPreeditNone
| XIMStatusArea
,
3169 XIMPreeditNone
| XIMStatusNothing
,
3170 XIMPreeditNone
| XIMStatusNone
,
3175 /* Create an X fontset on frame F with base font name
3179 xic_create_xfontset (f
, base_fontname
)
3181 char *base_fontname
;
3184 char **missing_list
;
3188 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3189 base_fontname
, &missing_list
,
3190 &missing_count
, &def_string
);
3192 XFreeStringList (missing_list
);
3194 /* No need to free def_string. */
3199 /* Value is the best input style, given user preferences USER (already
3200 checked to be supported by Emacs), and styles supported by the
3201 input method XIM. */
3204 best_xim_style (user
, xim
)
3210 for (i
= 0; i
< user
->count_styles
; ++i
)
3211 for (j
= 0; j
< xim
->count_styles
; ++j
)
3212 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3213 return user
->supported_styles
[i
];
3215 /* Return the default style. */
3216 return XIMPreeditNothing
| XIMStatusNothing
;
3219 /* Create XIC for frame F. */
3222 create_frame_xic (f
)
3227 XFontSet xfs
= NULL
;
3228 static XIMStyle xic_style
;
3233 xim
= FRAME_X_XIM (f
);
3238 XVaNestedList preedit_attr
;
3239 XVaNestedList status_attr
;
3240 char *base_fontname
;
3243 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3244 spot
.x
= 0; spot
.y
= 1;
3245 /* Create X fontset. */
3246 fontset
= FRAME_FONTSET (f
);
3248 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3251 /* Determine the base fontname from the ASCII font name of
3253 char *ascii_font
= (char *) XSTRING (fontset_ascii (fontset
))->data
;
3254 char *p
= ascii_font
;
3257 for (i
= 0; *p
; p
++)
3260 /* As the font name doesn't conform to XLFD, we can't
3261 modify it to get a suitable base fontname for the
3263 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3266 int len
= strlen (ascii_font
) + 1;
3269 for (i
= 0, p
= ascii_font
; i
< 8; p
++)
3278 base_fontname
= (char *) alloca (len
);
3279 bzero (base_fontname
, len
);
3280 strcpy (base_fontname
, "-*-*-");
3281 bcopy (p1
, base_fontname
+ 5, p
- p1
);
3282 strcat (base_fontname
, "*-*-*-*-*-*-*");
3285 xfs
= xic_create_xfontset (f
, base_fontname
);
3287 /* Determine XIC style. */
3290 XIMStyles supported_list
;
3291 supported_list
.count_styles
= (sizeof supported_xim_styles
3292 / sizeof supported_xim_styles
[0]);
3293 supported_list
.supported_styles
= supported_xim_styles
;
3294 xic_style
= best_xim_style (&supported_list
,
3295 FRAME_X_XIM_STYLES (f
));
3298 preedit_attr
= XVaCreateNestedList (0,
3301 FRAME_FOREGROUND_PIXEL (f
),
3303 FRAME_BACKGROUND_PIXEL (f
),
3304 (xic_style
& XIMPreeditPosition
3309 status_attr
= XVaCreateNestedList (0,
3315 FRAME_FOREGROUND_PIXEL (f
),
3317 FRAME_BACKGROUND_PIXEL (f
),
3320 xic
= XCreateIC (xim
,
3321 XNInputStyle
, xic_style
,
3322 XNClientWindow
, FRAME_X_WINDOW(f
),
3323 XNFocusWindow
, FRAME_X_WINDOW(f
),
3324 XNStatusAttributes
, status_attr
,
3325 XNPreeditAttributes
, preedit_attr
,
3327 XFree (preedit_attr
);
3328 XFree (status_attr
);
3331 FRAME_XIC (f
) = xic
;
3332 FRAME_XIC_STYLE (f
) = xic_style
;
3333 FRAME_XIC_FONTSET (f
) = xfs
;
3337 /* Destroy XIC and free XIC fontset of frame F, if any. */
3343 if (FRAME_XIC (f
) == NULL
)
3346 XDestroyIC (FRAME_XIC (f
));
3347 if (FRAME_XIC_FONTSET (f
))
3348 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3350 FRAME_XIC (f
) = NULL
;
3351 FRAME_XIC_FONTSET (f
) = NULL
;
3355 /* Place preedit area for XIC of window W's frame to specified
3356 pixel position X/Y. X and Y are relative to window W. */
3359 xic_set_preeditarea (w
, x
, y
)
3363 struct frame
*f
= XFRAME (w
->frame
);
3367 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3368 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3369 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3370 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3375 /* Place status area for XIC in bottom right corner of frame F.. */
3378 xic_set_statusarea (f
)
3381 XIC xic
= FRAME_XIC (f
);
3386 /* Negotiate geometry of status area. If input method has existing
3387 status area, use its current size. */
3388 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3389 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3390 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3393 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3394 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3397 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3399 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3400 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3404 area
.width
= needed
->width
;
3405 area
.height
= needed
->height
;
3406 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3407 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3408 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3411 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3412 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3417 /* Set X fontset for XIC of frame F, using base font name
3418 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3421 xic_set_xfontset (f
, base_fontname
)
3423 char *base_fontname
;
3428 xfs
= xic_create_xfontset (f
, base_fontname
);
3430 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3431 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3432 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3433 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3434 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3437 if (FRAME_XIC_FONTSET (f
))
3438 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3439 FRAME_XIC_FONTSET (f
) = xfs
;
3442 #endif /* HAVE_X_I18N */
3446 #ifdef USE_X_TOOLKIT
3448 /* Create and set up the X widget for frame F. */
3451 x_window (f
, window_prompting
, minibuffer_only
)
3453 long window_prompting
;
3454 int minibuffer_only
;
3456 XClassHint class_hints
;
3457 XSetWindowAttributes attributes
;
3458 unsigned long attribute_mask
;
3459 Widget shell_widget
;
3461 Widget frame_widget
;
3467 /* Use the resource name as the top-level widget name
3468 for looking up resources. Make a non-Lisp copy
3469 for the window manager, so GC relocation won't bother it.
3471 Elsewhere we specify the window name for the window manager. */
3474 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3475 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3476 strcpy (f
->namebuf
, str
);
3480 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3481 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3482 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3483 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3484 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3485 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3486 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3487 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3488 applicationShellWidgetClass
,
3489 FRAME_X_DISPLAY (f
), al
, ac
);
3491 f
->output_data
.x
->widget
= shell_widget
;
3492 /* maybe_set_screen_title_format (shell_widget); */
3494 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3495 (widget_value
*) NULL
,
3496 shell_widget
, False
,
3500 (lw_callback
) NULL
);
3503 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3504 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3505 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3506 XtSetValues (pane_widget
, al
, ac
);
3507 f
->output_data
.x
->column_widget
= pane_widget
;
3509 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3510 the emacs screen when changing menubar. This reduces flickering. */
3513 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3514 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3515 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3516 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3517 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3518 XtSetArg (al
[ac
], XtNvisual
, FRAME_X_VISUAL (f
)); ac
++;
3519 XtSetArg (al
[ac
], XtNdepth
, FRAME_X_DISPLAY_INFO (f
)->n_planes
); ac
++;
3520 XtSetArg (al
[ac
], XtNcolormap
, FRAME_X_COLORMAP (f
)); ac
++;
3521 frame_widget
= XtCreateWidget (f
->namebuf
, emacsFrameClass
, pane_widget
,
3524 f
->output_data
.x
->edit_widget
= frame_widget
;
3526 XtManageChild (frame_widget
);
3528 /* Do some needed geometry management. */
3531 char *tem
, shell_position
[32];
3534 int extra_borders
= 0;
3536 = (f
->output_data
.x
->menubar_widget
3537 ? (f
->output_data
.x
->menubar_widget
->core
.height
3538 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3541 #if 0 /* Experimentally, we now get the right results
3542 for -geometry -0-0 without this. 24 Aug 96, rms. */
3543 if (FRAME_EXTERNAL_MENU_BAR (f
))
3546 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3547 menubar_size
+= ibw
;
3551 f
->output_data
.x
->menubar_height
= menubar_size
;
3554 /* Motif seems to need this amount added to the sizes
3555 specified for the shell widget. The Athena/Lucid widgets don't.
3556 Both conclusions reached experimentally. -- rms. */
3557 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3558 &extra_borders
, NULL
);
3562 /* Convert our geometry parameters into a geometry string
3564 Note that we do not specify here whether the position
3565 is a user-specified or program-specified one.
3566 We pass that information later, in x_wm_set_size_hints. */
3568 int left
= f
->output_data
.x
->left_pos
;
3569 int xneg
= window_prompting
& XNegative
;
3570 int top
= f
->output_data
.x
->top_pos
;
3571 int yneg
= window_prompting
& YNegative
;
3577 if (window_prompting
& USPosition
)
3578 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3579 PIXEL_WIDTH (f
) + extra_borders
,
3580 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3581 (xneg
? '-' : '+'), left
,
3582 (yneg
? '-' : '+'), top
);
3584 sprintf (shell_position
, "=%dx%d",
3585 PIXEL_WIDTH (f
) + extra_borders
,
3586 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3589 len
= strlen (shell_position
) + 1;
3590 /* We don't free this because we don't know whether
3591 it is safe to free it while the frame exists.
3592 It isn't worth the trouble of arranging to free it
3593 when the frame is deleted. */
3594 tem
= (char *) xmalloc (len
);
3595 strncpy (tem
, shell_position
, len
);
3596 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3597 XtSetValues (shell_widget
, al
, ac
);
3600 XtManageChild (pane_widget
);
3601 XtRealizeWidget (shell_widget
);
3603 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3605 validate_x_resource_name ();
3607 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3608 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3609 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3612 FRAME_XIC (f
) = NULL
;
3614 create_frame_xic (f
);
3618 f
->output_data
.x
->wm_hints
.input
= True
;
3619 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3620 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3621 &f
->output_data
.x
->wm_hints
);
3623 hack_wm_protocols (f
, shell_widget
);
3626 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3629 /* Do a stupid property change to force the server to generate a
3630 PropertyNotify event so that the event_stream server timestamp will
3631 be initialized to something relevant to the time we created the window.
3633 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3634 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3635 XA_ATOM
, 32, PropModeAppend
,
3636 (unsigned char*) NULL
, 0);
3638 /* Make all the standard events reach the Emacs frame. */
3639 attributes
.event_mask
= STANDARD_EVENT_SET
;
3644 /* XIM server might require some X events. */
3645 unsigned long fevent
= NoEventMask
;
3646 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3647 attributes
.event_mask
|= fevent
;
3649 #endif /* HAVE_X_I18N */
3651 attribute_mask
= CWEventMask
;
3652 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3653 attribute_mask
, &attributes
);
3655 XtMapWidget (frame_widget
);
3657 /* x_set_name normally ignores requests to set the name if the
3658 requested name is the same as the current name. This is the one
3659 place where that assumption isn't correct; f->name is set, but
3660 the X server hasn't been told. */
3663 int explicit = f
->explicit_name
;
3665 f
->explicit_name
= 0;
3668 x_set_name (f
, name
, explicit);
3671 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3672 f
->output_data
.x
->text_cursor
);
3676 /* This is a no-op, except under Motif. Make sure main areas are
3677 set to something reasonable, in case we get an error later. */
3678 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3681 #else /* not USE_X_TOOLKIT */
3683 /* Create and set up the X window for frame F. */
3690 XClassHint class_hints
;
3691 XSetWindowAttributes attributes
;
3692 unsigned long attribute_mask
;
3694 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3695 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3696 attributes
.bit_gravity
= StaticGravity
;
3697 attributes
.backing_store
= NotUseful
;
3698 attributes
.save_under
= True
;
3699 attributes
.event_mask
= STANDARD_EVENT_SET
;
3700 attributes
.colormap
= FRAME_X_COLORMAP (f
);
3701 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
| CWEventMask
3706 = XCreateWindow (FRAME_X_DISPLAY (f
),
3707 f
->output_data
.x
->parent_desc
,
3708 f
->output_data
.x
->left_pos
,
3709 f
->output_data
.x
->top_pos
,
3710 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3711 f
->output_data
.x
->border_width
,
3712 CopyFromParent
, /* depth */
3713 InputOutput
, /* class */
3715 attribute_mask
, &attributes
);
3719 create_frame_xic (f
);
3722 /* XIM server might require some X events. */
3723 unsigned long fevent
= NoEventMask
;
3724 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3725 attributes
.event_mask
|= fevent
;
3726 attribute_mask
= CWEventMask
;
3727 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3728 attribute_mask
, &attributes
);
3731 #endif /* HAVE_X_I18N */
3733 validate_x_resource_name ();
3735 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3736 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3737 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3739 /* The menubar is part of the ordinary display;
3740 it does not count in addition to the height of the window. */
3741 f
->output_data
.x
->menubar_height
= 0;
3743 /* This indicates that we use the "Passive Input" input model.
3744 Unless we do this, we don't get the Focus{In,Out} events that we
3745 need to draw the cursor correctly. Accursed bureaucrats.
3746 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3748 f
->output_data
.x
->wm_hints
.input
= True
;
3749 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3750 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3751 &f
->output_data
.x
->wm_hints
);
3752 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3754 /* Request "save yourself" and "delete window" commands from wm. */
3757 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3758 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3759 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3762 /* x_set_name normally ignores requests to set the name if the
3763 requested name is the same as the current name. This is the one
3764 place where that assumption isn't correct; f->name is set, but
3765 the X server hasn't been told. */
3768 int explicit = f
->explicit_name
;
3770 f
->explicit_name
= 0;
3773 x_set_name (f
, name
, explicit);
3776 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3777 f
->output_data
.x
->text_cursor
);
3781 if (FRAME_X_WINDOW (f
) == 0)
3782 error ("Unable to create window");
3785 #endif /* not USE_X_TOOLKIT */
3787 /* Handle the icon stuff for this window. Perhaps later we might
3788 want an x_set_icon_position which can be called interactively as
3796 Lisp_Object icon_x
, icon_y
;
3797 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3799 /* Set the position of the icon. Note that twm groups all
3800 icons in an icon window. */
3801 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3802 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3803 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3805 CHECK_NUMBER (icon_x
, 0);
3806 CHECK_NUMBER (icon_y
, 0);
3808 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3809 error ("Both left and top icon corners of icon must be specified");
3813 if (! EQ (icon_x
, Qunbound
))
3814 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3816 /* Start up iconic or window? */
3817 x_wm_set_window_state
3818 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3823 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3830 /* Make the GC's needed for this window, setting the
3831 background, border and mouse colors; also create the
3832 mouse cursor and the gray border tile. */
3834 static char cursor_bits
[] =
3836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3846 XGCValues gc_values
;
3850 /* Create the GC's of this frame.
3851 Note that many default values are used. */
3854 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3855 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3856 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3857 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3858 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3860 GCLineWidth
| GCFont
3861 | GCForeground
| GCBackground
,
3864 /* Reverse video style. */
3865 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3866 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3867 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3869 GCFont
| GCForeground
| GCBackground
3873 /* Cursor has cursor-color background, background-color foreground. */
3874 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3875 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3876 gc_values
.fill_style
= FillOpaqueStippled
;
3878 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3879 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3880 cursor_bits
, 16, 16);
3881 f
->output_data
.x
->cursor_gc
3882 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3883 (GCFont
| GCForeground
| GCBackground
3884 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3888 f
->output_data
.x
->white_relief
.gc
= 0;
3889 f
->output_data
.x
->black_relief
.gc
= 0;
3891 /* Create the gray border tile used when the pointer is not in
3892 the frame. Since this depends on the frame's pixel values,
3893 this must be done on a per-frame basis. */
3894 f
->output_data
.x
->border_tile
3895 = (XCreatePixmapFromBitmapData
3896 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3897 gray_bits
, gray_width
, gray_height
,
3898 f
->output_data
.x
->foreground_pixel
,
3899 f
->output_data
.x
->background_pixel
,
3900 DefaultDepth (FRAME_X_DISPLAY (f
),
3901 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3906 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3908 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3909 Returns an Emacs frame object.\n\
3910 ALIST is an alist of frame parameters.\n\
3911 If the parameters specify that the frame should not have a minibuffer,\n\
3912 and do not specify a specific minibuffer window to use,\n\
3913 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3914 be shared by the new frame.\n\
3916 This function is an internal primitive--use `make-frame' instead.")
3921 Lisp_Object frame
, tem
;
3923 int minibuffer_only
= 0;
3924 long window_prompting
= 0;
3926 int count
= specpdl_ptr
- specpdl
;
3927 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3928 Lisp_Object display
;
3929 struct x_display_info
*dpyinfo
= NULL
;
3935 /* Use this general default value to start with
3936 until we know if this frame has a specified name. */
3937 Vx_resource_name
= Vinvocation_name
;
3939 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3940 if (EQ (display
, Qunbound
))
3942 dpyinfo
= check_x_display_info (display
);
3944 kb
= dpyinfo
->kboard
;
3946 kb
= &the_only_kboard
;
3949 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3951 && ! EQ (name
, Qunbound
)
3953 error ("Invalid frame name--not a string or nil");
3956 Vx_resource_name
= name
;
3958 /* See if parent window is specified. */
3959 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
3960 if (EQ (parent
, Qunbound
))
3962 if (! NILP (parent
))
3963 CHECK_NUMBER (parent
, 0);
3965 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3966 /* No need to protect DISPLAY because that's not used after passing
3967 it to make_frame_without_minibuffer. */
3969 GCPRO4 (parms
, parent
, name
, frame
);
3970 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
3972 if (EQ (tem
, Qnone
) || NILP (tem
))
3973 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3974 else if (EQ (tem
, Qonly
))
3976 f
= make_minibuffer_frame ();
3977 minibuffer_only
= 1;
3979 else if (WINDOWP (tem
))
3980 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3984 XSETFRAME (frame
, f
);
3986 /* Note that X Windows does support scroll bars. */
3987 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3989 f
->output_method
= output_x_window
;
3990 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
3991 bzero (f
->output_data
.x
, sizeof (struct x_output
));
3992 f
->output_data
.x
->icon_bitmap
= -1;
3993 f
->output_data
.x
->fontset
= -1;
3994 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
3995 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
3998 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
4000 if (! STRINGP (f
->icon_name
))
4001 f
->icon_name
= Qnil
;
4003 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
4005 FRAME_KBOARD (f
) = kb
;
4008 /* These colors will be set anyway later, but it's important
4009 to get the color reference counts right, so initialize them! */
4012 struct gcpro gcpro1
;
4014 black
= build_string ("black");
4016 f
->output_data
.x
->foreground_pixel
4017 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4018 f
->output_data
.x
->background_pixel
4019 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4020 f
->output_data
.x
->cursor_pixel
4021 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4022 f
->output_data
.x
->cursor_foreground_pixel
4023 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4024 f
->output_data
.x
->border_pixel
4025 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4026 f
->output_data
.x
->mouse_pixel
4027 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
4031 /* Specify the parent under which to make this X window. */
4035 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
4036 f
->output_data
.x
->explicit_parent
= 1;
4040 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4041 f
->output_data
.x
->explicit_parent
= 0;
4044 /* Set the name; the functions to which we pass f expect the name to
4046 if (EQ (name
, Qunbound
) || NILP (name
))
4048 f
->name
= build_string (dpyinfo
->x_id_name
);
4049 f
->explicit_name
= 0;
4054 f
->explicit_name
= 1;
4055 /* use the frame's title when getting resources for this frame. */
4056 specbind (Qx_resource_name
, name
);
4059 /* Extract the window parameters from the supplied values
4060 that are needed to determine window geometry. */
4064 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4067 /* First, try whatever font the caller has specified. */
4070 tem
= Fquery_fontset (font
, Qnil
);
4072 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4074 font
= x_new_font (f
, XSTRING (font
)->data
);
4077 /* Try out a font which we hope has bold and italic variations. */
4078 if (!STRINGP (font
))
4079 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4080 if (!STRINGP (font
))
4081 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4082 if (! STRINGP (font
))
4083 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4084 if (! STRINGP (font
))
4085 /* This was formerly the first thing tried, but it finds too many fonts
4086 and takes too long. */
4087 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4088 /* If those didn't work, look for something which will at least work. */
4089 if (! STRINGP (font
))
4090 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4092 if (! STRINGP (font
))
4093 font
= build_string ("fixed");
4095 x_default_parameter (f
, parms
, Qfont
, font
,
4096 "font", "Font", RES_TYPE_STRING
);
4100 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4101 whereby it fails to get any font. */
4102 xlwmenu_default_font
= f
->output_data
.x
->font
;
4105 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4106 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4108 /* This defaults to 2 in order to match xterm. We recognize either
4109 internalBorderWidth or internalBorder (which is what xterm calls
4111 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4115 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
4116 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
4117 if (! EQ (value
, Qunbound
))
4118 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4121 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
4122 "internalBorderWidth", "internalBorderWidth",
4124 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
4125 "verticalScrollBars", "ScrollBars",
4128 /* Also do the stuff which must be set before the window exists. */
4129 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4130 "foreground", "Foreground", RES_TYPE_STRING
);
4131 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4132 "background", "Background", RES_TYPE_STRING
);
4133 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4134 "pointerColor", "Foreground", RES_TYPE_STRING
);
4135 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4136 "cursorColor", "Foreground", RES_TYPE_STRING
);
4137 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4138 "borderColor", "BorderColor", RES_TYPE_STRING
);
4139 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
4140 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4141 x_default_parameter (f
, parms
, Qline_spacing
, Qnil
,
4142 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4144 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4145 "scrollBarForeground",
4146 "ScrollBarForeground", 1);
4147 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4148 "scrollBarBackground",
4149 "ScrollBarBackground", 0);
4151 /* Init faces before x_default_parameter is called for scroll-bar
4152 parameters because that function calls x_set_scroll_bar_width,
4153 which calls change_frame_size, which calls Fset_window_buffer,
4154 which runs hooks, which call Fvertical_motion. At the end, we
4155 end up in init_iterator with a null face cache, which should not
4157 init_frame_faces (f
);
4159 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4160 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4161 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (0),
4162 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4163 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4164 "bufferPredicate", "BufferPredicate",
4166 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4167 "title", "Title", RES_TYPE_STRING
);
4169 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4170 window_prompting
= x_figure_window_size (f
, parms
);
4172 if (window_prompting
& XNegative
)
4174 if (window_prompting
& YNegative
)
4175 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4177 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4181 if (window_prompting
& YNegative
)
4182 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4184 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4187 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4189 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4190 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4192 /* Create the X widget or window. Add the tool-bar height to the
4193 initial frame height so that the user gets a text display area of
4194 the size he specified with -g or via .Xdefaults. Later changes
4195 of the tool-bar height don't change the frame size. This is done
4196 so that users can create tall Emacs frames without having to
4197 guess how tall the tool-bar will get. */
4198 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
4200 #ifdef USE_X_TOOLKIT
4201 x_window (f
, window_prompting
, minibuffer_only
);
4209 /* Now consider the frame official. */
4210 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4211 Vframe_list
= Fcons (frame
, Vframe_list
);
4213 /* We need to do this after creating the X window, so that the
4214 icon-creation functions can say whose icon they're describing. */
4215 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4216 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4218 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4219 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4220 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4221 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4222 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4223 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4224 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4225 "scrollBarWidth", "ScrollBarWidth",
4228 /* Dimensions, especially f->height, must be done via change_frame_size.
4229 Change will not be effected unless different from the current
4234 SET_FRAME_WIDTH (f
, 0);
4235 change_frame_size (f
, height
, width
, 1, 0, 0);
4237 /* Set up faces after all frame parameters are known. */
4238 call1 (Qface_set_after_frame_default
, frame
);
4240 #ifdef USE_X_TOOLKIT
4241 /* Create the menu bar. */
4242 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4244 /* If this signals an error, we haven't set size hints for the
4245 frame and we didn't make it visible. */
4246 initialize_frame_menubar (f
);
4248 /* This is a no-op, except under Motif where it arranges the
4249 main window for the widgets on it. */
4250 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4251 f
->output_data
.x
->menubar_widget
,
4252 f
->output_data
.x
->edit_widget
);
4254 #endif /* USE_X_TOOLKIT */
4256 /* Tell the server what size and position, etc, we want, and how
4257 badly we want them. This should be done after we have the menu
4258 bar so that its size can be taken into account. */
4260 x_wm_set_size_hint (f
, window_prompting
, 0);
4263 /* Make the window appear on the frame and enable display, unless
4264 the caller says not to. However, with explicit parent, Emacs
4265 cannot control visibility, so don't try. */
4266 if (! f
->output_data
.x
->explicit_parent
)
4268 Lisp_Object visibility
;
4270 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4272 if (EQ (visibility
, Qunbound
))
4275 if (EQ (visibility
, Qicon
))
4276 x_iconify_frame (f
);
4277 else if (! NILP (visibility
))
4278 x_make_frame_visible (f
);
4280 /* Must have been Qnil. */
4285 return unbind_to (count
, frame
);
4288 /* FRAME is used only to get a handle on the X display. We don't pass the
4289 display info directly because we're called from frame.c, which doesn't
4290 know about that structure. */
4293 x_get_focus_frame (frame
)
4294 struct frame
*frame
;
4296 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4298 if (! dpyinfo
->x_focus_frame
)
4301 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4306 /* In certain situations, when the window manager follows a
4307 click-to-focus policy, there seems to be no way around calling
4308 XSetInputFocus to give another frame the input focus .
4310 In an ideal world, XSetInputFocus should generally be avoided so
4311 that applications don't interfere with the window manager's focus
4312 policy. But I think it's okay to use when it's clearly done
4313 following a user-command. */
4315 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4316 "Set the input focus to FRAME.\n\
4317 FRAME nil means use the selected frame.")
4321 struct frame
*f
= check_x_frame (frame
);
4322 Display
*dpy
= FRAME_X_DISPLAY (f
);
4326 count
= x_catch_errors (dpy
);
4327 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4328 RevertToParent
, CurrentTime
);
4329 x_uncatch_errors (dpy
, count
);
4336 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4337 "Internal function called by `color-defined-p', which see.")
4339 Lisp_Object color
, frame
;
4342 FRAME_PTR f
= check_x_frame (frame
);
4344 CHECK_STRING (color
, 1);
4346 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4352 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4353 "Internal function called by `color-values', which see.")
4355 Lisp_Object color
, frame
;
4358 FRAME_PTR f
= check_x_frame (frame
);
4360 CHECK_STRING (color
, 1);
4362 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4366 rgb
[0] = make_number (foo
.red
);
4367 rgb
[1] = make_number (foo
.green
);
4368 rgb
[2] = make_number (foo
.blue
);
4369 return Flist (3, rgb
);
4375 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4376 "Internal function called by `display-color-p', which see.")
4378 Lisp_Object display
;
4380 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4382 if (dpyinfo
->n_planes
<= 2)
4385 switch (dpyinfo
->visual
->class)
4398 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4400 "Return t if the X display supports shades of gray.\n\
4401 Note that color displays do support shades of gray.\n\
4402 The optional argument DISPLAY specifies which display to ask about.\n\
4403 DISPLAY should be either a frame or a display name (a string).\n\
4404 If omitted or nil, that stands for the selected frame's display.")
4406 Lisp_Object display
;
4408 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4410 if (dpyinfo
->n_planes
<= 1)
4413 switch (dpyinfo
->visual
->class)
4428 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4430 "Returns the width in pixels of the X display DISPLAY.\n\
4431 The optional argument DISPLAY specifies which display to ask about.\n\
4432 DISPLAY should be either a frame or a display name (a string).\n\
4433 If omitted or nil, that stands for the selected frame's display.")
4435 Lisp_Object display
;
4437 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4439 return make_number (dpyinfo
->width
);
4442 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4443 Sx_display_pixel_height
, 0, 1, 0,
4444 "Returns the height in pixels of the X display DISPLAY.\n\
4445 The optional argument DISPLAY specifies which display to ask about.\n\
4446 DISPLAY should be either a frame or a display name (a string).\n\
4447 If omitted or nil, that stands for the selected frame's display.")
4449 Lisp_Object display
;
4451 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4453 return make_number (dpyinfo
->height
);
4456 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4458 "Returns the number of bitplanes of the X display DISPLAY.\n\
4459 The optional argument DISPLAY specifies which display to ask about.\n\
4460 DISPLAY should be either a frame or a display name (a string).\n\
4461 If omitted or nil, that stands for the selected frame's display.")
4463 Lisp_Object display
;
4465 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4467 return make_number (dpyinfo
->n_planes
);
4470 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4472 "Returns the number of color cells of the X display DISPLAY.\n\
4473 The optional argument DISPLAY specifies which display to ask about.\n\
4474 DISPLAY should be either a frame or a display name (a string).\n\
4475 If omitted or nil, that stands for the selected frame's display.")
4477 Lisp_Object display
;
4479 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4481 return make_number (DisplayCells (dpyinfo
->display
,
4482 XScreenNumberOfScreen (dpyinfo
->screen
)));
4485 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4486 Sx_server_max_request_size
,
4488 "Returns the maximum request size of the X server of display DISPLAY.\n\
4489 The optional argument DISPLAY specifies which display to ask about.\n\
4490 DISPLAY should be either a frame or a display name (a string).\n\
4491 If omitted or nil, that stands for the selected frame's display.")
4493 Lisp_Object display
;
4495 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4497 return make_number (MAXREQUEST (dpyinfo
->display
));
4500 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4501 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4502 The optional argument DISPLAY specifies which display to ask about.\n\
4503 DISPLAY should be either a frame or a display name (a string).\n\
4504 If omitted or nil, that stands for the selected frame's display.")
4506 Lisp_Object display
;
4508 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4509 char *vendor
= ServerVendor (dpyinfo
->display
);
4511 if (! vendor
) vendor
= "";
4512 return build_string (vendor
);
4515 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4516 "Returns the version numbers of the X server of display DISPLAY.\n\
4517 The value is a list of three integers: the major and minor\n\
4518 version numbers of the X Protocol in use, and the vendor-specific release\n\
4519 number. See also the function `x-server-vendor'.\n\n\
4520 The optional argument DISPLAY specifies which display to ask about.\n\
4521 DISPLAY should be either a frame or a display name (a string).\n\
4522 If omitted or nil, that stands for the selected frame's display.")
4524 Lisp_Object display
;
4526 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4527 Display
*dpy
= dpyinfo
->display
;
4529 return Fcons (make_number (ProtocolVersion (dpy
)),
4530 Fcons (make_number (ProtocolRevision (dpy
)),
4531 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4534 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4535 "Returns the number of screens on the X server of display DISPLAY.\n\
4536 The optional argument DISPLAY specifies which display to ask about.\n\
4537 DISPLAY should be either a frame or a display name (a string).\n\
4538 If omitted or nil, that stands for the selected frame's display.")
4540 Lisp_Object display
;
4542 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4544 return make_number (ScreenCount (dpyinfo
->display
));
4547 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4548 "Returns the height in millimeters of the X display DISPLAY.\n\
4549 The optional argument DISPLAY specifies which display to ask about.\n\
4550 DISPLAY should be either a frame or a display name (a string).\n\
4551 If omitted or nil, that stands for the selected frame's display.")
4553 Lisp_Object display
;
4555 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4557 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4560 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4561 "Returns the width in millimeters of the X display DISPLAY.\n\
4562 The optional argument DISPLAY specifies which display to ask about.\n\
4563 DISPLAY should be either a frame or a display name (a string).\n\
4564 If omitted or nil, that stands for the selected frame's display.")
4566 Lisp_Object display
;
4568 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4570 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4573 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4574 Sx_display_backing_store
, 0, 1, 0,
4575 "Returns an indication of whether X display DISPLAY does backing store.\n\
4576 The value may be `always', `when-mapped', or `not-useful'.\n\
4577 The optional argument DISPLAY specifies which display to ask about.\n\
4578 DISPLAY should be either a frame or a display name (a string).\n\
4579 If omitted or nil, that stands for the selected frame's display.")
4581 Lisp_Object display
;
4583 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4585 switch (DoesBackingStore (dpyinfo
->screen
))
4588 return intern ("always");
4591 return intern ("when-mapped");
4594 return intern ("not-useful");
4597 error ("Strange value for BackingStore parameter of screen");
4601 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4602 Sx_display_visual_class
, 0, 1, 0,
4603 "Returns the visual class of the X display DISPLAY.\n\
4604 The value is one of the symbols `static-gray', `gray-scale',\n\
4605 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4606 The optional argument DISPLAY specifies which display to ask about.\n\
4607 DISPLAY should be either a frame or a display name (a string).\n\
4608 If omitted or nil, that stands for the selected frame's display.")
4610 Lisp_Object display
;
4612 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4614 switch (dpyinfo
->visual
->class)
4616 case StaticGray
: return (intern ("static-gray"));
4617 case GrayScale
: return (intern ("gray-scale"));
4618 case StaticColor
: return (intern ("static-color"));
4619 case PseudoColor
: return (intern ("pseudo-color"));
4620 case TrueColor
: return (intern ("true-color"));
4621 case DirectColor
: return (intern ("direct-color"));
4623 error ("Display has an unknown visual class");
4627 DEFUN ("x-display-save-under", Fx_display_save_under
,
4628 Sx_display_save_under
, 0, 1, 0,
4629 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4630 The optional argument DISPLAY specifies which display to ask about.\n\
4631 DISPLAY should be either a frame or a display name (a string).\n\
4632 If omitted or nil, that stands for the selected frame's display.")
4634 Lisp_Object display
;
4636 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4638 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4646 register struct frame
*f
;
4648 return PIXEL_WIDTH (f
);
4653 register struct frame
*f
;
4655 return PIXEL_HEIGHT (f
);
4660 register struct frame
*f
;
4662 return FONT_WIDTH (f
->output_data
.x
->font
);
4667 register struct frame
*f
;
4669 return f
->output_data
.x
->line_height
;
4674 register struct frame
*f
;
4676 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4681 /************************************************************************
4683 ************************************************************************/
4686 /* Mapping visual names to visuals. */
4688 static struct visual_class
4695 {"StaticGray", StaticGray
},
4696 {"GrayScale", GrayScale
},
4697 {"StaticColor", StaticColor
},
4698 {"PseudoColor", PseudoColor
},
4699 {"TrueColor", TrueColor
},
4700 {"DirectColor", DirectColor
},
4705 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4707 /* Value is the screen number of screen SCR. This is a substitute for
4708 the X function with the same name when that doesn't exist. */
4711 XScreenNumberOfScreen (scr
)
4712 register Screen
*scr
;
4714 Display
*dpy
= scr
->display
;
4717 for (i
= 0; i
< dpy
->nscreens
; ++i
)
4718 if (scr
== dpy
->screens
[i
])
4724 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4727 /* Select the visual that should be used on display DPYINFO. Set
4728 members of DPYINFO appropriately. Called from x_term_init. */
4731 select_visual (dpyinfo
)
4732 struct x_display_info
*dpyinfo
;
4734 Display
*dpy
= dpyinfo
->display
;
4735 Screen
*screen
= dpyinfo
->screen
;
4738 /* See if a visual is specified. */
4739 value
= display_x_get_resource (dpyinfo
,
4740 build_string ("visualClass"),
4741 build_string ("VisualClass"),
4743 if (STRINGP (value
))
4745 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4746 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4747 depth, a decimal number. NAME is compared with case ignored. */
4748 char *s
= (char *) alloca (STRING_BYTES (XSTRING (value
)) + 1);
4753 strcpy (s
, XSTRING (value
)->data
);
4754 dash
= index (s
, '-');
4757 dpyinfo
->n_planes
= atoi (dash
+ 1);
4761 /* We won't find a matching visual with depth 0, so that
4762 an error will be printed below. */
4763 dpyinfo
->n_planes
= 0;
4765 /* Determine the visual class. */
4766 for (i
= 0; visual_classes
[i
].name
; ++i
)
4767 if (xstricmp (s
, visual_classes
[i
].name
) == 0)
4769 class = visual_classes
[i
].class;
4773 /* Look up a matching visual for the specified class. */
4775 || !XMatchVisualInfo (dpy
, XScreenNumberOfScreen (screen
),
4776 dpyinfo
->n_planes
, class, &vinfo
))
4777 fatal ("Invalid visual specification `%s'", XSTRING (value
)->data
);
4779 dpyinfo
->visual
= vinfo
.visual
;
4784 XVisualInfo
*vinfo
, vinfo_template
;
4786 dpyinfo
->visual
= DefaultVisualOfScreen (screen
);
4789 vinfo_template
.visualid
= XVisualIDFromVisual (dpyinfo
->visual
);
4791 vinfo_template
.visualid
= dpyinfo
->visual
->visualid
;
4793 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
4794 vinfo
= XGetVisualInfo (dpy
, VisualIDMask
| VisualScreenMask
,
4795 &vinfo_template
, &n_visuals
);
4797 fatal ("Can't get proper X visual info");
4799 dpyinfo
->n_planes
= vinfo
->depth
;
4800 XFree ((char *) vinfo
);
4805 /* Return the X display structure for the display named NAME.
4806 Open a new connection if necessary. */
4808 struct x_display_info
*
4809 x_display_info_for_name (name
)
4813 struct x_display_info
*dpyinfo
;
4815 CHECK_STRING (name
, 0);
4817 if (! EQ (Vwindow_system
, intern ("x")))
4818 error ("Not using X Windows");
4820 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
4822 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4825 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4830 /* Use this general default value to start with. */
4831 Vx_resource_name
= Vinvocation_name
;
4833 validate_x_resource_name ();
4835 dpyinfo
= x_term_init (name
, (unsigned char *)0,
4836 (char *) XSTRING (Vx_resource_name
)->data
);
4839 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
4842 XSETFASTINT (Vwindow_system_version
, 11);
4848 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4849 1, 3, 0, "Open a connection to an X server.\n\
4850 DISPLAY is the name of the display to connect to.\n\
4851 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4852 If the optional third arg MUST-SUCCEED is non-nil,\n\
4853 terminate Emacs if we can't open the connection.")
4854 (display
, xrm_string
, must_succeed
)
4855 Lisp_Object display
, xrm_string
, must_succeed
;
4857 unsigned char *xrm_option
;
4858 struct x_display_info
*dpyinfo
;
4860 CHECK_STRING (display
, 0);
4861 if (! NILP (xrm_string
))
4862 CHECK_STRING (xrm_string
, 1);
4864 if (! EQ (Vwindow_system
, intern ("x")))
4865 error ("Not using X Windows");
4867 if (! NILP (xrm_string
))
4868 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
4870 xrm_option
= (unsigned char *) 0;
4872 validate_x_resource_name ();
4874 /* This is what opens the connection and sets x_current_display.
4875 This also initializes many symbols, such as those used for input. */
4876 dpyinfo
= x_term_init (display
, xrm_option
,
4877 (char *) XSTRING (Vx_resource_name
)->data
);
4881 if (!NILP (must_succeed
))
4882 fatal ("Cannot connect to X server %s.\n\
4883 Check the DISPLAY environment variable or use `-d'.\n\
4884 Also use the `xhost' program to verify that it is set to permit\n\
4885 connections from your machine.\n",
4886 XSTRING (display
)->data
);
4888 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
4893 XSETFASTINT (Vwindow_system_version
, 11);
4897 DEFUN ("x-close-connection", Fx_close_connection
,
4898 Sx_close_connection
, 1, 1, 0,
4899 "Close the connection to DISPLAY's X server.\n\
4900 For DISPLAY, specify either a frame or a display name (a string).\n\
4901 If DISPLAY is nil, that stands for the selected frame's display.")
4903 Lisp_Object display
;
4905 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4908 if (dpyinfo
->reference_count
> 0)
4909 error ("Display still has frames on it");
4912 /* Free the fonts in the font table. */
4913 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4914 if (dpyinfo
->font_table
[i
].name
)
4916 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
4917 xfree (dpyinfo
->font_table
[i
].full_name
);
4918 xfree (dpyinfo
->font_table
[i
].name
);
4919 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
4922 x_destroy_all_bitmaps (dpyinfo
);
4923 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
4925 #ifdef USE_X_TOOLKIT
4926 XtCloseDisplay (dpyinfo
->display
);
4928 XCloseDisplay (dpyinfo
->display
);
4931 x_delete_display (dpyinfo
);
4937 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
4938 "Return the list of display names that Emacs has connections to.")
4941 Lisp_Object tail
, result
;
4944 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
4945 result
= Fcons (XCAR (XCAR (tail
)), result
);
4950 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
4951 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
4952 If ON is nil, allow buffering of requests.\n\
4953 Turning on synchronization prohibits the Xlib routines from buffering\n\
4954 requests and seriously degrades performance, but makes debugging much\n\
4956 The optional second argument DISPLAY specifies which display to act on.\n\
4957 DISPLAY should be either a frame or a display name (a string).\n\
4958 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
4960 Lisp_Object display
, on
;
4962 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4964 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
4969 /* Wait for responses to all X commands issued so far for frame F. */
4976 XSync (FRAME_X_DISPLAY (f
), False
);
4981 /***********************************************************************
4983 ***********************************************************************/
4985 /* Value is the number of elements of vector VECTOR. */
4987 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
4989 /* List of supported image types. Use define_image_type to add new
4990 types. Use lookup_image_type to find a type for a given symbol. */
4992 static struct image_type
*image_types
;
4994 /* The symbol `image' which is the car of the lists used to represent
4997 extern Lisp_Object Qimage
;
4999 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5005 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5006 extern Lisp_Object QCdata
;
5007 Lisp_Object QCtype
, QCascent
, QCmargin
, QCrelief
;
5008 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5009 Lisp_Object QCindex
;
5011 /* Other symbols. */
5013 Lisp_Object Qlaplace
;
5015 /* Time in seconds after which images should be removed from the cache
5016 if not displayed. */
5018 Lisp_Object Vimage_cache_eviction_delay
;
5020 /* Function prototypes. */
5022 static void define_image_type
P_ ((struct image_type
*type
));
5023 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5024 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5025 static void x_laplace
P_ ((struct frame
*, struct image
*));
5026 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5030 /* Define a new image type from TYPE. This adds a copy of TYPE to
5031 image_types and adds the symbol *TYPE->type to Vimage_types. */
5034 define_image_type (type
)
5035 struct image_type
*type
;
5037 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5038 The initialized data segment is read-only. */
5039 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5040 bcopy (type
, p
, sizeof *p
);
5041 p
->next
= image_types
;
5043 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5047 /* Look up image type SYMBOL, and return a pointer to its image_type
5048 structure. Value is null if SYMBOL is not a known image type. */
5050 static INLINE
struct image_type
*
5051 lookup_image_type (symbol
)
5054 struct image_type
*type
;
5056 for (type
= image_types
; type
; type
= type
->next
)
5057 if (EQ (symbol
, *type
->type
))
5064 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5065 valid image specification is a list whose car is the symbol
5066 `image', and whose rest is a property list. The property list must
5067 contain a value for key `:type'. That value must be the name of a
5068 supported image type. The rest of the property list depends on the
5072 valid_image_p (object
)
5077 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5079 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5080 struct image_type
*type
= lookup_image_type (symbol
);
5083 valid_p
= type
->valid_p (object
);
5090 /* Log error message with format string FORMAT and argument ARG.
5091 Signaling an error, e.g. when an image cannot be loaded, is not a
5092 good idea because this would interrupt redisplay, and the error
5093 message display would lead to another redisplay. This function
5094 therefore simply displays a message. */
5097 image_error (format
, arg1
, arg2
)
5099 Lisp_Object arg1
, arg2
;
5101 add_to_log (format
, arg1
, arg2
);
5106 /***********************************************************************
5107 Image specifications
5108 ***********************************************************************/
5110 enum image_value_type
5112 IMAGE_DONT_CHECK_VALUE_TYPE
,
5115 IMAGE_POSITIVE_INTEGER_VALUE
,
5116 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5118 IMAGE_INTEGER_VALUE
,
5119 IMAGE_FUNCTION_VALUE
,
5124 /* Structure used when parsing image specifications. */
5126 struct image_keyword
5128 /* Name of keyword. */
5131 /* The type of value allowed. */
5132 enum image_value_type type
;
5134 /* Non-zero means key must be present. */
5137 /* Used to recognize duplicate keywords in a property list. */
5140 /* The value that was found. */
5145 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5147 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5150 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5151 has the format (image KEYWORD VALUE ...). One of the keyword/
5152 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5153 image_keywords structures of size NKEYWORDS describing other
5154 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5157 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5159 struct image_keyword
*keywords
;
5166 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5169 plist
= XCDR (spec
);
5170 while (CONSP (plist
))
5172 Lisp_Object key
, value
;
5174 /* First element of a pair must be a symbol. */
5176 plist
= XCDR (plist
);
5180 /* There must follow a value. */
5183 value
= XCAR (plist
);
5184 plist
= XCDR (plist
);
5186 /* Find key in KEYWORDS. Error if not found. */
5187 for (i
= 0; i
< nkeywords
; ++i
)
5188 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5194 /* Record that we recognized the keyword. If a keywords
5195 was found more than once, it's an error. */
5196 keywords
[i
].value
= value
;
5197 ++keywords
[i
].count
;
5199 if (keywords
[i
].count
> 1)
5202 /* Check type of value against allowed type. */
5203 switch (keywords
[i
].type
)
5205 case IMAGE_STRING_VALUE
:
5206 if (!STRINGP (value
))
5210 case IMAGE_SYMBOL_VALUE
:
5211 if (!SYMBOLP (value
))
5215 case IMAGE_POSITIVE_INTEGER_VALUE
:
5216 if (!INTEGERP (value
) || XINT (value
) <= 0)
5220 case IMAGE_ASCENT_VALUE
:
5221 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
5223 else if (INTEGERP (value
)
5224 && XINT (value
) >= 0
5225 && XINT (value
) <= 100)
5229 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5230 if (!INTEGERP (value
) || XINT (value
) < 0)
5234 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5237 case IMAGE_FUNCTION_VALUE
:
5238 value
= indirect_function (value
);
5240 || COMPILEDP (value
)
5241 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5245 case IMAGE_NUMBER_VALUE
:
5246 if (!INTEGERP (value
) && !FLOATP (value
))
5250 case IMAGE_INTEGER_VALUE
:
5251 if (!INTEGERP (value
))
5255 case IMAGE_BOOL_VALUE
:
5256 if (!NILP (value
) && !EQ (value
, Qt
))
5265 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5269 /* Check that all mandatory fields are present. */
5270 for (i
= 0; i
< nkeywords
; ++i
)
5271 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5274 return NILP (plist
);
5278 /* Return the value of KEY in image specification SPEC. Value is nil
5279 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5280 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5283 image_spec_value (spec
, key
, found
)
5284 Lisp_Object spec
, key
;
5289 xassert (valid_image_p (spec
));
5291 for (tail
= XCDR (spec
);
5292 CONSP (tail
) && CONSP (XCDR (tail
));
5293 tail
= XCDR (XCDR (tail
)))
5295 if (EQ (XCAR (tail
), key
))
5299 return XCAR (XCDR (tail
));
5309 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
5310 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5311 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5312 size in canonical character units.\n\
5313 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5314 or omitted means use the selected frame.")
5315 (spec
, pixels
, frame
)
5316 Lisp_Object spec
, pixels
, frame
;
5321 if (valid_image_p (spec
))
5323 struct frame
*f
= check_x_frame (frame
);
5324 int id
= lookup_image (f
, spec
);
5325 struct image
*img
= IMAGE_FROM_ID (f
, id
);
5326 int width
= img
->width
+ 2 * img
->margin
;
5327 int height
= img
->height
+ 2 * img
->margin
;
5330 size
= Fcons (make_float ((double) width
/ CANON_X_UNIT (f
)),
5331 make_float ((double) height
/ CANON_Y_UNIT (f
)));
5333 size
= Fcons (make_number (width
), make_number (height
));
5336 error ("Invalid image specification");
5343 /***********************************************************************
5344 Image type independent image structures
5345 ***********************************************************************/
5347 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5348 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5351 /* Allocate and return a new image structure for image specification
5352 SPEC. SPEC has a hash value of HASH. */
5354 static struct image
*
5355 make_image (spec
, hash
)
5359 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5361 xassert (valid_image_p (spec
));
5362 bzero (img
, sizeof *img
);
5363 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5364 xassert (img
->type
!= NULL
);
5366 img
->data
.lisp_val
= Qnil
;
5367 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
5373 /* Free image IMG which was used on frame F, including its resources. */
5382 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5384 /* Remove IMG from the hash table of its cache. */
5386 img
->prev
->next
= img
->next
;
5388 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
5391 img
->next
->prev
= img
->prev
;
5393 c
->images
[img
->id
] = NULL
;
5395 /* Free resources, then free IMG. */
5396 img
->type
->free (f
, img
);
5402 /* Prepare image IMG for display on frame F. Must be called before
5403 drawing an image. */
5406 prepare_image_for_display (f
, img
)
5412 /* We're about to display IMG, so set its timestamp to `now'. */
5414 img
->timestamp
= EMACS_SECS (t
);
5416 /* If IMG doesn't have a pixmap yet, load it now, using the image
5417 type dependent loader function. */
5418 if (img
->pixmap
== 0 && !img
->load_failed_p
)
5419 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5423 /* Value is the number of pixels for the ascent of image IMG when
5424 drawn in face FACE. */
5427 image_ascent (img
, face
)
5431 int height
= img
->height
+ img
->margin
;
5434 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
5437 ascent
= height
/ 2 - (face
->font
->descent
- face
->font
->ascent
) / 2;
5439 ascent
= height
/ 2;
5442 ascent
= height
* img
->ascent
/ 100.0;
5449 /***********************************************************************
5450 Helper functions for X image types
5451 ***********************************************************************/
5453 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
5454 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
5456 Lisp_Object color_name
,
5457 unsigned long dflt
));
5459 /* Free X resources of image IMG which is used on frame F. */
5462 x_clear_image (f
, img
)
5469 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5477 x_free_colors (f
, img
->colors
, img
->ncolors
);
5480 xfree (img
->colors
);
5487 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5488 cannot be allocated, use DFLT. Add a newly allocated color to
5489 IMG->colors, so that it can be freed again. Value is the pixel
5492 static unsigned long
5493 x_alloc_image_color (f
, img
, color_name
, dflt
)
5496 Lisp_Object color_name
;
5500 unsigned long result
;
5502 xassert (STRINGP (color_name
));
5504 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
5506 /* This isn't called frequently so we get away with simply
5507 reallocating the color vector to the needed size, here. */
5510 (unsigned long *) xrealloc (img
->colors
,
5511 img
->ncolors
* sizeof *img
->colors
);
5512 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
5513 result
= color
.pixel
;
5523 /***********************************************************************
5525 ***********************************************************************/
5527 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
5530 /* Return a new, initialized image cache that is allocated from the
5531 heap. Call free_image_cache to free an image cache. */
5533 struct image_cache
*
5536 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
5539 bzero (c
, sizeof *c
);
5541 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
5542 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
5543 c
->buckets
= (struct image
**) xmalloc (size
);
5544 bzero (c
->buckets
, size
);
5549 /* Free image cache of frame F. Be aware that X frames share images
5553 free_image_cache (f
)
5556 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5561 /* Cache should not be referenced by any frame when freed. */
5562 xassert (c
->refcount
== 0);
5564 for (i
= 0; i
< c
->used
; ++i
)
5565 free_image (f
, c
->images
[i
]);
5569 FRAME_X_IMAGE_CACHE (f
) = NULL
;
5574 /* Clear image cache of frame F. FORCE_P non-zero means free all
5575 images. FORCE_P zero means clear only images that haven't been
5576 displayed for some time. Should be called from time to time to
5577 reduce the number of loaded images. If image-eviction-seconds is
5578 non-nil, this frees images in the cache which weren't displayed for
5579 at least that many seconds. */
5582 clear_image_cache (f
, force_p
)
5586 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5588 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
5592 int i
, any_freed_p
= 0;
5595 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
5597 for (i
= 0; i
< c
->used
; ++i
)
5599 struct image
*img
= c
->images
[i
];
5602 || (img
->timestamp
> old
)))
5604 free_image (f
, img
);
5609 /* We may be clearing the image cache because, for example,
5610 Emacs was iconified for a longer period of time. In that
5611 case, current matrices may still contain references to
5612 images freed above. So, clear these matrices. */
5615 clear_current_matrices (f
);
5616 ++windows_or_buffers_changed
;
5622 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
5624 "Clear the image cache of FRAME.\n\
5625 FRAME nil or omitted means use the selected frame.\n\
5626 FRAME t means clear the image caches of all frames.")
5634 FOR_EACH_FRAME (tail
, frame
)
5635 if (FRAME_X_P (XFRAME (frame
)))
5636 clear_image_cache (XFRAME (frame
), 1);
5639 clear_image_cache (check_x_frame (frame
), 1);
5645 /* Return the id of image with Lisp specification SPEC on frame F.
5646 SPEC must be a valid Lisp image specification (see valid_image_p). */
5649 lookup_image (f
, spec
)
5653 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5657 struct gcpro gcpro1
;
5660 /* F must be a window-system frame, and SPEC must be a valid image
5662 xassert (FRAME_WINDOW_P (f
));
5663 xassert (valid_image_p (spec
));
5667 /* Look up SPEC in the hash table of the image cache. */
5668 hash
= sxhash (spec
, 0);
5669 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5671 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
5672 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
5675 /* If not found, create a new image and cache it. */
5678 img
= make_image (spec
, hash
);
5679 cache_image (f
, img
);
5680 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
5681 xassert (!interrupt_input_blocked
);
5683 /* If we can't load the image, and we don't have a width and
5684 height, use some arbitrary width and height so that we can
5685 draw a rectangle for it. */
5686 if (img
->load_failed_p
)
5690 value
= image_spec_value (spec
, QCwidth
, NULL
);
5691 img
->width
= (INTEGERP (value
)
5692 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
5693 value
= image_spec_value (spec
, QCheight
, NULL
);
5694 img
->height
= (INTEGERP (value
)
5695 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
5699 /* Handle image type independent image attributes
5700 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5701 Lisp_Object ascent
, margin
, relief
, algorithm
, heuristic_mask
;
5704 ascent
= image_spec_value (spec
, QCascent
, NULL
);
5705 if (INTEGERP (ascent
))
5706 img
->ascent
= XFASTINT (ascent
);
5707 else if (EQ (ascent
, Qcenter
))
5708 img
->ascent
= CENTERED_IMAGE_ASCENT
;
5710 margin
= image_spec_value (spec
, QCmargin
, NULL
);
5711 if (INTEGERP (margin
) && XINT (margin
) >= 0)
5712 img
->margin
= XFASTINT (margin
);
5714 relief
= image_spec_value (spec
, QCrelief
, NULL
);
5715 if (INTEGERP (relief
))
5717 img
->relief
= XINT (relief
);
5718 img
->margin
+= abs (img
->relief
);
5721 /* Should we apply a Laplace edge-detection algorithm? */
5722 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
5723 if (img
->pixmap
&& EQ (algorithm
, Qlaplace
))
5726 /* Should we built a mask heuristically? */
5727 heuristic_mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
5728 if (img
->pixmap
&& !img
->mask
&& !NILP (heuristic_mask
))
5729 x_build_heuristic_mask (f
, img
, heuristic_mask
);
5733 /* We're using IMG, so set its timestamp to `now'. */
5734 EMACS_GET_TIME (now
);
5735 img
->timestamp
= EMACS_SECS (now
);
5739 /* Value is the image id. */
5744 /* Cache image IMG in the image cache of frame F. */
5747 cache_image (f
, img
)
5751 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5754 /* Find a free slot in c->images. */
5755 for (i
= 0; i
< c
->used
; ++i
)
5756 if (c
->images
[i
] == NULL
)
5759 /* If no free slot found, maybe enlarge c->images. */
5760 if (i
== c
->used
&& c
->used
== c
->size
)
5763 c
->images
= (struct image
**) xrealloc (c
->images
,
5764 c
->size
* sizeof *c
->images
);
5767 /* Add IMG to c->images, and assign IMG an id. */
5773 /* Add IMG to the cache's hash table. */
5774 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
5775 img
->next
= c
->buckets
[i
];
5777 img
->next
->prev
= img
;
5779 c
->buckets
[i
] = img
;
5783 /* Call FN on every image in the image cache of frame F. Used to mark
5784 Lisp Objects in the image cache. */
5787 forall_images_in_image_cache (f
, fn
)
5789 void (*fn
) P_ ((struct image
*img
));
5791 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
5793 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
5797 for (i
= 0; i
< c
->used
; ++i
)
5806 /***********************************************************************
5808 ***********************************************************************/
5810 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
5811 XImage
**, Pixmap
*));
5812 static void x_destroy_x_image
P_ ((XImage
*));
5813 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
5816 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
5817 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
5818 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
5819 via xmalloc. Print error messages via image_error if an error
5820 occurs. Value is non-zero if successful. */
5823 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
5825 int width
, height
, depth
;
5829 Display
*display
= FRAME_X_DISPLAY (f
);
5830 Screen
*screen
= FRAME_X_SCREEN (f
);
5831 Window window
= FRAME_X_WINDOW (f
);
5833 xassert (interrupt_input_blocked
);
5836 depth
= DefaultDepthOfScreen (screen
);
5837 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
5838 depth
, ZPixmap
, 0, NULL
, width
, height
,
5839 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
5842 image_error ("Unable to allocate X image", Qnil
, Qnil
);
5846 /* Allocate image raster. */
5847 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
5849 /* Allocate a pixmap of the same size. */
5850 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
5853 x_destroy_x_image (*ximg
);
5855 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
5863 /* Destroy XImage XIMG. Free XIMG->data. */
5866 x_destroy_x_image (ximg
)
5869 xassert (interrupt_input_blocked
);
5874 XDestroyImage (ximg
);
5879 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
5880 are width and height of both the image and pixmap. */
5883 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
5890 xassert (interrupt_input_blocked
);
5891 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
5892 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
5893 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5898 /***********************************************************************
5900 ***********************************************************************/
5902 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
5903 static char *slurp_file
P_ ((char *, int *));
5906 /* Find image file FILE. Look in data-directory, then
5907 x-bitmap-file-path. Value is the full name of the file found, or
5908 nil if not found. */
5911 x_find_image_file (file
)
5914 Lisp_Object file_found
, search_path
;
5915 struct gcpro gcpro1
, gcpro2
;
5919 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
5920 GCPRO2 (file_found
, search_path
);
5922 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
5923 fd
= openp (search_path
, file
, "", &file_found
, 0);
5935 /* Read FILE into memory. Value is a pointer to a buffer allocated
5936 with xmalloc holding FILE's contents. Value is null if an error
5937 occured. *SIZE is set to the size of the file. */
5940 slurp_file (file
, size
)
5948 if (stat (file
, &st
) == 0
5949 && (fp
= fopen (file
, "r")) != NULL
5950 && (buf
= (char *) xmalloc (st
.st_size
),
5951 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5972 /***********************************************************************
5974 ***********************************************************************/
5976 static int xbm_scan
P_ ((char **, char *, char *, int *));
5977 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
5978 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
5980 static int xbm_image_p
P_ ((Lisp_Object object
));
5981 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
5983 static int xbm_file_p
P_ ((Lisp_Object
));
5986 /* Indices of image specification fields in xbm_format, below. */
5988 enum xbm_keyword_index
6005 /* Vector of image_keyword structures describing the format
6006 of valid XBM image specifications. */
6008 static struct image_keyword xbm_format
[XBM_LAST
] =
6010 {":type", IMAGE_SYMBOL_VALUE
, 1},
6011 {":file", IMAGE_STRING_VALUE
, 0},
6012 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6013 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6014 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6015 {":foreground", IMAGE_STRING_VALUE
, 0},
6016 {":background", IMAGE_STRING_VALUE
, 0},
6017 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6018 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6019 {":relief", IMAGE_INTEGER_VALUE
, 0},
6020 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6021 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6024 /* Structure describing the image type XBM. */
6026 static struct image_type xbm_type
=
6035 /* Tokens returned from xbm_scan. */
6044 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6045 A valid specification is a list starting with the symbol `image'
6046 The rest of the list is a property list which must contain an
6049 If the specification specifies a file to load, it must contain
6050 an entry `:file FILENAME' where FILENAME is a string.
6052 If the specification is for a bitmap loaded from memory it must
6053 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6054 WIDTH and HEIGHT are integers > 0. DATA may be:
6056 1. a string large enough to hold the bitmap data, i.e. it must
6057 have a size >= (WIDTH + 7) / 8 * HEIGHT
6059 2. a bool-vector of size >= WIDTH * HEIGHT
6061 3. a vector of strings or bool-vectors, one for each line of the
6064 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6065 may not be specified in this case because they are defined in the
6068 Both the file and data forms may contain the additional entries
6069 `:background COLOR' and `:foreground COLOR'. If not present,
6070 foreground and background of the frame on which the image is
6071 displayed is used. */
6074 xbm_image_p (object
)
6077 struct image_keyword kw
[XBM_LAST
];
6079 bcopy (xbm_format
, kw
, sizeof kw
);
6080 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6083 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6085 if (kw
[XBM_FILE
].count
)
6087 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6090 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
6092 /* In-memory XBM file. */
6093 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
6101 /* Entries for `:width', `:height' and `:data' must be present. */
6102 if (!kw
[XBM_WIDTH
].count
6103 || !kw
[XBM_HEIGHT
].count
6104 || !kw
[XBM_DATA
].count
)
6107 data
= kw
[XBM_DATA
].value
;
6108 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6109 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6111 /* Check type of data, and width and height against contents of
6117 /* Number of elements of the vector must be >= height. */
6118 if (XVECTOR (data
)->size
< height
)
6121 /* Each string or bool-vector in data must be large enough
6122 for one line of the image. */
6123 for (i
= 0; i
< height
; ++i
)
6125 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6129 if (XSTRING (elt
)->size
6130 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6133 else if (BOOL_VECTOR_P (elt
))
6135 if (XBOOL_VECTOR (elt
)->size
< width
)
6142 else if (STRINGP (data
))
6144 if (XSTRING (data
)->size
6145 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6148 else if (BOOL_VECTOR_P (data
))
6150 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6161 /* Scan a bitmap file. FP is the stream to read from. Value is
6162 either an enumerator from enum xbm_token, or a character for a
6163 single-character token, or 0 at end of file. If scanning an
6164 identifier, store the lexeme of the identifier in SVAL. If
6165 scanning a number, store its value in *IVAL. */
6168 xbm_scan (s
, end
, sval
, ival
)
6175 /* Skip white space. */
6176 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6181 else if (isdigit (c
))
6183 int value
= 0, digit
;
6185 if (c
== '0' && *s
< end
)
6188 if (c
== 'x' || c
== 'X')
6195 else if (c
>= 'a' && c
<= 'f')
6196 digit
= c
- 'a' + 10;
6197 else if (c
>= 'A' && c
<= 'F')
6198 digit
= c
- 'A' + 10;
6201 value
= 16 * value
+ digit
;
6204 else if (isdigit (c
))
6208 && (c
= *(*s
)++, isdigit (c
)))
6209 value
= 8 * value
+ c
- '0';
6216 && (c
= *(*s
)++, isdigit (c
)))
6217 value
= 10 * value
+ c
- '0';
6225 else if (isalpha (c
) || c
== '_')
6229 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
6241 /* Replacement for XReadBitmapFileData which isn't available under old
6242 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6243 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6244 the image. Return in *DATA the bitmap data allocated with xmalloc.
6245 Value is non-zero if successful. DATA null means just test if
6246 CONTENTS looks like an im-memory XBM file. */
6249 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
6250 char *contents
, *end
;
6251 int *width
, *height
;
6252 unsigned char **data
;
6255 char buffer
[BUFSIZ
];
6258 int bytes_per_line
, i
, nbytes
;
6264 LA1 = xbm_scan (&s, end, buffer, &value)
6266 #define expect(TOKEN) \
6267 if (LA1 != (TOKEN)) \
6272 #define expect_ident(IDENT) \
6273 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6278 *width
= *height
= -1;
6281 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
6283 /* Parse defines for width, height and hot-spots. */
6287 expect_ident ("define");
6288 expect (XBM_TK_IDENT
);
6290 if (LA1
== XBM_TK_NUMBER
);
6292 char *p
= strrchr (buffer
, '_');
6293 p
= p
? p
+ 1 : buffer
;
6294 if (strcmp (p
, "width") == 0)
6296 else if (strcmp (p
, "height") == 0)
6299 expect (XBM_TK_NUMBER
);
6302 if (*width
< 0 || *height
< 0)
6304 else if (data
== NULL
)
6307 /* Parse bits. Must start with `static'. */
6308 expect_ident ("static");
6309 if (LA1
== XBM_TK_IDENT
)
6311 if (strcmp (buffer
, "unsigned") == 0)
6314 expect_ident ("char");
6316 else if (strcmp (buffer
, "short") == 0)
6320 if (*width
% 16 && *width
% 16 < 9)
6323 else if (strcmp (buffer
, "char") == 0)
6331 expect (XBM_TK_IDENT
);
6337 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6338 nbytes
= bytes_per_line
* *height
;
6339 p
= *data
= (char *) xmalloc (nbytes
);
6343 for (i
= 0; i
< nbytes
; i
+= 2)
6346 expect (XBM_TK_NUMBER
);
6349 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6352 if (LA1
== ',' || LA1
== '}')
6360 for (i
= 0; i
< nbytes
; ++i
)
6363 expect (XBM_TK_NUMBER
);
6367 if (LA1
== ',' || LA1
== '}')
6392 /* Load XBM image IMG which will be displayed on frame F from buffer
6393 CONTENTS. END is the end of the buffer. Value is non-zero if
6397 xbm_load_image (f
, img
, contents
, end
)
6400 char *contents
, *end
;
6403 unsigned char *data
;
6406 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
6409 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6410 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6411 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6414 xassert (img
->width
> 0 && img
->height
> 0);
6416 /* Get foreground and background colors, maybe allocate colors. */
6417 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
6419 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
6421 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6423 background
= x_alloc_image_color (f
, img
, value
, background
);
6427 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6430 img
->width
, img
->height
,
6431 foreground
, background
,
6435 if (img
->pixmap
== 0)
6437 x_clear_image (f
, img
);
6438 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
6446 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6452 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6459 return (STRINGP (data
)
6460 && xbm_read_bitmap_data (XSTRING (data
)->data
,
6461 (XSTRING (data
)->data
6462 + STRING_BYTES (XSTRING (data
))),
6467 /* Fill image IMG which is used on frame F with pixmap data. Value is
6468 non-zero if successful. */
6476 Lisp_Object file_name
;
6478 xassert (xbm_image_p (img
->spec
));
6480 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6481 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
6482 if (STRINGP (file_name
))
6487 struct gcpro gcpro1
;
6489 file
= x_find_image_file (file_name
);
6491 if (!STRINGP (file
))
6493 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
6498 contents
= slurp_file (XSTRING (file
)->data
, &size
);
6499 if (contents
== NULL
)
6501 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
6506 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
6511 struct image_keyword fmt
[XBM_LAST
];
6513 unsigned char *bitmap_data
;
6515 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
6516 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
6518 int parsed_p
, height
, width
;
6519 int in_memory_file_p
= 0;
6521 /* See if data looks like an in-memory XBM file. */
6522 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6523 in_memory_file_p
= xbm_file_p (data
);
6525 /* Parse the image specification. */
6526 bcopy (xbm_format
, fmt
, sizeof fmt
);
6527 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
6530 /* Get specified width, and height. */
6531 if (!in_memory_file_p
)
6533 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
6534 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
6535 xassert (img
->width
> 0 && img
->height
> 0);
6540 /* Get foreground and background colors, maybe allocate colors. */
6541 if (fmt
[XBM_FOREGROUND
].count
)
6542 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
6544 if (fmt
[XBM_BACKGROUND
].count
)
6545 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
6548 if (in_memory_file_p
)
6549 success_p
= xbm_load_image (f
, img
, XSTRING (data
)->data
,
6550 (XSTRING (data
)->data
6551 + STRING_BYTES (XSTRING (data
))));
6558 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
6560 p
= bits
= (char *) alloca (nbytes
* img
->height
);
6561 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
6563 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
6565 bcopy (XSTRING (line
)->data
, p
, nbytes
);
6567 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
6570 else if (STRINGP (data
))
6571 bits
= XSTRING (data
)->data
;
6573 bits
= XBOOL_VECTOR (data
)->data
;
6575 /* Create the pixmap. */
6576 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6578 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
6581 img
->width
, img
->height
,
6582 foreground
, background
,
6588 image_error ("Unable to create pixmap for XBM image `%s'",
6590 x_clear_image (f
, img
);
6602 /***********************************************************************
6604 ***********************************************************************/
6608 static int xpm_image_p
P_ ((Lisp_Object object
));
6609 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
6610 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
6612 #include "X11/xpm.h"
6614 /* The symbol `xpm' identifying XPM-format images. */
6618 /* Indices of image specification fields in xpm_format, below. */
6620 enum xpm_keyword_index
6634 /* Vector of image_keyword structures describing the format
6635 of valid XPM image specifications. */
6637 static struct image_keyword xpm_format
[XPM_LAST
] =
6639 {":type", IMAGE_SYMBOL_VALUE
, 1},
6640 {":file", IMAGE_STRING_VALUE
, 0},
6641 {":data", IMAGE_STRING_VALUE
, 0},
6642 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6643 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6644 {":relief", IMAGE_INTEGER_VALUE
, 0},
6645 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6646 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6647 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6650 /* Structure describing the image type XBM. */
6652 static struct image_type xpm_type
=
6662 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
6663 for XPM images. Such a list must consist of conses whose car and
6667 xpm_valid_color_symbols_p (color_symbols
)
6668 Lisp_Object color_symbols
;
6670 while (CONSP (color_symbols
))
6672 Lisp_Object sym
= XCAR (color_symbols
);
6674 || !STRINGP (XCAR (sym
))
6675 || !STRINGP (XCDR (sym
)))
6677 color_symbols
= XCDR (color_symbols
);
6680 return NILP (color_symbols
);
6684 /* Value is non-zero if OBJECT is a valid XPM image specification. */
6687 xpm_image_p (object
)
6690 struct image_keyword fmt
[XPM_LAST
];
6691 bcopy (xpm_format
, fmt
, sizeof fmt
);
6692 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
6693 /* Either `:file' or `:data' must be present. */
6694 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
6695 /* Either no `:color-symbols' or it's a list of conses
6696 whose car and cdr are strings. */
6697 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
6698 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
6702 /* Load image IMG which will be displayed on frame F. Value is
6703 non-zero if successful. */
6711 XpmAttributes attrs
;
6712 Lisp_Object specified_file
, color_symbols
;
6714 /* Configure the XPM lib. Use the visual of frame F. Allocate
6715 close colors. Return colors allocated. */
6716 bzero (&attrs
, sizeof attrs
);
6717 attrs
.visual
= FRAME_X_VISUAL (f
);
6718 attrs
.colormap
= FRAME_X_COLORMAP (f
);
6719 attrs
.valuemask
|= XpmVisual
;
6720 attrs
.valuemask
|= XpmColormap
;
6721 attrs
.valuemask
|= XpmReturnAllocPixels
;
6722 #ifdef XpmAllocCloseColors
6723 attrs
.alloc_close_colors
= 1;
6724 attrs
.valuemask
|= XpmAllocCloseColors
;
6726 attrs
.closeness
= 600;
6727 attrs
.valuemask
|= XpmCloseness
;
6730 /* If image specification contains symbolic color definitions, add
6731 these to `attrs'. */
6732 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
6733 if (CONSP (color_symbols
))
6736 XpmColorSymbol
*xpm_syms
;
6739 attrs
.valuemask
|= XpmColorSymbols
;
6741 /* Count number of symbols. */
6742 attrs
.numsymbols
= 0;
6743 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
6746 /* Allocate an XpmColorSymbol array. */
6747 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
6748 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
6749 bzero (xpm_syms
, size
);
6750 attrs
.colorsymbols
= xpm_syms
;
6752 /* Fill the color symbol array. */
6753 for (tail
= color_symbols
, i
= 0;
6755 ++i
, tail
= XCDR (tail
))
6757 Lisp_Object name
= XCAR (XCAR (tail
));
6758 Lisp_Object color
= XCDR (XCAR (tail
));
6759 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
6760 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
6761 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
6762 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
6766 /* Create a pixmap for the image, either from a file, or from a
6767 string buffer containing data in the same format as an XPM file. */
6769 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6770 if (STRINGP (specified_file
))
6772 Lisp_Object file
= x_find_image_file (specified_file
);
6773 if (!STRINGP (file
))
6775 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6780 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6781 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
6786 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
6787 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6788 XSTRING (buffer
)->data
,
6789 &img
->pixmap
, &img
->mask
,
6794 if (rc
== XpmSuccess
)
6796 /* Remember allocated colors. */
6797 img
->ncolors
= attrs
.nalloc_pixels
;
6798 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
6799 * sizeof *img
->colors
);
6800 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
6802 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
6803 #ifdef DEBUG_X_COLORS
6804 register_color (img
->colors
[i
]);
6808 img
->width
= attrs
.width
;
6809 img
->height
= attrs
.height
;
6810 xassert (img
->width
> 0 && img
->height
> 0);
6812 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6814 XpmFreeAttributes (&attrs
);
6822 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
6825 case XpmFileInvalid
:
6826 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
6830 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
6833 case XpmColorFailed
:
6834 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
6838 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
6843 return rc
== XpmSuccess
;
6846 #endif /* HAVE_XPM != 0 */
6849 /***********************************************************************
6851 ***********************************************************************/
6853 /* An entry in the color table mapping an RGB color to a pixel color. */
6858 unsigned long pixel
;
6860 /* Next in color table collision list. */
6861 struct ct_color
*next
;
6864 /* The bucket vector size to use. Must be prime. */
6868 /* Value is a hash of the RGB color given by R, G, and B. */
6870 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6872 /* The color hash table. */
6874 struct ct_color
**ct_table
;
6876 /* Number of entries in the color table. */
6878 int ct_colors_allocated
;
6880 /* Function prototypes. */
6882 static void init_color_table
P_ ((void));
6883 static void free_color_table
P_ ((void));
6884 static unsigned long *colors_in_color_table
P_ ((int *n
));
6885 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
6886 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
6889 /* Initialize the color table. */
6894 int size
= CT_SIZE
* sizeof (*ct_table
);
6895 ct_table
= (struct ct_color
**) xmalloc (size
);
6896 bzero (ct_table
, size
);
6897 ct_colors_allocated
= 0;
6901 /* Free memory associated with the color table. */
6907 struct ct_color
*p
, *next
;
6909 for (i
= 0; i
< CT_SIZE
; ++i
)
6910 for (p
= ct_table
[i
]; p
; p
= next
)
6921 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6922 entry for that color already is in the color table, return the
6923 pixel color of that entry. Otherwise, allocate a new color for R,
6924 G, B, and make an entry in the color table. */
6926 static unsigned long
6927 lookup_rgb_color (f
, r
, g
, b
)
6931 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
6932 int i
= hash
% CT_SIZE
;
6935 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6936 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
6950 cmap
= FRAME_X_COLORMAP (f
);
6951 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
6956 ++ct_colors_allocated
;
6958 p
= (struct ct_color
*) xmalloc (sizeof *p
);
6962 p
->pixel
= color
.pixel
;
6963 p
->next
= ct_table
[i
];
6967 return FRAME_FOREGROUND_PIXEL (f
);
6974 /* Look up pixel color PIXEL which is used on frame F in the color
6975 table. If not already present, allocate it. Value is PIXEL. */
6977 static unsigned long
6978 lookup_pixel_color (f
, pixel
)
6980 unsigned long pixel
;
6982 int i
= pixel
% CT_SIZE
;
6985 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6986 if (p
->pixel
== pixel
)
6997 cmap
= FRAME_X_COLORMAP (f
);
6998 color
.pixel
= pixel
;
6999 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7000 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7005 ++ct_colors_allocated
;
7007 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7012 p
->next
= ct_table
[i
];
7016 return FRAME_FOREGROUND_PIXEL (f
);
7023 /* Value is a vector of all pixel colors contained in the color table,
7024 allocated via xmalloc. Set *N to the number of colors. */
7026 static unsigned long *
7027 colors_in_color_table (n
)
7032 unsigned long *colors
;
7034 if (ct_colors_allocated
== 0)
7041 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7043 *n
= ct_colors_allocated
;
7045 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7046 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7047 colors
[j
++] = p
->pixel
;
7055 /***********************************************************************
7057 ***********************************************************************/
7059 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7060 int, XImage
*, int));
7061 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7062 XColor
*, int, XImage
*, int));
7065 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7066 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7067 the width of one row in the image. */
7070 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
7080 for (x
= 0; x
< width
; ++x
)
7081 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
7083 XQueryColors (FRAME_X_DISPLAY (f
), cmap
, colors
, width
);
7087 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7088 containing the pixel colors to write. F is the frame we are
7092 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
7101 for (x
= 0; x
< width
; ++x
)
7102 XPutPixel (ximg
, x
, y
, pixels
[x
]);
7106 /* Transform image IMG which is used on frame F with a Laplace
7107 edge-detection algorithm. The result is an image that can be used
7108 to draw disabled buttons, for example. */
7115 Colormap cmap
= FRAME_X_COLORMAP (f
);
7116 XImage
*ximg
, *oimg
;
7122 int in_y
, out_y
, rc
;
7127 /* Get the X image IMG->pixmap. */
7128 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7129 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7131 /* Allocate 3 input rows, and one output row of colors. */
7132 for (i
= 0; i
< 3; ++i
)
7133 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
7134 out
= (long *) alloca (img
->width
* sizeof (long));
7136 /* Create an X image for output. */
7137 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7140 /* Fill first two rows. */
7141 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
7142 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
7145 /* Write first row, all zeros. */
7146 init_color_table ();
7147 pixel
= lookup_rgb_color (f
, 0, 0, 0);
7148 for (x
= 0; x
< img
->width
; ++x
)
7150 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
7153 for (y
= 2; y
< img
->height
; ++y
)
7156 int rowb
= (y
+ 2) % 3;
7158 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
7160 for (x
= 0; x
< img
->width
- 2; ++x
)
7162 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
7163 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
7164 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
7166 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
7170 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
7173 /* Write last line, all zeros. */
7174 for (x
= 0; x
< img
->width
; ++x
)
7176 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
7178 /* Free the input image, and free resources of IMG. */
7179 XDestroyImage (ximg
);
7180 x_clear_image (f
, img
);
7182 /* Put the output image into pixmap, and destroy it. */
7183 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7184 x_destroy_x_image (oimg
);
7186 /* Remember new pixmap and colors in IMG. */
7187 img
->pixmap
= pixmap
;
7188 img
->colors
= colors_in_color_table (&img
->ncolors
);
7189 free_color_table ();
7195 /* Build a mask for image IMG which is used on frame F. FILE is the
7196 name of an image file, for error messages. HOW determines how to
7197 determine the background color of IMG. If it is a list '(R G B)',
7198 with R, G, and B being integers >= 0, take that as the color of the
7199 background. Otherwise, determine the background color of IMG
7200 heuristically. Value is non-zero if successful. */
7203 x_build_heuristic_mask (f
, img
, how
)
7208 Display
*dpy
= FRAME_X_DISPLAY (f
);
7209 XImage
*ximg
, *mask_img
;
7210 int x
, y
, rc
, look_at_corners_p
;
7215 /* Create an image and pixmap serving as mask. */
7216 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
7217 &mask_img
, &img
->mask
);
7224 /* Get the X image of IMG->pixmap. */
7225 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7228 /* Determine the background color of ximg. If HOW is `(R G B)'
7229 take that as color. Otherwise, try to determine the color
7231 look_at_corners_p
= 1;
7239 && NATNUMP (XCAR (how
)))
7241 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
7245 if (i
== 3 && NILP (how
))
7247 char color_name
[30];
7248 XColor exact
, color
;
7251 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
7253 cmap
= FRAME_X_COLORMAP (f
);
7254 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
7257 look_at_corners_p
= 0;
7262 if (look_at_corners_p
)
7264 unsigned long corners
[4];
7267 /* Get the colors at the corners of ximg. */
7268 corners
[0] = XGetPixel (ximg
, 0, 0);
7269 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7270 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7271 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7273 /* Choose the most frequently found color as background. */
7274 for (i
= best_count
= 0; i
< 4; ++i
)
7278 for (j
= n
= 0; j
< 4; ++j
)
7279 if (corners
[i
] == corners
[j
])
7283 bg
= corners
[i
], best_count
= n
;
7287 /* Set all bits in mask_img to 1 whose color in ximg is different
7288 from the background color bg. */
7289 for (y
= 0; y
< img
->height
; ++y
)
7290 for (x
= 0; x
< img
->width
; ++x
)
7291 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7293 /* Put mask_img into img->mask. */
7294 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7295 x_destroy_x_image (mask_img
);
7296 XDestroyImage (ximg
);
7304 /***********************************************************************
7305 PBM (mono, gray, color)
7306 ***********************************************************************/
7308 static int pbm_image_p
P_ ((Lisp_Object object
));
7309 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7310 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
7312 /* The symbol `pbm' identifying images of this type. */
7316 /* Indices of image specification fields in gs_format, below. */
7318 enum pbm_keyword_index
7331 /* Vector of image_keyword structures describing the format
7332 of valid user-defined image specifications. */
7334 static struct image_keyword pbm_format
[PBM_LAST
] =
7336 {":type", IMAGE_SYMBOL_VALUE
, 1},
7337 {":file", IMAGE_STRING_VALUE
, 0},
7338 {":data", IMAGE_STRING_VALUE
, 0},
7339 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7340 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7341 {":relief", IMAGE_INTEGER_VALUE
, 0},
7342 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7343 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7346 /* Structure describing the image type `pbm'. */
7348 static struct image_type pbm_type
=
7358 /* Return non-zero if OBJECT is a valid PBM image specification. */
7361 pbm_image_p (object
)
7364 struct image_keyword fmt
[PBM_LAST
];
7366 bcopy (pbm_format
, fmt
, sizeof fmt
);
7368 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
7371 /* Must specify either :data or :file. */
7372 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
7376 /* Scan a decimal number from *S and return it. Advance *S while
7377 reading the number. END is the end of the string. Value is -1 at
7381 pbm_scan_number (s
, end
)
7382 unsigned char **s
, *end
;
7388 /* Skip white-space. */
7389 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
7394 /* Skip comment to end of line. */
7395 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
7398 else if (isdigit (c
))
7400 /* Read decimal number. */
7402 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
7403 val
= 10 * val
+ c
- '0';
7414 /* Load PBM image IMG for use on frame F. */
7422 int width
, height
, max_color_idx
= 0;
7424 Lisp_Object file
, specified_file
;
7425 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
7426 struct gcpro gcpro1
;
7427 unsigned char *contents
= NULL
;
7428 unsigned char *end
, *p
;
7431 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7435 if (STRINGP (specified_file
))
7437 file
= x_find_image_file (specified_file
);
7438 if (!STRINGP (file
))
7440 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7445 contents
= slurp_file (XSTRING (file
)->data
, &size
);
7446 if (contents
== NULL
)
7448 image_error ("Error reading `%s'", file
, Qnil
);
7454 end
= contents
+ size
;
7459 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7460 p
= XSTRING (data
)->data
;
7461 end
= p
+ STRING_BYTES (XSTRING (data
));
7464 /* Check magic number. */
7465 if (end
- p
< 2 || *p
++ != 'P')
7467 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
7477 raw_p
= 0, type
= PBM_MONO
;
7481 raw_p
= 0, type
= PBM_GRAY
;
7485 raw_p
= 0, type
= PBM_COLOR
;
7489 raw_p
= 1, type
= PBM_MONO
;
7493 raw_p
= 1, type
= PBM_GRAY
;
7497 raw_p
= 1, type
= PBM_COLOR
;
7501 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
7505 /* Read width, height, maximum color-component. Characters
7506 starting with `#' up to the end of a line are ignored. */
7507 width
= pbm_scan_number (&p
, end
);
7508 height
= pbm_scan_number (&p
, end
);
7510 if (type
!= PBM_MONO
)
7512 max_color_idx
= pbm_scan_number (&p
, end
);
7513 if (raw_p
&& max_color_idx
> 255)
7514 max_color_idx
= 255;
7519 || (type
!= PBM_MONO
&& max_color_idx
< 0))
7523 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
7524 &ximg
, &img
->pixmap
))
7530 /* Initialize the color hash table. */
7531 init_color_table ();
7533 if (type
== PBM_MONO
)
7537 for (y
= 0; y
< height
; ++y
)
7538 for (x
= 0; x
< width
; ++x
)
7548 g
= pbm_scan_number (&p
, end
);
7550 XPutPixel (ximg
, x
, y
, (g
7551 ? FRAME_FOREGROUND_PIXEL (f
)
7552 : FRAME_BACKGROUND_PIXEL (f
)));
7557 for (y
= 0; y
< height
; ++y
)
7558 for (x
= 0; x
< width
; ++x
)
7562 if (type
== PBM_GRAY
)
7563 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
7572 r
= pbm_scan_number (&p
, end
);
7573 g
= pbm_scan_number (&p
, end
);
7574 b
= pbm_scan_number (&p
, end
);
7577 if (r
< 0 || g
< 0 || b
< 0)
7581 XDestroyImage (ximg
);
7583 image_error ("Invalid pixel value in image `%s'",
7588 /* RGB values are now in the range 0..max_color_idx.
7589 Scale this to the range 0..0xffff supported by X. */
7590 r
= (double) r
* 65535 / max_color_idx
;
7591 g
= (double) g
* 65535 / max_color_idx
;
7592 b
= (double) b
* 65535 / max_color_idx
;
7593 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
7597 /* Store in IMG->colors the colors allocated for the image, and
7598 free the color table. */
7599 img
->colors
= colors_in_color_table (&img
->ncolors
);
7600 free_color_table ();
7602 /* Put the image into a pixmap. */
7603 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7604 x_destroy_x_image (ximg
);
7608 img
->height
= height
;
7617 /***********************************************************************
7619 ***********************************************************************/
7625 /* Function prototypes. */
7627 static int png_image_p
P_ ((Lisp_Object object
));
7628 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
7630 /* The symbol `png' identifying images of this type. */
7634 /* Indices of image specification fields in png_format, below. */
7636 enum png_keyword_index
7649 /* Vector of image_keyword structures describing the format
7650 of valid user-defined image specifications. */
7652 static struct image_keyword png_format
[PNG_LAST
] =
7654 {":type", IMAGE_SYMBOL_VALUE
, 1},
7655 {":data", IMAGE_STRING_VALUE
, 0},
7656 {":file", IMAGE_STRING_VALUE
, 0},
7657 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7658 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7659 {":relief", IMAGE_INTEGER_VALUE
, 0},
7660 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7661 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7664 /* Structure describing the image type `png'. */
7666 static struct image_type png_type
=
7676 /* Return non-zero if OBJECT is a valid PNG image specification. */
7679 png_image_p (object
)
7682 struct image_keyword fmt
[PNG_LAST
];
7683 bcopy (png_format
, fmt
, sizeof fmt
);
7685 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
7688 /* Must specify either the :data or :file keyword. */
7689 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
7693 /* Error and warning handlers installed when the PNG library
7697 my_png_error (png_ptr
, msg
)
7698 png_struct
*png_ptr
;
7701 xassert (png_ptr
!= NULL
);
7702 image_error ("PNG error: %s", build_string (msg
), Qnil
);
7703 longjmp (png_ptr
->jmpbuf
, 1);
7708 my_png_warning (png_ptr
, msg
)
7709 png_struct
*png_ptr
;
7712 xassert (png_ptr
!= NULL
);
7713 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
7716 /* Memory source for PNG decoding. */
7718 struct png_memory_storage
7720 unsigned char *bytes
; /* The data */
7721 size_t len
; /* How big is it? */
7722 int index
; /* Where are we? */
7726 /* Function set as reader function when reading PNG image from memory.
7727 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7728 bytes from the input to DATA. */
7731 png_read_from_memory (png_ptr
, data
, length
)
7732 png_structp png_ptr
;
7736 struct png_memory_storage
*tbr
7737 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
7739 if (length
> tbr
->len
- tbr
->index
)
7740 png_error (png_ptr
, "Read error");
7742 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
7743 tbr
->index
= tbr
->index
+ length
;
7746 /* Load PNG image IMG for use on frame F. Value is non-zero if
7754 Lisp_Object file
, specified_file
;
7755 Lisp_Object specified_data
;
7757 XImage
*ximg
, *mask_img
= NULL
;
7758 struct gcpro gcpro1
;
7759 png_struct
*png_ptr
= NULL
;
7760 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
7763 png_byte
*pixels
= NULL
;
7764 png_byte
**rows
= NULL
;
7765 png_uint_32 width
, height
;
7766 int bit_depth
, color_type
, interlace_type
;
7768 png_uint_32 row_bytes
;
7771 double screen_gamma
, image_gamma
;
7773 struct png_memory_storage tbr
; /* Data to be read */
7775 /* Find out what file to load. */
7776 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7777 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7781 if (NILP (specified_data
))
7783 file
= x_find_image_file (specified_file
);
7784 if (!STRINGP (file
))
7786 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7791 /* Open the image file. */
7792 fp
= fopen (XSTRING (file
)->data
, "rb");
7795 image_error ("Cannot open image file `%s'", file
, Qnil
);
7801 /* Check PNG signature. */
7802 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
7803 || !png_check_sig (sig
, sizeof sig
))
7805 image_error ("Not a PNG file: `%s'", file
, Qnil
);
7813 /* Read from memory. */
7814 tbr
.bytes
= XSTRING (specified_data
)->data
;
7815 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
7818 /* Check PNG signature. */
7819 if (tbr
.len
< sizeof sig
7820 || !png_check_sig (tbr
.bytes
, sizeof sig
))
7822 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
7827 /* Need to skip past the signature. */
7828 tbr
.bytes
+= sizeof (sig
);
7831 /* Initialize read and info structs for PNG lib. */
7832 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
7833 my_png_error
, my_png_warning
);
7836 if (fp
) fclose (fp
);
7841 info_ptr
= png_create_info_struct (png_ptr
);
7844 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
7845 if (fp
) fclose (fp
);
7850 end_info
= png_create_info_struct (png_ptr
);
7853 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
7854 if (fp
) fclose (fp
);
7859 /* Set error jump-back. We come back here when the PNG library
7860 detects an error. */
7861 if (setjmp (png_ptr
->jmpbuf
))
7865 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
7868 if (fp
) fclose (fp
);
7873 /* Read image info. */
7874 if (!NILP (specified_data
))
7875 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
7877 png_init_io (png_ptr
, fp
);
7879 png_set_sig_bytes (png_ptr
, sizeof sig
);
7880 png_read_info (png_ptr
, info_ptr
);
7881 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
7882 &interlace_type
, NULL
, NULL
);
7884 /* If image contains simply transparency data, we prefer to
7885 construct a clipping mask. */
7886 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
7891 /* This function is easier to write if we only have to handle
7892 one data format: RGB or RGBA with 8 bits per channel. Let's
7893 transform other formats into that format. */
7895 /* Strip more than 8 bits per channel. */
7896 if (bit_depth
== 16)
7897 png_set_strip_16 (png_ptr
);
7899 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7901 png_set_expand (png_ptr
);
7903 /* Convert grayscale images to RGB. */
7904 if (color_type
== PNG_COLOR_TYPE_GRAY
7905 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
7906 png_set_gray_to_rgb (png_ptr
);
7908 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
7909 gamma_str
= getenv ("SCREEN_GAMMA");
7910 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
7912 /* Tell the PNG lib to handle gamma correction for us. */
7914 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7915 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
7916 /* There is a special chunk in the image specifying the gamma. */
7917 png_set_sRGB (png_ptr
, info_ptr
, intent
);
7920 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
7921 /* Image contains gamma information. */
7922 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
7924 /* Use a default of 0.5 for the image gamma. */
7925 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
7927 /* Handle alpha channel by combining the image with a background
7928 color. Do this only if a real alpha channel is supplied. For
7929 simple transparency, we prefer a clipping mask. */
7932 png_color_16
*image_background
;
7934 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
7935 /* Image contains a background color with which to
7936 combine the image. */
7937 png_set_background (png_ptr
, image_background
,
7938 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
7941 /* Image does not contain a background color with which
7942 to combine the image data via an alpha channel. Use
7943 the frame's background instead. */
7946 png_color_16 frame_background
;
7949 cmap
= FRAME_X_COLORMAP (f
);
7950 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7951 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7954 bzero (&frame_background
, sizeof frame_background
);
7955 frame_background
.red
= color
.red
;
7956 frame_background
.green
= color
.green
;
7957 frame_background
.blue
= color
.blue
;
7959 png_set_background (png_ptr
, &frame_background
,
7960 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
7964 /* Update info structure. */
7965 png_read_update_info (png_ptr
, info_ptr
);
7967 /* Get number of channels. Valid values are 1 for grayscale images
7968 and images with a palette, 2 for grayscale images with transparency
7969 information (alpha channel), 3 for RGB images, and 4 for RGB
7970 images with alpha channel, i.e. RGBA. If conversions above were
7971 sufficient we should only have 3 or 4 channels here. */
7972 channels
= png_get_channels (png_ptr
, info_ptr
);
7973 xassert (channels
== 3 || channels
== 4);
7975 /* Number of bytes needed for one row of the image. */
7976 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
7978 /* Allocate memory for the image. */
7979 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
7980 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
7981 for (i
= 0; i
< height
; ++i
)
7982 rows
[i
] = pixels
+ i
* row_bytes
;
7984 /* Read the entire image. */
7985 png_read_image (png_ptr
, rows
);
7986 png_read_end (png_ptr
, info_ptr
);
7995 /* Create the X image and pixmap. */
7996 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8003 /* Create an image and pixmap serving as mask if the PNG image
8004 contains an alpha channel. */
8007 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8008 &mask_img
, &img
->mask
))
8010 x_destroy_x_image (ximg
);
8011 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8017 /* Fill the X image and mask from PNG data. */
8018 init_color_table ();
8020 for (y
= 0; y
< height
; ++y
)
8022 png_byte
*p
= rows
[y
];
8024 for (x
= 0; x
< width
; ++x
)
8031 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8033 /* An alpha channel, aka mask channel, associates variable
8034 transparency with an image. Where other image formats
8035 support binary transparency---fully transparent or fully
8036 opaque---PNG allows up to 254 levels of partial transparency.
8037 The PNG library implements partial transparency by combining
8038 the image with a specified background color.
8040 I'm not sure how to handle this here nicely: because the
8041 background on which the image is displayed may change, for
8042 real alpha channel support, it would be necessary to create
8043 a new image for each possible background.
8045 What I'm doing now is that a mask is created if we have
8046 boolean transparency information. Otherwise I'm using
8047 the frame's background color to combine the image with. */
8052 XPutPixel (mask_img
, x
, y
, *p
> 0);
8058 /* Remember colors allocated for this image. */
8059 img
->colors
= colors_in_color_table (&img
->ncolors
);
8060 free_color_table ();
8063 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8068 img
->height
= height
;
8070 /* Put the image into the pixmap, then free the X image and its buffer. */
8071 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8072 x_destroy_x_image (ximg
);
8074 /* Same for the mask. */
8077 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8078 x_destroy_x_image (mask_img
);
8086 #endif /* HAVE_PNG != 0 */
8090 /***********************************************************************
8092 ***********************************************************************/
8096 /* Work around a warning about HAVE_STDLIB_H being redefined in
8098 #ifdef HAVE_STDLIB_H
8099 #define HAVE_STDLIB_H_1
8100 #undef HAVE_STDLIB_H
8101 #endif /* HAVE_STLIB_H */
8103 #include <jpeglib.h>
8107 #ifdef HAVE_STLIB_H_1
8108 #define HAVE_STDLIB_H 1
8111 static int jpeg_image_p
P_ ((Lisp_Object object
));
8112 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8114 /* The symbol `jpeg' identifying images of this type. */
8118 /* Indices of image specification fields in gs_format, below. */
8120 enum jpeg_keyword_index
8129 JPEG_HEURISTIC_MASK
,
8133 /* Vector of image_keyword structures describing the format
8134 of valid user-defined image specifications. */
8136 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8138 {":type", IMAGE_SYMBOL_VALUE
, 1},
8139 {":data", IMAGE_STRING_VALUE
, 0},
8140 {":file", IMAGE_STRING_VALUE
, 0},
8141 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8142 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8143 {":relief", IMAGE_INTEGER_VALUE
, 0},
8144 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8145 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8148 /* Structure describing the image type `jpeg'. */
8150 static struct image_type jpeg_type
=
8160 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8163 jpeg_image_p (object
)
8166 struct image_keyword fmt
[JPEG_LAST
];
8168 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8170 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
8173 /* Must specify either the :data or :file keyword. */
8174 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
8178 struct my_jpeg_error_mgr
8180 struct jpeg_error_mgr pub
;
8181 jmp_buf setjmp_buffer
;
8186 my_error_exit (cinfo
)
8189 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8190 longjmp (mgr
->setjmp_buffer
, 1);
8194 /* Init source method for JPEG data source manager. Called by
8195 jpeg_read_header() before any data is actually read. See
8196 libjpeg.doc from the JPEG lib distribution. */
8199 our_init_source (cinfo
)
8200 j_decompress_ptr cinfo
;
8205 /* Fill input buffer method for JPEG data source manager. Called
8206 whenever more data is needed. We read the whole image in one step,
8207 so this only adds a fake end of input marker at the end. */
8210 our_fill_input_buffer (cinfo
)
8211 j_decompress_ptr cinfo
;
8213 /* Insert a fake EOI marker. */
8214 struct jpeg_source_mgr
*src
= cinfo
->src
;
8215 static JOCTET buffer
[2];
8217 buffer
[0] = (JOCTET
) 0xFF;
8218 buffer
[1] = (JOCTET
) JPEG_EOI
;
8220 src
->next_input_byte
= buffer
;
8221 src
->bytes_in_buffer
= 2;
8226 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8227 is the JPEG data source manager. */
8230 our_skip_input_data (cinfo
, num_bytes
)
8231 j_decompress_ptr cinfo
;
8234 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8238 if (num_bytes
> src
->bytes_in_buffer
)
8239 ERREXIT (cinfo
, JERR_INPUT_EOF
);
8241 src
->bytes_in_buffer
-= num_bytes
;
8242 src
->next_input_byte
+= num_bytes
;
8247 /* Method to terminate data source. Called by
8248 jpeg_finish_decompress() after all data has been processed. */
8251 our_term_source (cinfo
)
8252 j_decompress_ptr cinfo
;
8257 /* Set up the JPEG lib for reading an image from DATA which contains
8258 LEN bytes. CINFO is the decompression info structure created for
8259 reading the image. */
8262 jpeg_memory_src (cinfo
, data
, len
)
8263 j_decompress_ptr cinfo
;
8267 struct jpeg_source_mgr
*src
;
8269 if (cinfo
->src
== NULL
)
8271 /* First time for this JPEG object? */
8272 cinfo
->src
= (struct jpeg_source_mgr
*)
8273 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
8274 sizeof (struct jpeg_source_mgr
));
8275 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8276 src
->next_input_byte
= data
;
8279 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8280 src
->init_source
= our_init_source
;
8281 src
->fill_input_buffer
= our_fill_input_buffer
;
8282 src
->skip_input_data
= our_skip_input_data
;
8283 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
8284 src
->term_source
= our_term_source
;
8285 src
->bytes_in_buffer
= len
;
8286 src
->next_input_byte
= data
;
8290 /* Load image IMG for use on frame F. Patterned after example.c
8291 from the JPEG lib. */
8298 struct jpeg_decompress_struct cinfo
;
8299 struct my_jpeg_error_mgr mgr
;
8300 Lisp_Object file
, specified_file
;
8301 Lisp_Object specified_data
;
8304 int row_stride
, x
, y
;
8305 XImage
*ximg
= NULL
;
8307 unsigned long *colors
;
8309 struct gcpro gcpro1
;
8311 /* Open the JPEG file. */
8312 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8313 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8317 if (NILP (specified_data
))
8319 file
= x_find_image_file (specified_file
);
8320 if (!STRINGP (file
))
8322 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8327 fp
= fopen (XSTRING (file
)->data
, "r");
8330 image_error ("Cannot open `%s'", file
, Qnil
);
8336 /* Customize libjpeg's error handling to call my_error_exit when an
8337 error is detected. This function will perform a longjmp. */
8338 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8339 mgr
.pub
.error_exit
= my_error_exit
;
8341 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8345 /* Called from my_error_exit. Display a JPEG error. */
8346 char buffer
[JMSG_LENGTH_MAX
];
8347 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8348 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
8349 build_string (buffer
));
8352 /* Close the input file and destroy the JPEG object. */
8355 jpeg_destroy_decompress (&cinfo
);
8359 /* If we already have an XImage, free that. */
8360 x_destroy_x_image (ximg
);
8362 /* Free pixmap and colors. */
8363 x_clear_image (f
, img
);
8370 /* Create the JPEG decompression object. Let it read from fp.
8371 Read the JPEG image header. */
8372 jpeg_create_decompress (&cinfo
);
8374 if (NILP (specified_data
))
8375 jpeg_stdio_src (&cinfo
, fp
);
8377 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
8378 STRING_BYTES (XSTRING (specified_data
)));
8380 jpeg_read_header (&cinfo
, TRUE
);
8382 /* Customize decompression so that color quantization will be used.
8383 Start decompression. */
8384 cinfo
.quantize_colors
= TRUE
;
8385 jpeg_start_decompress (&cinfo
);
8386 width
= img
->width
= cinfo
.output_width
;
8387 height
= img
->height
= cinfo
.output_height
;
8391 /* Create X image and pixmap. */
8392 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8395 longjmp (mgr
.setjmp_buffer
, 2);
8398 /* Allocate colors. When color quantization is used,
8399 cinfo.actual_number_of_colors has been set with the number of
8400 colors generated, and cinfo.colormap is a two-dimensional array
8401 of color indices in the range 0..cinfo.actual_number_of_colors.
8402 No more than 255 colors will be generated. */
8406 if (cinfo
.out_color_components
> 2)
8407 ir
= 0, ig
= 1, ib
= 2;
8408 else if (cinfo
.out_color_components
> 1)
8409 ir
= 0, ig
= 1, ib
= 0;
8411 ir
= 0, ig
= 0, ib
= 0;
8413 /* Use the color table mechanism because it handles colors that
8414 cannot be allocated nicely. Such colors will be replaced with
8415 a default color, and we don't have to care about which colors
8416 can be freed safely, and which can't. */
8417 init_color_table ();
8418 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8421 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8423 /* Multiply RGB values with 255 because X expects RGB values
8424 in the range 0..0xffff. */
8425 int r
= cinfo
.colormap
[ir
][i
] << 8;
8426 int g
= cinfo
.colormap
[ig
][i
] << 8;
8427 int b
= cinfo
.colormap
[ib
][i
] << 8;
8428 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8431 /* Remember those colors actually allocated. */
8432 img
->colors
= colors_in_color_table (&img
->ncolors
);
8433 free_color_table ();
8437 row_stride
= width
* cinfo
.output_components
;
8438 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
8440 for (y
= 0; y
< height
; ++y
)
8442 jpeg_read_scanlines (&cinfo
, buffer
, 1);
8443 for (x
= 0; x
< cinfo
.output_width
; ++x
)
8444 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
8448 jpeg_finish_decompress (&cinfo
);
8449 jpeg_destroy_decompress (&cinfo
);
8453 /* Put the image into the pixmap. */
8454 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8455 x_destroy_x_image (ximg
);
8461 #endif /* HAVE_JPEG */
8465 /***********************************************************************
8467 ***********************************************************************/
8473 static int tiff_image_p
P_ ((Lisp_Object object
));
8474 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
8476 /* The symbol `tiff' identifying images of this type. */
8480 /* Indices of image specification fields in tiff_format, below. */
8482 enum tiff_keyword_index
8491 TIFF_HEURISTIC_MASK
,
8495 /* Vector of image_keyword structures describing the format
8496 of valid user-defined image specifications. */
8498 static struct image_keyword tiff_format
[TIFF_LAST
] =
8500 {":type", IMAGE_SYMBOL_VALUE
, 1},
8501 {":data", IMAGE_STRING_VALUE
, 0},
8502 {":file", IMAGE_STRING_VALUE
, 0},
8503 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8504 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8505 {":relief", IMAGE_INTEGER_VALUE
, 0},
8506 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8507 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8510 /* Structure describing the image type `tiff'. */
8512 static struct image_type tiff_type
=
8522 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8525 tiff_image_p (object
)
8528 struct image_keyword fmt
[TIFF_LAST
];
8529 bcopy (tiff_format
, fmt
, sizeof fmt
);
8531 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
8534 /* Must specify either the :data or :file keyword. */
8535 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
8539 /* Reading from a memory buffer for TIFF images Based on the PNG
8540 memory source, but we have to provide a lot of extra functions.
8543 We really only need to implement read and seek, but I am not
8544 convinced that the TIFF library is smart enough not to destroy
8545 itself if we only hand it the function pointers we need to
8550 unsigned char *bytes
;
8558 tiff_read_from_memory (data
, buf
, size
)
8563 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8565 if (size
> src
->len
- src
->index
)
8567 bcopy (src
->bytes
+ src
->index
, buf
, size
);
8574 tiff_write_from_memory (data
, buf
, size
)
8584 tiff_seek_in_memory (data
, off
, whence
)
8589 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8594 case SEEK_SET
: /* Go from beginning of source. */
8598 case SEEK_END
: /* Go from end of source. */
8599 idx
= src
->len
+ off
;
8602 case SEEK_CUR
: /* Go from current position. */
8603 idx
= src
->index
+ off
;
8606 default: /* Invalid `whence'. */
8610 if (idx
> src
->len
|| idx
< 0)
8619 tiff_close_memory (data
)
8628 tiff_mmap_memory (data
, pbase
, psize
)
8633 /* It is already _IN_ memory. */
8639 tiff_unmap_memory (data
, base
, size
)
8644 /* We don't need to do this. */
8649 tiff_size_of_memory (data
)
8652 return ((tiff_memory_source
*) data
)->len
;
8656 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8664 Lisp_Object file
, specified_file
;
8665 Lisp_Object specified_data
;
8667 int width
, height
, x
, y
;
8671 struct gcpro gcpro1
;
8672 tiff_memory_source memsrc
;
8674 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8675 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8679 if (NILP (specified_data
))
8681 /* Read from a file */
8682 file
= x_find_image_file (specified_file
);
8683 if (!STRINGP (file
))
8685 image_error ("Cannot find image file `%s'", file
, Qnil
);
8690 /* Try to open the image file. */
8691 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
8694 image_error ("Cannot open `%s'", file
, Qnil
);
8701 /* Memory source! */
8702 memsrc
.bytes
= XSTRING (specified_data
)->data
;
8703 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
8706 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
8707 (TIFFReadWriteProc
) tiff_read_from_memory
,
8708 (TIFFReadWriteProc
) tiff_write_from_memory
,
8709 tiff_seek_in_memory
,
8711 tiff_size_of_memory
,
8717 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
8723 /* Get width and height of the image, and allocate a raster buffer
8724 of width x height 32-bit values. */
8725 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
8726 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
8727 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8729 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8733 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
8741 /* Create the X image and pixmap. */
8742 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8750 /* Initialize the color table. */
8751 init_color_table ();
8753 /* Process the pixel raster. Origin is in the lower-left corner. */
8754 for (y
= 0; y
< height
; ++y
)
8756 uint32
*row
= buf
+ y
* width
;
8758 for (x
= 0; x
< width
; ++x
)
8760 uint32 abgr
= row
[x
];
8761 int r
= TIFFGetR (abgr
) << 8;
8762 int g
= TIFFGetG (abgr
) << 8;
8763 int b
= TIFFGetB (abgr
) << 8;
8764 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
8768 /* Remember the colors allocated for the image. Free the color table. */
8769 img
->colors
= colors_in_color_table (&img
->ncolors
);
8770 free_color_table ();
8772 /* Put the image into the pixmap, then free the X image and its buffer. */
8773 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8774 x_destroy_x_image (ximg
);
8779 img
->height
= height
;
8785 #endif /* HAVE_TIFF != 0 */
8789 /***********************************************************************
8791 ***********************************************************************/
8795 #include <gif_lib.h>
8797 static int gif_image_p
P_ ((Lisp_Object object
));
8798 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
8800 /* The symbol `gif' identifying images of this type. */
8804 /* Indices of image specification fields in gif_format, below. */
8806 enum gif_keyword_index
8820 /* Vector of image_keyword structures describing the format
8821 of valid user-defined image specifications. */
8823 static struct image_keyword gif_format
[GIF_LAST
] =
8825 {":type", IMAGE_SYMBOL_VALUE
, 1},
8826 {":data", IMAGE_STRING_VALUE
, 0},
8827 {":file", IMAGE_STRING_VALUE
, 0},
8828 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8829 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8830 {":relief", IMAGE_INTEGER_VALUE
, 0},
8831 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8832 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8833 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
8836 /* Structure describing the image type `gif'. */
8838 static struct image_type gif_type
=
8848 /* Return non-zero if OBJECT is a valid GIF image specification. */
8851 gif_image_p (object
)
8854 struct image_keyword fmt
[GIF_LAST
];
8855 bcopy (gif_format
, fmt
, sizeof fmt
);
8857 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
8860 /* Must specify either the :data or :file keyword. */
8861 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8865 /* Reading a GIF image from memory
8866 Based on the PNG memory stuff to a certain extent. */
8870 unsigned char *bytes
;
8877 /* Make the current memory source available to gif_read_from_memory.
8878 It's done this way because not all versions of libungif support
8879 a UserData field in the GifFileType structure. */
8880 static gif_memory_source
*current_gif_memory_src
;
8883 gif_read_from_memory (file
, buf
, len
)
8888 gif_memory_source
*src
= current_gif_memory_src
;
8890 if (len
> src
->len
- src
->index
)
8893 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8899 /* Load GIF image IMG for use on frame F. Value is non-zero if
8907 Lisp_Object file
, specified_file
;
8908 Lisp_Object specified_data
;
8909 int rc
, width
, height
, x
, y
, i
;
8911 ColorMapObject
*gif_color_map
;
8912 unsigned long pixel_colors
[256];
8914 struct gcpro gcpro1
;
8916 int ino
, image_left
, image_top
, image_width
, image_height
;
8917 gif_memory_source memsrc
;
8918 unsigned char *raster
;
8920 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8921 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8925 if (NILP (specified_data
))
8927 file
= x_find_image_file (specified_file
);
8928 if (!STRINGP (file
))
8930 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8935 /* Open the GIF file. */
8936 gif
= DGifOpenFileName (XSTRING (file
)->data
);
8939 image_error ("Cannot open `%s'", file
, Qnil
);
8946 /* Read from memory! */
8947 current_gif_memory_src
= &memsrc
;
8948 memsrc
.bytes
= XSTRING (specified_data
)->data
;
8949 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
8952 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
8955 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8961 /* Read entire contents. */
8962 rc
= DGifSlurp (gif
);
8963 if (rc
== GIF_ERROR
)
8965 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8966 DGifCloseFile (gif
);
8971 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8972 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8973 if (ino
>= gif
->ImageCount
)
8975 image_error ("Invalid image number `%s' in image `%s'",
8977 DGifCloseFile (gif
);
8982 width
= img
->width
= gif
->SWidth
;
8983 height
= img
->height
= gif
->SHeight
;
8987 /* Create the X image and pixmap. */
8988 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8991 DGifCloseFile (gif
);
8996 /* Allocate colors. */
8997 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8999 gif_color_map
= gif
->SColorMap
;
9000 init_color_table ();
9001 bzero (pixel_colors
, sizeof pixel_colors
);
9003 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9005 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9006 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9007 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9008 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9011 img
->colors
= colors_in_color_table (&img
->ncolors
);
9012 free_color_table ();
9014 /* Clear the part of the screen image that are not covered by
9015 the image from the GIF file. Full animated GIF support
9016 requires more than can be done here (see the gif89 spec,
9017 disposal methods). Let's simply assume that the part
9018 not covered by a sub-image is in the frame's background color. */
9019 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9020 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9021 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9022 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9024 for (y
= 0; y
< image_top
; ++y
)
9025 for (x
= 0; x
< width
; ++x
)
9026 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9028 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9029 for (x
= 0; x
< width
; ++x
)
9030 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9032 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9034 for (x
= 0; x
< image_left
; ++x
)
9035 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9036 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9037 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9040 /* Read the GIF image into the X image. We use a local variable
9041 `raster' here because RasterBits below is a char *, and invites
9042 problems with bytes >= 0x80. */
9043 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9045 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9047 static int interlace_start
[] = {0, 4, 2, 1};
9048 static int interlace_increment
[] = {8, 8, 4, 2};
9050 int row
= interlace_start
[0];
9054 for (y
= 0; y
< image_height
; y
++)
9056 if (row
>= image_height
)
9058 row
= interlace_start
[++pass
];
9059 while (row
>= image_height
)
9060 row
= interlace_start
[++pass
];
9063 for (x
= 0; x
< image_width
; x
++)
9065 int i
= raster
[(y
* image_width
) + x
];
9066 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9070 row
+= interlace_increment
[pass
];
9075 for (y
= 0; y
< image_height
; ++y
)
9076 for (x
= 0; x
< image_width
; ++x
)
9078 int i
= raster
[y
* image_width
+ x
];
9079 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9083 DGifCloseFile (gif
);
9085 /* Put the image into the pixmap, then free the X image and its buffer. */
9086 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9087 x_destroy_x_image (ximg
);
9094 #endif /* HAVE_GIF != 0 */
9098 /***********************************************************************
9100 ***********************************************************************/
9102 static int gs_image_p
P_ ((Lisp_Object object
));
9103 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9104 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9106 /* The symbol `postscript' identifying images of this type. */
9108 Lisp_Object Qpostscript
;
9110 /* Keyword symbols. */
9112 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9114 /* Indices of image specification fields in gs_format, below. */
9116 enum gs_keyword_index
9132 /* Vector of image_keyword structures describing the format
9133 of valid user-defined image specifications. */
9135 static struct image_keyword gs_format
[GS_LAST
] =
9137 {":type", IMAGE_SYMBOL_VALUE
, 1},
9138 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9139 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9140 {":file", IMAGE_STRING_VALUE
, 1},
9141 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9142 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9143 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9144 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9145 {":relief", IMAGE_INTEGER_VALUE
, 0},
9146 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9147 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9150 /* Structure describing the image type `ghostscript'. */
9152 static struct image_type gs_type
=
9162 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9165 gs_clear_image (f
, img
)
9169 /* IMG->data.ptr_val may contain a recorded colormap. */
9170 xfree (img
->data
.ptr_val
);
9171 x_clear_image (f
, img
);
9175 /* Return non-zero if OBJECT is a valid Ghostscript image
9182 struct image_keyword fmt
[GS_LAST
];
9186 bcopy (gs_format
, fmt
, sizeof fmt
);
9188 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9191 /* Bounding box must be a list or vector containing 4 integers. */
9192 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9195 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9196 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9201 else if (VECTORP (tem
))
9203 if (XVECTOR (tem
)->size
!= 4)
9205 for (i
= 0; i
< 4; ++i
)
9206 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9216 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9225 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9226 struct gcpro gcpro1
, gcpro2
;
9228 double in_width
, in_height
;
9229 Lisp_Object pixel_colors
= Qnil
;
9231 /* Compute pixel size of pixmap needed from the given size in the
9232 image specification. Sizes in the specification are in pt. 1 pt
9233 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9235 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9236 in_width
= XFASTINT (pt_width
) / 72.0;
9237 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9238 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9239 in_height
= XFASTINT (pt_height
) / 72.0;
9240 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9242 /* Create the pixmap. */
9244 xassert (img
->pixmap
== 0);
9245 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9246 img
->width
, img
->height
,
9247 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9252 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9256 /* Call the loader to fill the pixmap. It returns a process object
9257 if successful. We do not record_unwind_protect here because
9258 other places in redisplay like calling window scroll functions
9259 don't either. Let the Lisp loader use `unwind-protect' instead. */
9260 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9262 sprintf (buffer
, "%lu %lu",
9263 (unsigned long) FRAME_X_WINDOW (f
),
9264 (unsigned long) img
->pixmap
);
9265 window_and_pixmap_id
= build_string (buffer
);
9267 sprintf (buffer
, "%lu %lu",
9268 FRAME_FOREGROUND_PIXEL (f
),
9269 FRAME_BACKGROUND_PIXEL (f
));
9270 pixel_colors
= build_string (buffer
);
9272 XSETFRAME (frame
, f
);
9273 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9275 loader
= intern ("gs-load-image");
9277 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9278 make_number (img
->width
),
9279 make_number (img
->height
),
9280 window_and_pixmap_id
,
9283 return PROCESSP (img
->data
.lisp_val
);
9287 /* Kill the Ghostscript process that was started to fill PIXMAP on
9288 frame F. Called from XTread_socket when receiving an event
9289 telling Emacs that Ghostscript has finished drawing. */
9292 x_kill_gs_process (pixmap
, f
)
9296 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9300 /* Find the image containing PIXMAP. */
9301 for (i
= 0; i
< c
->used
; ++i
)
9302 if (c
->images
[i
]->pixmap
== pixmap
)
9305 /* Kill the GS process. We should have found PIXMAP in the image
9306 cache and its image should contain a process object. */
9307 xassert (i
< c
->used
);
9309 xassert (PROCESSP (img
->data
.lisp_val
));
9310 Fkill_process (img
->data
.lisp_val
, Qnil
);
9311 img
->data
.lisp_val
= Qnil
;
9313 /* On displays with a mutable colormap, figure out the colors
9314 allocated for the image by looking at the pixels of an XImage for
9316 class = FRAME_X_VISUAL (f
)->class;
9317 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9323 /* Try to get an XImage for img->pixmep. */
9324 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9325 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9330 /* Initialize the color table. */
9331 init_color_table ();
9333 /* For each pixel of the image, look its color up in the
9334 color table. After having done so, the color table will
9335 contain an entry for each color used by the image. */
9336 for (y
= 0; y
< img
->height
; ++y
)
9337 for (x
= 0; x
< img
->width
; ++x
)
9339 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9340 lookup_pixel_color (f
, pixel
);
9343 /* Record colors in the image. Free color table and XImage. */
9344 img
->colors
= colors_in_color_table (&img
->ncolors
);
9345 free_color_table ();
9346 XDestroyImage (ximg
);
9348 #if 0 /* This doesn't seem to be the case. If we free the colors
9349 here, we get a BadAccess later in x_clear_image when
9350 freeing the colors. */
9351 /* We have allocated colors once, but Ghostscript has also
9352 allocated colors on behalf of us. So, to get the
9353 reference counts right, free them once. */
9355 x_free_colors (f
, img
->colors
, img
->ncolors
);
9359 image_error ("Cannot get X image of `%s'; colors will not be freed",
9368 /***********************************************************************
9370 ***********************************************************************/
9372 DEFUN ("x-change-window-property", Fx_change_window_property
,
9373 Sx_change_window_property
, 2, 3, 0,
9374 "Change window property PROP to VALUE on the X window of FRAME.\n\
9375 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9376 selected frame. Value is VALUE.")
9377 (prop
, value
, frame
)
9378 Lisp_Object frame
, prop
, value
;
9380 struct frame
*f
= check_x_frame (frame
);
9383 CHECK_STRING (prop
, 1);
9384 CHECK_STRING (value
, 2);
9387 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9388 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9389 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9390 XSTRING (value
)->data
, XSTRING (value
)->size
);
9392 /* Make sure the property is set when we return. */
9393 XFlush (FRAME_X_DISPLAY (f
));
9400 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9401 Sx_delete_window_property
, 1, 2, 0,
9402 "Remove window property PROP from X window of FRAME.\n\
9403 FRAME nil or omitted means use the selected frame. Value is PROP.")
9405 Lisp_Object prop
, frame
;
9407 struct frame
*f
= check_x_frame (frame
);
9410 CHECK_STRING (prop
, 1);
9412 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9413 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9415 /* Make sure the property is removed when we return. */
9416 XFlush (FRAME_X_DISPLAY (f
));
9423 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9425 "Value is the value of window property PROP on FRAME.\n\
9426 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9427 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9430 Lisp_Object prop
, frame
;
9432 struct frame
*f
= check_x_frame (frame
);
9435 Lisp_Object prop_value
= Qnil
;
9436 char *tmp_data
= NULL
;
9439 unsigned long actual_size
, bytes_remaining
;
9441 CHECK_STRING (prop
, 1);
9443 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9444 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9445 prop_atom
, 0, 0, False
, XA_STRING
,
9446 &actual_type
, &actual_format
, &actual_size
,
9447 &bytes_remaining
, (unsigned char **) &tmp_data
);
9450 int size
= bytes_remaining
;
9455 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9456 prop_atom
, 0, bytes_remaining
,
9458 &actual_type
, &actual_format
,
9459 &actual_size
, &bytes_remaining
,
9460 (unsigned char **) &tmp_data
);
9462 prop_value
= make_string (tmp_data
, size
);
9473 /***********************************************************************
9475 ***********************************************************************/
9477 /* If non-null, an asynchronous timer that, when it expires, displays
9478 a busy cursor on all frames. */
9480 static struct atimer
*busy_cursor_atimer
;
9482 /* Non-zero means a busy cursor is currently shown. */
9484 static int busy_cursor_shown_p
;
9486 /* Number of seconds to wait before displaying a busy cursor. */
9488 static Lisp_Object Vbusy_cursor_delay
;
9490 /* Default number of seconds to wait before displaying a busy
9493 #define DEFAULT_BUSY_CURSOR_DELAY 1
9495 /* Function prototypes. */
9497 static void show_busy_cursor
P_ ((struct atimer
*));
9498 static void hide_busy_cursor
P_ ((void));
9501 /* Cancel a currently active busy-cursor timer, and start a new one. */
9504 start_busy_cursor ()
9507 int secs
, usecs
= 0;
9509 cancel_busy_cursor ();
9511 if (INTEGERP (Vbusy_cursor_delay
)
9512 && XINT (Vbusy_cursor_delay
) > 0)
9513 secs
= XFASTINT (Vbusy_cursor_delay
);
9514 else if (FLOATP (Vbusy_cursor_delay
)
9515 && XFLOAT_DATA (Vbusy_cursor_delay
) > 0)
9518 tem
= Ftruncate (Vbusy_cursor_delay
, Qnil
);
9519 secs
= XFASTINT (tem
);
9520 usecs
= (XFLOAT_DATA (Vbusy_cursor_delay
) - secs
) * 1000000;
9523 secs
= DEFAULT_BUSY_CURSOR_DELAY
;
9525 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
9526 busy_cursor_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
9527 show_busy_cursor
, NULL
);
9531 /* Cancel the busy cursor timer if active, hide a busy cursor if
9535 cancel_busy_cursor ()
9537 if (busy_cursor_atimer
)
9539 cancel_atimer (busy_cursor_atimer
);
9540 busy_cursor_atimer
= NULL
;
9543 if (busy_cursor_shown_p
)
9544 hide_busy_cursor ();
9548 /* Timer function of busy_cursor_atimer. TIMER is equal to
9551 Display a busy cursor on all frames by mapping the frames'
9552 busy_window. Set the busy_p flag in the frames' output_data.x
9553 structure to indicate that a busy cursor is shown on the
9557 show_busy_cursor (timer
)
9558 struct atimer
*timer
;
9560 /* The timer implementation will cancel this timer automatically
9561 after this function has run. Set busy_cursor_atimer to null
9562 so that we know the timer doesn't have to be canceled. */
9563 busy_cursor_atimer
= NULL
;
9565 if (!busy_cursor_shown_p
)
9567 Lisp_Object rest
, frame
;
9571 FOR_EACH_FRAME (rest
, frame
)
9572 if (FRAME_X_P (XFRAME (frame
)))
9574 struct frame
*f
= XFRAME (frame
);
9576 f
->output_data
.x
->busy_p
= 1;
9578 if (!f
->output_data
.x
->busy_window
)
9580 unsigned long mask
= CWCursor
;
9581 XSetWindowAttributes attrs
;
9583 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
9585 f
->output_data
.x
->busy_window
9586 = XCreateWindow (FRAME_X_DISPLAY (f
),
9587 FRAME_OUTER_WINDOW (f
),
9588 0, 0, 32000, 32000, 0, 0,
9594 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9595 XFlush (FRAME_X_DISPLAY (f
));
9598 busy_cursor_shown_p
= 1;
9604 /* Hide the busy cursor on all frames, if it is currently shown. */
9609 if (busy_cursor_shown_p
)
9611 Lisp_Object rest
, frame
;
9614 FOR_EACH_FRAME (rest
, frame
)
9616 struct frame
*f
= XFRAME (frame
);
9619 /* Watch out for newly created frames. */
9620 && f
->output_data
.x
->busy_window
)
9622 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
9623 /* Sync here because XTread_socket looks at the busy_p flag
9624 that is reset to zero below. */
9625 XSync (FRAME_X_DISPLAY (f
), False
);
9626 f
->output_data
.x
->busy_p
= 0;
9630 busy_cursor_shown_p
= 0;
9637 /***********************************************************************
9639 ***********************************************************************/
9641 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
9644 /* The frame of a currently visible tooltip, or null. */
9646 struct frame
*tip_frame
;
9648 /* If non-nil, a timer started that hides the last tooltip when it
9651 Lisp_Object tip_timer
;
9654 /* Create a frame for a tooltip on the display described by DPYINFO.
9655 PARMS is a list of frame parameters. Value is the frame. */
9658 x_create_tip_frame (dpyinfo
, parms
)
9659 struct x_display_info
*dpyinfo
;
9663 Lisp_Object frame
, tem
;
9665 long window_prompting
= 0;
9667 int count
= specpdl_ptr
- specpdl
;
9668 struct gcpro gcpro1
, gcpro2
, gcpro3
;
9673 /* Use this general default value to start with until we know if
9674 this frame has a specified name. */
9675 Vx_resource_name
= Vinvocation_name
;
9678 kb
= dpyinfo
->kboard
;
9680 kb
= &the_only_kboard
;
9683 /* Get the name of the frame to use for resource lookup. */
9684 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
9686 && !EQ (name
, Qunbound
)
9688 error ("Invalid frame name--not a string or nil");
9689 Vx_resource_name
= name
;
9692 GCPRO3 (parms
, name
, frame
);
9693 tip_frame
= f
= make_frame (1);
9694 XSETFRAME (frame
, f
);
9695 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
9697 f
->output_method
= output_x_window
;
9698 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
9699 bzero (f
->output_data
.x
, sizeof (struct x_output
));
9700 f
->output_data
.x
->icon_bitmap
= -1;
9701 f
->output_data
.x
->fontset
= -1;
9702 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
9703 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
9704 f
->icon_name
= Qnil
;
9705 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
9707 FRAME_KBOARD (f
) = kb
;
9709 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9710 f
->output_data
.x
->explicit_parent
= 0;
9712 /* These colors will be set anyway later, but it's important
9713 to get the color reference counts right, so initialize them! */
9716 struct gcpro gcpro1
;
9718 black
= build_string ("black");
9720 f
->output_data
.x
->foreground_pixel
9721 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9722 f
->output_data
.x
->background_pixel
9723 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9724 f
->output_data
.x
->cursor_pixel
9725 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9726 f
->output_data
.x
->cursor_foreground_pixel
9727 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9728 f
->output_data
.x
->border_pixel
9729 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9730 f
->output_data
.x
->mouse_pixel
9731 = x_decode_color (f
, black
, BLACK_PIX_DEFAULT (f
));
9735 /* Set the name; the functions to which we pass f expect the name to
9737 if (EQ (name
, Qunbound
) || NILP (name
))
9739 f
->name
= build_string (dpyinfo
->x_id_name
);
9740 f
->explicit_name
= 0;
9745 f
->explicit_name
= 1;
9746 /* use the frame's title when getting resources for this frame. */
9747 specbind (Qx_resource_name
, name
);
9750 /* Extract the window parameters from the supplied values
9751 that are needed to determine window geometry. */
9755 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
9758 /* First, try whatever font the caller has specified. */
9761 tem
= Fquery_fontset (font
, Qnil
);
9763 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
9765 font
= x_new_font (f
, XSTRING (font
)->data
);
9768 /* Try out a font which we hope has bold and italic variations. */
9769 if (!STRINGP (font
))
9770 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9771 if (!STRINGP (font
))
9772 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9773 if (! STRINGP (font
))
9774 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9775 if (! STRINGP (font
))
9776 /* This was formerly the first thing tried, but it finds too many fonts
9777 and takes too long. */
9778 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9779 /* If those didn't work, look for something which will at least work. */
9780 if (! STRINGP (font
))
9781 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9783 if (! STRINGP (font
))
9784 font
= build_string ("fixed");
9786 x_default_parameter (f
, parms
, Qfont
, font
,
9787 "font", "Font", RES_TYPE_STRING
);
9790 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
9791 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
9793 /* This defaults to 2 in order to match xterm. We recognize either
9794 internalBorderWidth or internalBorder (which is what xterm calls
9796 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9800 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
9801 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
9802 if (! EQ (value
, Qunbound
))
9803 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
9807 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
9808 "internalBorderWidth", "internalBorderWidth",
9811 /* Also do the stuff which must be set before the window exists. */
9812 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
9813 "foreground", "Foreground", RES_TYPE_STRING
);
9814 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
9815 "background", "Background", RES_TYPE_STRING
);
9816 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
9817 "pointerColor", "Foreground", RES_TYPE_STRING
);
9818 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
9819 "cursorColor", "Foreground", RES_TYPE_STRING
);
9820 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
9821 "borderColor", "BorderColor", RES_TYPE_STRING
);
9823 /* Init faces before x_default_parameter is called for scroll-bar
9824 parameters because that function calls x_set_scroll_bar_width,
9825 which calls change_frame_size, which calls Fset_window_buffer,
9826 which runs hooks, which call Fvertical_motion. At the end, we
9827 end up in init_iterator with a null face cache, which should not
9829 init_frame_faces (f
);
9831 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
9832 window_prompting
= x_figure_window_size (f
, parms
);
9834 if (window_prompting
& XNegative
)
9836 if (window_prompting
& YNegative
)
9837 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
9839 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
9843 if (window_prompting
& YNegative
)
9844 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
9846 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9849 f
->output_data
.x
->size_hint_flags
= window_prompting
;
9851 XSetWindowAttributes attrs
;
9855 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
9856 /* Window managers look at the override-redirect flag to determine
9857 whether or net to give windows a decoration (Xlib spec, chapter
9859 attrs
.override_redirect
= True
;
9860 attrs
.save_under
= True
;
9861 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
9862 /* Arrange for getting MapNotify and UnmapNotify events. */
9863 attrs
.event_mask
= StructureNotifyMask
;
9865 = FRAME_X_WINDOW (f
)
9866 = XCreateWindow (FRAME_X_DISPLAY (f
),
9867 FRAME_X_DISPLAY_INFO (f
)->root_window
,
9868 /* x, y, width, height */
9872 CopyFromParent
, InputOutput
, CopyFromParent
,
9879 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
9880 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9881 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
9882 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
9883 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
9884 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
9886 /* Dimensions, especially f->height, must be done via change_frame_size.
9887 Change will not be effected unless different from the current
9892 SET_FRAME_WIDTH (f
, 0);
9893 change_frame_size (f
, height
, width
, 1, 0, 0);
9899 /* It is now ok to make the frame official even if we get an error
9900 below. And the frame needs to be on Vframe_list or making it
9901 visible won't work. */
9902 Vframe_list
= Fcons (frame
, Vframe_list
);
9904 /* Now that the frame is official, it counts as a reference to
9906 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
9908 return unbind_to (count
, frame
);
9912 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
9913 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
9914 A tooltip window is a small X window displaying a string.\n\
9916 FRAME nil or omitted means use the selected frame.\n\
9918 PARMS is an optional list of frame parameters which can be\n\
9919 used to change the tooltip's appearance.\n\
9921 Automatically hide the tooltip after TIMEOUT seconds.\n\
9922 TIMEOUT nil means use the default timeout of 5 seconds.\n\
9924 If the list of frame parameters PARAMS contains a `left' parameters,\n\
9925 the tooltip is displayed at that x-position. Otherwise it is\n\
9926 displayed at the mouse position, with offset DX added (default is 5 if\n\
9927 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
9928 parameter is specified, it determines the y-position of the tooltip\n\
9929 window, otherwise it is displayed at the mouse position, with offset\n\
9930 DY added (default is -5).")
9931 (string
, frame
, parms
, timeout
, dx
, dy
)
9932 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
9937 Lisp_Object buffer
, top
, left
;
9938 struct buffer
*old_buffer
;
9939 struct text_pos pos
;
9940 int i
, width
, height
;
9941 int root_x
, root_y
, win_x
, win_y
;
9943 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
9944 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
9945 int count
= specpdl_ptr
- specpdl
;
9947 specbind (Qinhibit_redisplay
, Qt
);
9949 GCPRO4 (string
, parms
, frame
, timeout
);
9951 CHECK_STRING (string
, 0);
9952 f
= check_x_frame (frame
);
9954 timeout
= make_number (5);
9956 CHECK_NATNUM (timeout
, 2);
9959 dx
= make_number (5);
9961 CHECK_NUMBER (dx
, 5);
9964 dy
= make_number (-5);
9966 CHECK_NUMBER (dy
, 6);
9968 /* Hide a previous tip, if any. */
9971 /* Add default values to frame parameters. */
9972 if (NILP (Fassq (Qname
, parms
)))
9973 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
9974 if (NILP (Fassq (Qinternal_border_width
, parms
)))
9975 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
9976 if (NILP (Fassq (Qborder_width
, parms
)))
9977 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
9978 if (NILP (Fassq (Qborder_color
, parms
)))
9979 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
9980 if (NILP (Fassq (Qbackground_color
, parms
)))
9981 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
9984 /* Create a frame for the tooltip, and record it in the global
9985 variable tip_frame. */
9986 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
9987 tip_frame
= f
= XFRAME (frame
);
9989 /* Set up the frame's root window. Currently we use a size of 80
9990 columns x 40 lines. If someone wants to show a larger tip, he
9991 will loose. I don't think this is a realistic case. */
9992 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
9993 w
->left
= w
->top
= make_number (0);
9994 w
->width
= make_number (80);
9995 w
->height
= make_number (40);
9997 w
->pseudo_window_p
= 1;
9999 /* Display the tooltip text in a temporary buffer. */
10000 buffer
= Fget_buffer_create (build_string (" *tip*"));
10001 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10002 old_buffer
= current_buffer
;
10003 set_buffer_internal_1 (XBUFFER (buffer
));
10005 Finsert (1, &string
);
10006 clear_glyph_matrix (w
->desired_matrix
);
10007 clear_glyph_matrix (w
->current_matrix
);
10008 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
10009 try_window (FRAME_ROOT_WINDOW (f
), pos
);
10011 /* Compute width and height of the tooltip. */
10012 width
= height
= 0;
10013 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
10015 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
10016 struct glyph
*last
;
10019 /* Stop at the first empty row at the end. */
10020 if (!row
->enabled_p
|| !row
->displays_text_p
)
10023 /* Let the row go over the full width of the frame. */
10024 row
->full_width_p
= 1;
10026 /* There's a glyph at the end of rows that is used to place
10027 the cursor there. Don't include the width of this glyph. */
10028 if (row
->used
[TEXT_AREA
])
10030 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
10031 row_width
= row
->pixel_width
- last
->pixel_width
;
10034 row_width
= row
->pixel_width
;
10036 height
+= row
->height
;
10037 width
= max (width
, row_width
);
10040 /* Add the frame's internal border to the width and height the X
10041 window should have. */
10042 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10043 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10045 /* User-specified position? */
10046 left
= Fcdr (Fassq (Qleft
, parms
));
10047 top
= Fcdr (Fassq (Qtop
, parms
));
10049 /* Move the tooltip window where the mouse pointer is. Resize and
10052 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10053 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
10056 root_x
+= XINT (dx
);
10057 root_y
+= XINT (dy
);
10059 if (INTEGERP (left
))
10060 root_x
= XINT (left
);
10061 if (INTEGERP (top
))
10062 root_y
= XINT (top
);
10065 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10066 root_x
, root_y
- height
, width
, height
);
10067 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10070 /* Draw into the window. */
10071 w
->must_be_updated_p
= 1;
10072 update_single_window (w
, 1);
10074 /* Restore original current buffer. */
10075 set_buffer_internal_1 (old_buffer
);
10076 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
10078 /* Let the tip disappear after timeout seconds. */
10079 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
10080 intern ("x-hide-tip"));
10083 return unbind_to (count
, Qnil
);
10087 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
10088 "Hide the current tooltip window, if there is any.\n\
10089 Value is t is tooltip was open, nil otherwise.")
10092 int count
= specpdl_ptr
- specpdl
;
10095 specbind (Qinhibit_redisplay
, Qt
);
10097 if (!NILP (tip_timer
))
10099 call1 (intern ("cancel-timer"), tip_timer
);
10107 XSETFRAME (frame
, tip_frame
);
10108 Fdelete_frame (frame
, Qt
);
10113 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
10118 /***********************************************************************
10119 File selection dialog
10120 ***********************************************************************/
10124 /* Callback for "OK" and "Cancel" on file selection dialog. */
10127 file_dialog_cb (widget
, client_data
, call_data
)
10129 XtPointer call_data
, client_data
;
10131 int *result
= (int *) client_data
;
10132 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
10133 *result
= cb
->reason
;
10137 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
10138 "Read file name, prompting with PROMPT in directory DIR.\n\
10139 Use a file selection dialog.\n\
10140 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10141 specified. Don't let the user enter a file name in the file\n\
10142 selection dialog's entry field, if MUSTMATCH is non-nil.")
10143 (prompt
, dir
, default_filename
, mustmatch
)
10144 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
10147 struct frame
*f
= SELECTED_FRAME ();
10148 Lisp_Object file
= Qnil
;
10149 Widget dialog
, text
, list
, help
;
10152 extern XtAppContext Xt_app_con
;
10154 XmString dir_xmstring
, pattern_xmstring
;
10155 int popup_activated_flag
;
10156 int count
= specpdl_ptr
- specpdl
;
10157 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
10159 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
10160 CHECK_STRING (prompt
, 0);
10161 CHECK_STRING (dir
, 1);
10163 /* Prevent redisplay. */
10164 specbind (Qinhibit_redisplay
, Qt
);
10168 /* Create the dialog with PROMPT as title, using DIR as initial
10169 directory and using "*" as pattern. */
10170 dir
= Fexpand_file_name (dir
, Qnil
);
10171 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
10172 pattern_xmstring
= XmStringCreateLocalized ("*");
10174 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
10175 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
10176 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
10177 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
10178 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
10179 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
10181 XmStringFree (dir_xmstring
);
10182 XmStringFree (pattern_xmstring
);
10184 /* Add callbacks for OK and Cancel. */
10185 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
10186 (XtPointer
) &result
);
10187 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
10188 (XtPointer
) &result
);
10190 /* Disable the help button since we can't display help. */
10191 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
10192 XtSetSensitive (help
, False
);
10194 /* Mark OK button as default. */
10195 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
10196 XmNshowAsDefault
, True
, NULL
);
10198 /* If MUSTMATCH is non-nil, disable the file entry field of the
10199 dialog, so that the user must select a file from the files list
10200 box. We can't remove it because we wouldn't have a way to get at
10201 the result file name, then. */
10202 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
10203 if (!NILP (mustmatch
))
10206 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
10207 XtSetSensitive (text
, False
);
10208 XtSetSensitive (label
, False
);
10211 /* Manage the dialog, so that list boxes get filled. */
10212 XtManageChild (dialog
);
10214 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10215 must include the path for this to work. */
10216 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
10217 if (STRINGP (default_filename
))
10219 XmString default_xmstring
;
10223 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
10225 if (!XmListItemExists (list
, default_xmstring
))
10227 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10228 XmListAddItem (list
, default_xmstring
, 0);
10232 item_pos
= XmListItemPos (list
, default_xmstring
);
10233 XmStringFree (default_xmstring
);
10235 /* Select the item and scroll it into view. */
10236 XmListSelectPos (list
, item_pos
, True
);
10237 XmListSetPos (list
, item_pos
);
10240 #ifdef HAVE_MOTIF_2_1
10242 /* Process events until the user presses Cancel or OK. */
10244 while (result
== 0 || XtAppPending (Xt_app_con
))
10245 XtAppProcessEvent (Xt_app_con
, XtIMAll
);
10247 #else /* not HAVE_MOTIF_2_1 */
10249 /* Process all events until the user presses Cancel or OK. */
10250 for (result
= 0; result
== 0;)
10253 Widget widget
, parent
;
10255 XtAppNextEvent (Xt_app_con
, &event
);
10257 /* See if the receiver of the event is one of the widgets of
10258 the file selection dialog. If so, dispatch it. If not,
10260 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
10262 while (parent
&& parent
!= dialog
)
10263 parent
= XtParent (parent
);
10265 if (parent
== dialog
10266 || (event
.type
== Expose
10267 && !process_expose_from_menu (event
)))
10268 XtDispatchEvent (&event
);
10271 #endif /* not HAVE_MOTIF_2_1 */
10273 /* Get the result. */
10274 if (result
== XmCR_OK
)
10279 XtVaGetValues (dialog
, XmNtextString
, &text
, NULL
);
10280 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
10281 XmStringFree (text
);
10282 file
= build_string (data
);
10289 XtUnmanageChild (dialog
);
10290 XtDestroyWidget (dialog
);
10294 /* Make "Cancel" equivalent to C-g. */
10296 Fsignal (Qquit
, Qnil
);
10298 return unbind_to (count
, file
);
10301 #endif /* USE_MOTIF */
10305 /***********************************************************************
10307 ***********************************************************************/
10312 /* This is zero if not using X windows. */
10315 /* The section below is built by the lisp expression at the top of the file,
10316 just above where these variables are declared. */
10317 /*&&& init symbols here &&&*/
10318 Qauto_raise
= intern ("auto-raise");
10319 staticpro (&Qauto_raise
);
10320 Qauto_lower
= intern ("auto-lower");
10321 staticpro (&Qauto_lower
);
10322 Qbar
= intern ("bar");
10324 Qborder_color
= intern ("border-color");
10325 staticpro (&Qborder_color
);
10326 Qborder_width
= intern ("border-width");
10327 staticpro (&Qborder_width
);
10328 Qbox
= intern ("box");
10330 Qcursor_color
= intern ("cursor-color");
10331 staticpro (&Qcursor_color
);
10332 Qcursor_type
= intern ("cursor-type");
10333 staticpro (&Qcursor_type
);
10334 Qgeometry
= intern ("geometry");
10335 staticpro (&Qgeometry
);
10336 Qicon_left
= intern ("icon-left");
10337 staticpro (&Qicon_left
);
10338 Qicon_top
= intern ("icon-top");
10339 staticpro (&Qicon_top
);
10340 Qicon_type
= intern ("icon-type");
10341 staticpro (&Qicon_type
);
10342 Qicon_name
= intern ("icon-name");
10343 staticpro (&Qicon_name
);
10344 Qinternal_border_width
= intern ("internal-border-width");
10345 staticpro (&Qinternal_border_width
);
10346 Qleft
= intern ("left");
10347 staticpro (&Qleft
);
10348 Qright
= intern ("right");
10349 staticpro (&Qright
);
10350 Qmouse_color
= intern ("mouse-color");
10351 staticpro (&Qmouse_color
);
10352 Qnone
= intern ("none");
10353 staticpro (&Qnone
);
10354 Qparent_id
= intern ("parent-id");
10355 staticpro (&Qparent_id
);
10356 Qscroll_bar_width
= intern ("scroll-bar-width");
10357 staticpro (&Qscroll_bar_width
);
10358 Qsuppress_icon
= intern ("suppress-icon");
10359 staticpro (&Qsuppress_icon
);
10360 Qundefined_color
= intern ("undefined-color");
10361 staticpro (&Qundefined_color
);
10362 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10363 staticpro (&Qvertical_scroll_bars
);
10364 Qvisibility
= intern ("visibility");
10365 staticpro (&Qvisibility
);
10366 Qwindow_id
= intern ("window-id");
10367 staticpro (&Qwindow_id
);
10368 Qouter_window_id
= intern ("outer-window-id");
10369 staticpro (&Qouter_window_id
);
10370 Qx_frame_parameter
= intern ("x-frame-parameter");
10371 staticpro (&Qx_frame_parameter
);
10372 Qx_resource_name
= intern ("x-resource-name");
10373 staticpro (&Qx_resource_name
);
10374 Quser_position
= intern ("user-position");
10375 staticpro (&Quser_position
);
10376 Quser_size
= intern ("user-size");
10377 staticpro (&Quser_size
);
10378 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10379 staticpro (&Qscroll_bar_foreground
);
10380 Qscroll_bar_background
= intern ("scroll-bar-background");
10381 staticpro (&Qscroll_bar_background
);
10382 Qscreen_gamma
= intern ("screen-gamma");
10383 staticpro (&Qscreen_gamma
);
10384 Qline_spacing
= intern ("line-spacing");
10385 staticpro (&Qline_spacing
);
10386 Qcenter
= intern ("center");
10387 staticpro (&Qcenter
);
10388 Qcompound_text
= intern ("compound-text");
10389 staticpro (&Qcompound_text
);
10390 /* This is the end of symbol initialization. */
10392 /* Text property `display' should be nonsticky by default. */
10393 Vtext_property_default_nonsticky
10394 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
10397 Qlaplace
= intern ("laplace");
10398 staticpro (&Qlaplace
);
10400 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10401 staticpro (&Qface_set_after_frame_default
);
10403 Fput (Qundefined_color
, Qerror_conditions
,
10404 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10405 Fput (Qundefined_color
, Qerror_message
,
10406 build_string ("Undefined color"));
10408 init_x_parm_symbols ();
10410 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10411 "List of directories to search for bitmap files for X.");
10412 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
10414 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10415 "The shape of the pointer when over text.\n\
10416 Changing the value does not affect existing frames\n\
10417 unless you set the mouse color.");
10418 Vx_pointer_shape
= Qnil
;
10420 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
10421 "The name Emacs uses to look up X resources.\n\
10422 `x-get-resource' uses this as the first component of the instance name\n\
10423 when requesting resource values.\n\
10424 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10425 was invoked, or to the value specified with the `-name' or `-rn'\n\
10426 switches, if present.\n\
10428 It may be useful to bind this variable locally around a call\n\
10429 to `x-get-resource'. See also the variable `x-resource-class'.");
10430 Vx_resource_name
= Qnil
;
10432 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
10433 "The class Emacs uses to look up X resources.\n\
10434 `x-get-resource' uses this as the first component of the instance class\n\
10435 when requesting resource values.\n\
10436 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10438 Setting this variable permanently is not a reasonable thing to do,\n\
10439 but binding this variable locally around a call to `x-get-resource'\n\
10440 is a reasonable practice. See also the variable `x-resource-name'.");
10441 Vx_resource_class
= build_string (EMACS_CLASS
);
10443 #if 0 /* This doesn't really do anything. */
10444 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
10445 "The shape of the pointer when not over text.\n\
10446 This variable takes effect when you create a new frame\n\
10447 or when you set the mouse color.");
10449 Vx_nontext_pointer_shape
= Qnil
;
10451 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
10452 "The shape of the pointer when Emacs is busy.\n\
10453 This variable takes effect when you create a new frame\n\
10454 or when you set the mouse color.");
10455 Vx_busy_pointer_shape
= Qnil
;
10457 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
10458 "Non-zero means Emacs displays a busy cursor on window systems.");
10459 display_busy_cursor_p
= 1;
10461 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay
,
10462 "*Seconds to wait before displaying a busy-cursor.\n\
10463 Value must be an integer or float.");
10464 Vbusy_cursor_delay
= make_number (DEFAULT_BUSY_CURSOR_DELAY
);
10466 #if 0 /* This doesn't really do anything. */
10467 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
10468 "The shape of the pointer when over the mode line.\n\
10469 This variable takes effect when you create a new frame\n\
10470 or when you set the mouse color.");
10472 Vx_mode_pointer_shape
= Qnil
;
10474 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10475 &Vx_sensitive_text_pointer_shape
,
10476 "The shape of the pointer when over mouse-sensitive text.\n\
10477 This variable takes effect when you create a new frame\n\
10478 or when you set the mouse color.");
10479 Vx_sensitive_text_pointer_shape
= Qnil
;
10481 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
10482 "A string indicating the foreground color of the cursor box.");
10483 Vx_cursor_fore_pixel
= Qnil
;
10485 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
10486 "Non-nil if no X window manager is in use.\n\
10487 Emacs doesn't try to figure this out; this is always nil\n\
10488 unless you set it to something else.");
10489 /* We don't have any way to find this out, so set it to nil
10490 and maybe the user would like to set it to t. */
10491 Vx_no_window_manager
= Qnil
;
10493 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10494 &Vx_pixel_size_width_font_regexp
,
10495 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10497 Since Emacs gets width of a font matching with this regexp from\n\
10498 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10499 such a font. This is especially effective for such large fonts as\n\
10500 Chinese, Japanese, and Korean.");
10501 Vx_pixel_size_width_font_regexp
= Qnil
;
10503 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
10504 "Time after which cached images are removed from the cache.\n\
10505 When an image has not been displayed this many seconds, remove it\n\
10506 from the image cache. Value must be an integer or nil with nil\n\
10507 meaning don't clear the cache.");
10508 Vimage_cache_eviction_delay
= make_number (30 * 60);
10510 #ifdef USE_X_TOOLKIT
10511 Fprovide (intern ("x-toolkit"));
10514 Fprovide (intern ("motif"));
10517 defsubr (&Sx_get_resource
);
10519 /* X window properties. */
10520 defsubr (&Sx_change_window_property
);
10521 defsubr (&Sx_delete_window_property
);
10522 defsubr (&Sx_window_property
);
10524 defsubr (&Sxw_display_color_p
);
10525 defsubr (&Sx_display_grayscale_p
);
10526 defsubr (&Sxw_color_defined_p
);
10527 defsubr (&Sxw_color_values
);
10528 defsubr (&Sx_server_max_request_size
);
10529 defsubr (&Sx_server_vendor
);
10530 defsubr (&Sx_server_version
);
10531 defsubr (&Sx_display_pixel_width
);
10532 defsubr (&Sx_display_pixel_height
);
10533 defsubr (&Sx_display_mm_width
);
10534 defsubr (&Sx_display_mm_height
);
10535 defsubr (&Sx_display_screens
);
10536 defsubr (&Sx_display_planes
);
10537 defsubr (&Sx_display_color_cells
);
10538 defsubr (&Sx_display_visual_class
);
10539 defsubr (&Sx_display_backing_store
);
10540 defsubr (&Sx_display_save_under
);
10541 defsubr (&Sx_parse_geometry
);
10542 defsubr (&Sx_create_frame
);
10543 defsubr (&Sx_open_connection
);
10544 defsubr (&Sx_close_connection
);
10545 defsubr (&Sx_display_list
);
10546 defsubr (&Sx_synchronize
);
10547 defsubr (&Sx_focus_frame
);
10549 /* Setting callback functions for fontset handler. */
10550 get_font_info_func
= x_get_font_info
;
10552 #if 0 /* This function pointer doesn't seem to be used anywhere.
10553 And the pointer assigned has the wrong type, anyway. */
10554 list_fonts_func
= x_list_fonts
;
10557 load_font_func
= x_load_font
;
10558 find_ccl_program_func
= x_find_ccl_program
;
10559 query_font_func
= x_query_font
;
10560 set_frame_fontset_func
= x_set_font
;
10561 check_window_system_func
= check_x
;
10564 Qxbm
= intern ("xbm");
10566 QCtype
= intern (":type");
10567 staticpro (&QCtype
);
10568 QCalgorithm
= intern (":algorithm");
10569 staticpro (&QCalgorithm
);
10570 QCheuristic_mask
= intern (":heuristic-mask");
10571 staticpro (&QCheuristic_mask
);
10572 QCcolor_symbols
= intern (":color-symbols");
10573 staticpro (&QCcolor_symbols
);
10574 QCascent
= intern (":ascent");
10575 staticpro (&QCascent
);
10576 QCmargin
= intern (":margin");
10577 staticpro (&QCmargin
);
10578 QCrelief
= intern (":relief");
10579 staticpro (&QCrelief
);
10580 Qpostscript
= intern ("postscript");
10581 staticpro (&Qpostscript
);
10582 QCloader
= intern (":loader");
10583 staticpro (&QCloader
);
10584 QCbounding_box
= intern (":bounding-box");
10585 staticpro (&QCbounding_box
);
10586 QCpt_width
= intern (":pt-width");
10587 staticpro (&QCpt_width
);
10588 QCpt_height
= intern (":pt-height");
10589 staticpro (&QCpt_height
);
10590 QCindex
= intern (":index");
10591 staticpro (&QCindex
);
10592 Qpbm
= intern ("pbm");
10596 Qxpm
= intern ("xpm");
10601 Qjpeg
= intern ("jpeg");
10602 staticpro (&Qjpeg
);
10606 Qtiff
= intern ("tiff");
10607 staticpro (&Qtiff
);
10611 Qgif
= intern ("gif");
10616 Qpng
= intern ("png");
10620 defsubr (&Sclear_image_cache
);
10621 defsubr (&Simage_size
);
10623 busy_cursor_atimer
= NULL
;
10624 busy_cursor_shown_p
= 0;
10626 defsubr (&Sx_show_tip
);
10627 defsubr (&Sx_hide_tip
);
10628 staticpro (&tip_timer
);
10632 defsubr (&Sx_file_dialog
);
10640 image_types
= NULL
;
10641 Vimage_types
= Qnil
;
10643 define_image_type (&xbm_type
);
10644 define_image_type (&gs_type
);
10645 define_image_type (&pbm_type
);
10648 define_image_type (&xpm_type
);
10652 define_image_type (&jpeg_type
);
10656 define_image_type (&tiff_type
);
10660 define_image_type (&gif_type
);
10664 define_image_type (&png_type
);
10668 #endif /* HAVE_X_WINDOWS */