1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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"
44 #include "termhooks.h"
49 #include <sys/types.h>
52 /* On some systems, the character-composition stuff is broken in X11R5. */
54 #if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
55 #ifdef X11R5_INHIBIT_I18N
56 #define X_I18N_INHIBITED
61 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
62 #include "bitmaps/gray.xbm"
64 #include <X11/bitmaps/gray>
67 #include "[.bitmaps]gray.xbm"
71 #include <X11/Shell.h>
74 #include <X11/Xaw/Paned.h>
75 #include <X11/Xaw/Label.h>
76 #endif /* USE_MOTIF */
79 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
88 #include "../lwlib/lwlib.h"
92 #include <Xm/DialogS.h>
93 #include <Xm/FileSB.h>
96 /* Do the EDITRES protocol if running X11R5
97 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
99 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
101 extern void _XEditResCheckMessages ();
102 #endif /* R5 + Athena */
104 /* Unique id counter for widgets created by the Lucid Widget Library. */
106 extern LWLIB_ID widget_id_tick
;
109 /* This is part of a kludge--see lwlib/xlwmenu.c. */
110 extern XFontStruct
*xlwmenu_default_font
;
113 extern void free_frame_menubar ();
114 extern double atof ();
116 #endif /* USE_X_TOOLKIT */
118 #define min(a,b) ((a) < (b) ? (a) : (b))
119 #define max(a,b) ((a) > (b) ? (a) : (b))
122 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
124 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
127 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
128 it, and including `bitmaps/gray' more than once is a problem when
129 config.h defines `static' as an empty replacement string. */
131 int gray_bitmap_width
= gray_width
;
132 int gray_bitmap_height
= gray_height
;
133 unsigned char *gray_bitmap_bits
= gray_bits
;
135 /* The name we're using in resource queries. Most often "emacs". */
137 Lisp_Object Vx_resource_name
;
139 /* The application class we're using in resource queries.
142 Lisp_Object Vx_resource_class
;
144 /* Non-zero means we're allowed to display a busy cursor. */
146 int display_busy_cursor_p
;
148 /* The background and shape of the mouse pointer, and shape when not
149 over text or in the modeline. */
151 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
152 Lisp_Object Vx_busy_pointer_shape
;
154 /* The shape when over mouse-sensitive text. */
156 Lisp_Object Vx_sensitive_text_pointer_shape
;
158 /* Color of chars displayed in cursor box. */
160 Lisp_Object Vx_cursor_fore_pixel
;
162 /* Nonzero if using X. */
166 /* Non nil if no window manager is in use. */
168 Lisp_Object Vx_no_window_manager
;
170 /* Search path for bitmap files. */
172 Lisp_Object Vx_bitmap_file_path
;
174 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
176 Lisp_Object Vx_pixel_size_width_font_regexp
;
178 /* Evaluate this expression to rebuild the section of syms_of_xfns
179 that initializes and staticpros the symbols declared below. Note
180 that Emacs 18 has a bug that keeps C-x C-e from being able to
181 evaluate this expression.
184 ;; Accumulate a list of the symbols we want to initialize from the
185 ;; declarations at the top of the file.
186 (goto-char (point-min))
187 (search-forward "/\*&&& symbols declared here &&&*\/\n")
189 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
191 (cons (buffer-substring (match-beginning 1) (match-end 1))
194 (setq symbol-list (nreverse symbol-list))
195 ;; Delete the section of syms_of_... where we initialize the symbols.
196 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
197 (let ((start (point)))
198 (while (looking-at "^ Q")
200 (kill-region start (point)))
201 ;; Write a new symbol initialization section.
203 (insert (format " %s = intern (\"" (car symbol-list)))
204 (let ((start (point)))
205 (insert (substring (car symbol-list) 1))
206 (subst-char-in-region start (point) ?_ ?-))
207 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
208 (setq symbol-list (cdr symbol-list)))))
212 /*&&& symbols declared here &&&*/
213 Lisp_Object Qauto_raise
;
214 Lisp_Object Qauto_lower
;
216 Lisp_Object Qborder_color
;
217 Lisp_Object Qborder_width
;
219 Lisp_Object Qcursor_color
;
220 Lisp_Object Qcursor_type
;
221 Lisp_Object Qgeometry
;
222 Lisp_Object Qicon_left
;
223 Lisp_Object Qicon_top
;
224 Lisp_Object Qicon_type
;
225 Lisp_Object Qicon_name
;
226 Lisp_Object Qinternal_border_width
;
229 Lisp_Object Qmouse_color
;
231 Lisp_Object Qouter_window_id
;
232 Lisp_Object Qparent_id
;
233 Lisp_Object Qscroll_bar_width
;
234 Lisp_Object Qsuppress_icon
;
235 extern Lisp_Object Qtop
;
236 Lisp_Object Qundefined_color
;
237 Lisp_Object Qvertical_scroll_bars
;
238 Lisp_Object Qvisibility
;
239 Lisp_Object Qwindow_id
;
240 Lisp_Object Qx_frame_parameter
;
241 Lisp_Object Qx_resource_name
;
242 Lisp_Object Quser_position
;
243 Lisp_Object Quser_size
;
244 extern Lisp_Object Qdisplay
;
245 Lisp_Object Qscroll_bar_foreground
, Qscroll_bar_background
;
246 Lisp_Object Qscreen_gamma
;
248 /* The below are defined in frame.c. */
250 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
251 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
252 extern Lisp_Object Qtool_bar_lines
;
254 extern Lisp_Object Vwindow_system_version
;
256 Lisp_Object Qface_set_after_frame_default
;
259 /* Error if we are not connected to X. */
265 error ("X windows are not in use or not initialized");
268 /* Nonzero if we can use mouse menus.
269 You should not call this unless HAVE_MENUS is defined. */
277 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
278 and checking validity for X. */
281 check_x_frame (frame
)
287 frame
= selected_frame
;
288 CHECK_LIVE_FRAME (frame
, 0);
291 error ("Non-X frame used");
295 /* Let the user specify an X display with a frame.
296 nil stands for the selected frame--or, if that is not an X frame,
297 the first X display on the list. */
299 static struct x_display_info
*
300 check_x_display_info (frame
)
305 struct frame
*sf
= XFRAME (selected_frame
);
307 if (FRAME_X_P (sf
) && FRAME_LIVE_P (sf
))
308 return FRAME_X_DISPLAY_INFO (sf
);
309 else if (x_display_list
!= 0)
310 return x_display_list
;
312 error ("X windows are not in use or not initialized");
314 else if (STRINGP (frame
))
315 return x_display_info_for_name (frame
);
320 CHECK_LIVE_FRAME (frame
, 0);
323 error ("Non-X frame used");
324 return FRAME_X_DISPLAY_INFO (f
);
329 /* Return the Emacs frame-object corresponding to an X window.
330 It could be the frame's main window or an icon window. */
332 /* This function can be called during GC, so use GC_xxx type test macros. */
335 x_window_to_frame (dpyinfo
, wdesc
)
336 struct x_display_info
*dpyinfo
;
339 Lisp_Object tail
, frame
;
342 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
345 if (!GC_FRAMEP (frame
))
348 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
351 if ((f
->output_data
.x
->edit_widget
352 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
353 /* A tooltip frame? */
354 || (!f
->output_data
.x
->edit_widget
355 && FRAME_X_WINDOW (f
) == wdesc
)
356 || f
->output_data
.x
->icon_desc
== wdesc
)
358 #else /* not USE_X_TOOLKIT */
359 if (FRAME_X_WINDOW (f
) == wdesc
360 || f
->output_data
.x
->icon_desc
== wdesc
)
362 #endif /* not USE_X_TOOLKIT */
368 /* Like x_window_to_frame but also compares the window with the widget's
372 x_any_window_to_frame (dpyinfo
, wdesc
)
373 struct x_display_info
*dpyinfo
;
376 Lisp_Object tail
, frame
;
380 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
383 if (!GC_FRAMEP (frame
))
386 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
388 x
= f
->output_data
.x
;
389 /* This frame matches if the window is any of its widgets. */
392 if (wdesc
== XtWindow (x
->widget
)
393 || wdesc
== XtWindow (x
->column_widget
)
394 || wdesc
== XtWindow (x
->edit_widget
))
396 /* Match if the window is this frame's menubar. */
397 if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
400 else if (FRAME_X_WINDOW (f
) == wdesc
)
401 /* A tooltip frame. */
407 /* Likewise, but exclude the menu bar widget. */
410 x_non_menubar_window_to_frame (dpyinfo
, wdesc
)
411 struct x_display_info
*dpyinfo
;
414 Lisp_Object tail
, frame
;
418 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
421 if (!GC_FRAMEP (frame
))
424 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
426 x
= f
->output_data
.x
;
427 /* This frame matches if the window is any of its widgets. */
430 if (wdesc
== XtWindow (x
->widget
)
431 || wdesc
== XtWindow (x
->column_widget
)
432 || wdesc
== XtWindow (x
->edit_widget
))
435 else if (FRAME_X_WINDOW (f
) == wdesc
)
436 /* A tooltip frame. */
442 /* Likewise, but consider only the menu bar widget. */
445 x_menubar_window_to_frame (dpyinfo
, wdesc
)
446 struct x_display_info
*dpyinfo
;
449 Lisp_Object tail
, frame
;
453 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
456 if (!GC_FRAMEP (frame
))
459 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
461 x
= f
->output_data
.x
;
462 /* Match if the window is this frame's menubar. */
463 if (x
->menubar_widget
464 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
470 /* Return the frame whose principal (outermost) window is WDESC.
471 If WDESC is some other (smaller) window, we return 0. */
474 x_top_window_to_frame (dpyinfo
, wdesc
)
475 struct x_display_info
*dpyinfo
;
478 Lisp_Object tail
, frame
;
482 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
485 if (!GC_FRAMEP (frame
))
488 if (!FRAME_X_P (f
) || FRAME_X_DISPLAY_INFO (f
) != dpyinfo
)
490 x
= f
->output_data
.x
;
494 /* This frame matches if the window is its topmost widget. */
495 if (wdesc
== XtWindow (x
->widget
))
497 #if 0 /* I don't know why it did this,
498 but it seems logically wrong,
499 and it causes trouble for MapNotify events. */
500 /* Match if the window is this frame's menubar. */
501 if (x
->menubar_widget
502 && wdesc
== XtWindow (x
->menubar_widget
))
506 else if (FRAME_X_WINDOW (f
) == wdesc
)
512 #endif /* USE_X_TOOLKIT */
516 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
517 id, which is just an int that this section returns. Bitmaps are
518 reference counted so they can be shared among frames.
520 Bitmap indices are guaranteed to be > 0, so a negative number can
521 be used to indicate no bitmap.
523 If you use x_create_bitmap_from_data, then you must keep track of
524 the bitmaps yourself. That is, creating a bitmap from the same
525 data more than once will not be caught. */
528 /* Functions to access the contents of a bitmap, given an id. */
531 x_bitmap_height (f
, id
)
535 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
539 x_bitmap_width (f
, id
)
543 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
547 x_bitmap_pixmap (f
, id
)
551 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
555 /* Allocate a new bitmap record. Returns index of new record. */
558 x_allocate_bitmap_record (f
)
561 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
564 if (dpyinfo
->bitmaps
== NULL
)
566 dpyinfo
->bitmaps_size
= 10;
568 = (struct x_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
569 dpyinfo
->bitmaps_last
= 1;
573 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
574 return ++dpyinfo
->bitmaps_last
;
576 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
577 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
580 dpyinfo
->bitmaps_size
*= 2;
582 = (struct x_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
583 dpyinfo
->bitmaps_size
* sizeof (struct x_bitmap_record
));
584 return ++dpyinfo
->bitmaps_last
;
587 /* Add one reference to the reference count of the bitmap with id ID. */
590 x_reference_bitmap (f
, id
)
594 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
597 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
600 x_create_bitmap_from_data (f
, bits
, width
, height
)
603 unsigned int width
, height
;
605 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
609 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
610 bits
, width
, height
);
615 id
= x_allocate_bitmap_record (f
);
616 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
617 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
618 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
619 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
620 dpyinfo
->bitmaps
[id
- 1].height
= height
;
621 dpyinfo
->bitmaps
[id
- 1].width
= width
;
626 /* Create bitmap from file FILE for frame F. */
629 x_create_bitmap_from_file (f
, file
)
633 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
634 unsigned int width
, height
;
636 int xhot
, yhot
, result
, id
;
641 /* Look for an existing bitmap with the same name. */
642 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
644 if (dpyinfo
->bitmaps
[id
].refcount
645 && dpyinfo
->bitmaps
[id
].file
646 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
648 ++dpyinfo
->bitmaps
[id
].refcount
;
653 /* Search bitmap-file-path for the file, if appropriate. */
654 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
657 /* XReadBitmapFile won't handle magic file names. */
662 filename
= (char *) XSTRING (found
)->data
;
664 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
665 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
666 if (result
!= BitmapSuccess
)
669 id
= x_allocate_bitmap_record (f
);
670 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
671 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
672 dpyinfo
->bitmaps
[id
- 1].file
673 = (char *) xmalloc (STRING_BYTES (XSTRING (file
)) + 1);
674 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
675 dpyinfo
->bitmaps
[id
- 1].height
= height
;
676 dpyinfo
->bitmaps
[id
- 1].width
= width
;
677 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
682 /* Remove reference to bitmap with id number ID. */
685 x_destroy_bitmap (f
, id
)
689 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
693 --dpyinfo
->bitmaps
[id
- 1].refcount
;
694 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
697 XFreePixmap (FRAME_X_DISPLAY (f
), dpyinfo
->bitmaps
[id
- 1].pixmap
);
698 if (dpyinfo
->bitmaps
[id
- 1].file
)
700 xfree (dpyinfo
->bitmaps
[id
- 1].file
);
701 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
708 /* Free all the bitmaps for the display specified by DPYINFO. */
711 x_destroy_all_bitmaps (dpyinfo
)
712 struct x_display_info
*dpyinfo
;
715 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
716 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
718 XFreePixmap (dpyinfo
->display
, dpyinfo
->bitmaps
[i
].pixmap
);
719 if (dpyinfo
->bitmaps
[i
].file
)
720 xfree (dpyinfo
->bitmaps
[i
].file
);
722 dpyinfo
->bitmaps_last
= 0;
725 /* Connect the frame-parameter names for X frames
726 to the ways of passing the parameter values to the window system.
728 The name of a parameter, as a Lisp symbol,
729 has an `x-frame-parameter' property which is an integer in Lisp
730 that is an index in this table. */
732 struct x_frame_parm_table
735 void (*setter
) P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
738 static void x_create_im
P_ ((struct frame
*));
739 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
740 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
741 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
742 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
743 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
744 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
745 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
746 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
747 void x_set_font
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
748 void x_set_border_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
749 void x_set_internal_border_width
P_ ((struct frame
*, Lisp_Object
,
751 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
752 void x_set_autoraise
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
753 void x_set_autolower
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
754 void x_set_vertical_scroll_bars
P_ ((struct frame
*, Lisp_Object
,
756 void x_set_visibility
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
757 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
758 void x_set_scroll_bar_width
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
759 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
760 void x_set_unsplittable
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
761 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
762 void x_set_scroll_bar_foreground
P_ ((struct frame
*, Lisp_Object
,
764 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
766 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
771 static void x_set_screen_gamma
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
773 static struct x_frame_parm_table x_frame_parms
[] =
775 "auto-raise", x_set_autoraise
,
776 "auto-lower", x_set_autolower
,
777 "background-color", x_set_background_color
,
778 "border-color", x_set_border_color
,
779 "border-width", x_set_border_width
,
780 "cursor-color", x_set_cursor_color
,
781 "cursor-type", x_set_cursor_type
,
783 "foreground-color", x_set_foreground_color
,
784 "icon-name", x_set_icon_name
,
785 "icon-type", x_set_icon_type
,
786 "internal-border-width", x_set_internal_border_width
,
787 "menu-bar-lines", x_set_menu_bar_lines
,
788 "mouse-color", x_set_mouse_color
,
789 "name", x_explicitly_set_name
,
790 "scroll-bar-width", x_set_scroll_bar_width
,
791 "title", x_set_title
,
792 "unsplittable", x_set_unsplittable
,
793 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
794 "visibility", x_set_visibility
,
795 "tool-bar-lines", x_set_tool_bar_lines
,
796 "scroll-bar-foreground", x_set_scroll_bar_foreground
,
797 "scroll-bar-background", x_set_scroll_bar_background
,
798 "screen-gamma", x_set_screen_gamma
801 /* Attach the `x-frame-parameter' properties to
802 the Lisp symbol names of parameters relevant to X. */
805 init_x_parm_symbols ()
809 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
810 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
814 /* Change the parameters of frame F as specified by ALIST.
815 If a parameter is not specially recognized, do nothing;
816 otherwise call the `x_set_...' function for that parameter. */
819 x_set_frame_parameters (f
, alist
)
825 /* If both of these parameters are present, it's more efficient to
826 set them both at once. So we wait until we've looked at the
827 entire list before we set them. */
831 Lisp_Object left
, top
;
833 /* Same with these. */
834 Lisp_Object icon_left
, icon_top
;
836 /* Record in these vectors all the parms specified. */
840 int left_no_change
= 0, top_no_change
= 0;
841 int icon_left_no_change
= 0, icon_top_no_change
= 0;
843 struct gcpro gcpro1
, gcpro2
;
846 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
849 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
850 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
852 /* Extract parm names and values into those vectors. */
855 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
860 parms
[i
] = Fcar (elt
);
861 values
[i
] = Fcdr (elt
);
864 /* TAIL and ALIST are not used again below here. */
867 GCPRO2 (*parms
, *values
);
871 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
872 because their values appear in VALUES and strings are not valid. */
873 top
= left
= Qunbound
;
874 icon_left
= icon_top
= Qunbound
;
876 /* Provide default values for HEIGHT and WIDTH. */
877 if (FRAME_NEW_WIDTH (f
))
878 width
= FRAME_NEW_WIDTH (f
);
880 width
= FRAME_WIDTH (f
);
882 if (FRAME_NEW_HEIGHT (f
))
883 height
= FRAME_NEW_HEIGHT (f
);
885 height
= FRAME_HEIGHT (f
);
887 /* Process foreground_color and background_color before anything else.
888 They are independent of other properties, but other properties (e.g.,
889 cursor_color) are dependent upon them. */
890 for (p
= 0; p
< i
; p
++)
892 Lisp_Object prop
, val
;
896 if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
898 register Lisp_Object param_index
, old_value
;
900 param_index
= Fget (prop
, Qx_frame_parameter
);
901 old_value
= get_frame_param (f
, prop
);
902 store_frame_param (f
, prop
, val
);
903 if (NATNUMP (param_index
)
904 && (XFASTINT (param_index
)
905 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
906 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
910 /* Now process them in reverse of specified order. */
911 for (i
--; i
>= 0; i
--)
913 Lisp_Object prop
, val
;
918 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
919 width
= XFASTINT (val
);
920 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
921 height
= XFASTINT (val
);
922 else if (EQ (prop
, Qtop
))
924 else if (EQ (prop
, Qleft
))
926 else if (EQ (prop
, Qicon_top
))
928 else if (EQ (prop
, Qicon_left
))
930 else if (EQ (prop
, Qforeground_color
) || EQ (prop
, Qbackground_color
))
931 /* Processed above. */
935 register Lisp_Object param_index
, old_value
;
937 param_index
= Fget (prop
, Qx_frame_parameter
);
938 old_value
= get_frame_param (f
, prop
);
939 store_frame_param (f
, prop
, val
);
940 if (NATNUMP (param_index
)
941 && (XFASTINT (param_index
)
942 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
943 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
947 /* Don't die if just one of these was set. */
948 if (EQ (left
, Qunbound
))
951 if (f
->output_data
.x
->left_pos
< 0)
952 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->left_pos
), Qnil
));
954 XSETINT (left
, f
->output_data
.x
->left_pos
);
956 if (EQ (top
, Qunbound
))
959 if (f
->output_data
.x
->top_pos
< 0)
960 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.x
->top_pos
), Qnil
));
962 XSETINT (top
, f
->output_data
.x
->top_pos
);
965 /* If one of the icon positions was not set, preserve or default it. */
966 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
968 icon_left_no_change
= 1;
969 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
970 if (NILP (icon_left
))
971 XSETINT (icon_left
, 0);
973 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
975 icon_top_no_change
= 1;
976 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
978 XSETINT (icon_top
, 0);
981 /* Don't set these parameters unless they've been explicitly
982 specified. The window might be mapped or resized while we're in
983 this function, and we don't want to override that unless the lisp
984 code has asked for it.
986 Don't set these parameters unless they actually differ from the
987 window's current parameters; the window may not actually exist
992 check_frame_size (f
, &height
, &width
);
994 XSETFRAME (frame
, f
);
996 if (width
!= FRAME_WIDTH (f
)
997 || height
!= FRAME_HEIGHT (f
)
998 || FRAME_NEW_HEIGHT (f
) || FRAME_NEW_WIDTH (f
))
999 Fset_frame_size (frame
, make_number (width
), make_number (height
));
1001 if ((!NILP (left
) || !NILP (top
))
1002 && ! (left_no_change
&& top_no_change
)
1003 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.x
->left_pos
1004 && NUMBERP (top
) && XINT (top
) == f
->output_data
.x
->top_pos
))
1009 /* Record the signs. */
1010 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
1011 if (EQ (left
, Qminus
))
1012 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1013 else if (INTEGERP (left
))
1015 leftpos
= XINT (left
);
1017 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1019 else if (CONSP (left
) && EQ (XCAR (left
), Qminus
)
1020 && CONSP (XCDR (left
))
1021 && INTEGERP (XCAR (XCDR (left
))))
1023 leftpos
= - XINT (XCAR (XCDR (left
)));
1024 f
->output_data
.x
->size_hint_flags
|= XNegative
;
1026 else if (CONSP (left
) && EQ (XCAR (left
), Qplus
)
1027 && CONSP (XCDR (left
))
1028 && INTEGERP (XCAR (XCDR (left
))))
1030 leftpos
= XINT (XCAR (XCDR (left
)));
1033 if (EQ (top
, Qminus
))
1034 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1035 else if (INTEGERP (top
))
1037 toppos
= XINT (top
);
1039 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1041 else if (CONSP (top
) && EQ (XCAR (top
), Qminus
)
1042 && CONSP (XCDR (top
))
1043 && INTEGERP (XCAR (XCDR (top
))))
1045 toppos
= - XINT (XCAR (XCDR (top
)));
1046 f
->output_data
.x
->size_hint_flags
|= YNegative
;
1048 else if (CONSP (top
) && EQ (XCAR (top
), Qplus
)
1049 && CONSP (XCDR (top
))
1050 && INTEGERP (XCAR (XCDR (top
))))
1052 toppos
= XINT (XCAR (XCDR (top
)));
1056 /* Store the numeric value of the position. */
1057 f
->output_data
.x
->top_pos
= toppos
;
1058 f
->output_data
.x
->left_pos
= leftpos
;
1060 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
1062 /* Actually set that position, and convert to absolute. */
1063 x_set_offset (f
, leftpos
, toppos
, -1);
1066 if ((!NILP (icon_left
) || !NILP (icon_top
))
1067 && ! (icon_left_no_change
&& icon_top_no_change
))
1068 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
1074 /* Store the screen positions of frame F into XPTR and YPTR.
1075 These are the positions of the containing window manager window,
1076 not Emacs's own window. */
1079 x_real_positions (f
, xptr
, yptr
)
1086 /* This is pretty gross, but seems to be the easiest way out of
1087 the problem that arises when restarting window-managers. */
1089 #ifdef USE_X_TOOLKIT
1090 Window outer
= (f
->output_data
.x
->widget
1091 ? XtWindow (f
->output_data
.x
->widget
)
1092 : FRAME_X_WINDOW (f
));
1094 Window outer
= f
->output_data
.x
->window_desc
;
1096 Window tmp_root_window
;
1097 Window
*tmp_children
;
1102 int count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1103 Window outer_window
;
1105 XQueryTree (FRAME_X_DISPLAY (f
), outer
, &tmp_root_window
,
1106 &f
->output_data
.x
->parent_desc
,
1107 &tmp_children
, &tmp_nchildren
);
1108 XFree ((char *) tmp_children
);
1112 /* Find the position of the outside upper-left corner of
1113 the inner window, with respect to the outer window. */
1114 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
1115 outer_window
= f
->output_data
.x
->parent_desc
;
1117 outer_window
= outer
;
1119 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1121 /* From-window, to-window. */
1123 FRAME_X_DISPLAY_INFO (f
)->root_window
,
1125 /* From-position, to-position. */
1126 0, 0, &win_x
, &win_y
,
1131 /* It is possible for the window returned by the XQueryNotify
1132 to become invalid by the time we call XTranslateCoordinates.
1133 That can happen when you restart some window managers.
1134 If so, we get an error in XTranslateCoordinates.
1135 Detect that and try the whole thing over. */
1136 if (! x_had_errors_p (FRAME_X_DISPLAY (f
)))
1138 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1142 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1149 /* Insert a description of internally-recorded parameters of frame X
1150 into the parameter alist *ALISTPTR that is to be given to the user.
1151 Only parameters that are specific to the X window system
1152 and whose values are not correctly recorded in the frame's
1153 param_alist need to be considered here. */
1156 x_report_frame_params (f
, alistptr
)
1158 Lisp_Object
*alistptr
;
1163 /* Represent negative positions (off the top or left screen edge)
1164 in a way that Fmodify_frame_parameters will understand correctly. */
1165 XSETINT (tem
, f
->output_data
.x
->left_pos
);
1166 if (f
->output_data
.x
->left_pos
>= 0)
1167 store_in_alist (alistptr
, Qleft
, tem
);
1169 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1171 XSETINT (tem
, f
->output_data
.x
->top_pos
);
1172 if (f
->output_data
.x
->top_pos
>= 0)
1173 store_in_alist (alistptr
, Qtop
, tem
);
1175 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
1177 store_in_alist (alistptr
, Qborder_width
,
1178 make_number (f
->output_data
.x
->border_width
));
1179 store_in_alist (alistptr
, Qinternal_border_width
,
1180 make_number (f
->output_data
.x
->internal_border_width
));
1181 sprintf (buf
, "%ld", (long) FRAME_X_WINDOW (f
));
1182 store_in_alist (alistptr
, Qwindow_id
,
1183 build_string (buf
));
1184 #ifdef USE_X_TOOLKIT
1185 /* Tooltip frame may not have this widget. */
1186 if (f
->output_data
.x
->widget
)
1188 sprintf (buf
, "%ld", (long) FRAME_OUTER_WINDOW (f
));
1189 store_in_alist (alistptr
, Qouter_window_id
,
1190 build_string (buf
));
1191 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
1192 FRAME_SAMPLE_VISIBILITY (f
);
1193 store_in_alist (alistptr
, Qvisibility
,
1194 (FRAME_VISIBLE_P (f
) ? Qt
1195 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
1196 store_in_alist (alistptr
, Qdisplay
,
1197 XCAR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
1199 if (f
->output_data
.x
->parent_desc
== FRAME_X_DISPLAY_INFO (f
)->root_window
)
1202 XSETFASTINT (tem
, f
->output_data
.x
->parent_desc
);
1203 store_in_alist (alistptr
, Qparent_id
, tem
);
1208 /* Gamma-correct COLOR on frame F. */
1211 gamma_correct (f
, color
)
1217 color
->red
= pow (color
->red
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1218 color
->green
= pow (color
->green
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1219 color
->blue
= pow (color
->blue
/ 65535.0, f
->gamma
) * 65535.0 + 0.5;
1224 /* Decide if color named COLOR is valid for the display associated with
1225 the selected frame; if so, return the rgb values in COLOR_DEF.
1226 If ALLOC is nonzero, allocate a new colormap cell. */
1229 x_defined_color (f
, color
, color_def
, alloc
)
1235 register int status
;
1236 Colormap screen_colormap
;
1237 Display
*display
= FRAME_X_DISPLAY (f
);
1240 screen_colormap
= DefaultColormap (display
, XDefaultScreen (display
));
1242 status
= XParseColor (display
, screen_colormap
, color
, color_def
);
1243 if (status
&& alloc
)
1245 /* Apply gamma correction. */
1246 gamma_correct (f
, color_def
);
1248 status
= XAllocColor (display
, screen_colormap
, color_def
);
1251 /* If we got to this point, the colormap is full, so we're
1252 going to try and get the next closest color.
1253 The algorithm used is a least-squares matching, which is
1254 what X uses for closest color matching with StaticColor visuals. */
1259 long nearest_delta
, trial_delta
;
1262 no_cells
= XDisplayCells (display
, XDefaultScreen (display
));
1263 cells
= (XColor
*) alloca (sizeof (XColor
) * no_cells
);
1265 for (x
= 0; x
< no_cells
; x
++)
1268 XQueryColors (display
, screen_colormap
, cells
, no_cells
);
1270 /* I'm assuming CSE so I'm not going to condense this. */
1271 nearest_delta
= ((((color_def
->red
>> 8) - (cells
[0].red
>> 8))
1272 * ((color_def
->red
>> 8) - (cells
[0].red
>> 8)))
1274 (((color_def
->green
>> 8) - (cells
[0].green
>> 8))
1275 * ((color_def
->green
>> 8) - (cells
[0].green
>> 8)))
1277 (((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))
1278 * ((color_def
->blue
>> 8) - (cells
[0].blue
>> 8))));
1279 for (x
= 1; x
< no_cells
; x
++)
1281 trial_delta
= ((((color_def
->red
>> 8) - (cells
[x
].red
>> 8))
1282 * ((color_def
->red
>> 8) - (cells
[x
].red
>> 8)))
1284 (((color_def
->green
>> 8) - (cells
[x
].green
>> 8))
1285 * ((color_def
->green
>> 8) - (cells
[x
].green
>> 8)))
1287 (((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))
1288 * ((color_def
->blue
>> 8) - (cells
[x
].blue
>> 8))));
1289 if (trial_delta
< nearest_delta
)
1292 temp
.red
= cells
[x
].red
;
1293 temp
.green
= cells
[x
].green
;
1294 temp
.blue
= cells
[x
].blue
;
1295 status
= XAllocColor (display
, screen_colormap
, &temp
);
1299 nearest_delta
= trial_delta
;
1303 color_def
->red
= cells
[nearest
].red
;
1304 color_def
->green
= cells
[nearest
].green
;
1305 color_def
->blue
= cells
[nearest
].blue
;
1306 status
= XAllocColor (display
, screen_colormap
, color_def
);
1317 /* Given a string ARG naming a color, compute a pixel value from it
1318 suitable for screen F.
1319 If F is not a color screen, return DEF (default) regardless of what
1323 x_decode_color (f
, arg
, def
)
1330 CHECK_STRING (arg
, 0);
1332 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1333 return BLACK_PIX_DEFAULT (f
);
1334 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1335 return WHITE_PIX_DEFAULT (f
);
1337 if (FRAME_X_DISPLAY_INFO (f
)->n_planes
== 1)
1340 /* x_defined_color is responsible for coping with failures
1341 by looking for a near-miss. */
1342 if (x_defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1345 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
1346 Fcons (arg
, Qnil
)));
1349 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1350 the previous value of that parameter, NEW_VALUE is the new value. */
1353 x_set_screen_gamma (f
, new_value
, old_value
)
1355 Lisp_Object new_value
, old_value
;
1357 if (NILP (new_value
))
1359 else if (NUMBERP (new_value
) && XFLOATINT (new_value
) > 0)
1360 /* The value 0.4545 is the normal viewing gamma. */
1361 f
->gamma
= 1.0 / (0.4545 * XFLOATINT (new_value
));
1363 Fsignal (Qerror
, Fcons (build_string ("Illegal screen-gamma"),
1364 Fcons (new_value
, Qnil
)));
1366 clear_face_cache (0);
1370 /* Functions called only from `x_set_frame_param'
1371 to set individual parameters.
1373 If FRAME_X_WINDOW (f) is 0,
1374 the frame is being created and its X-window does not exist yet.
1375 In that case, just record the parameter's new value
1376 in the standard place; do not attempt to change the window. */
1379 x_set_foreground_color (f
, arg
, oldval
)
1381 Lisp_Object arg
, oldval
;
1384 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1386 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
1387 f
->output_data
.x
->foreground_pixel
= pixel
;
1389 if (FRAME_X_WINDOW (f
) != 0)
1392 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1393 f
->output_data
.x
->foreground_pixel
);
1394 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1395 f
->output_data
.x
->foreground_pixel
);
1397 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1398 if (FRAME_VISIBLE_P (f
))
1404 x_set_background_color (f
, arg
, oldval
)
1406 Lisp_Object arg
, oldval
;
1409 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1411 unload_color (f
, f
->output_data
.x
->background_pixel
);
1412 f
->output_data
.x
->background_pixel
= pixel
;
1414 if (FRAME_X_WINDOW (f
) != 0)
1417 /* The main frame area. */
1418 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1419 f
->output_data
.x
->background_pixel
);
1420 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
1421 f
->output_data
.x
->background_pixel
);
1422 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1423 f
->output_data
.x
->background_pixel
);
1424 XSetWindowBackground (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1425 f
->output_data
.x
->background_pixel
);
1428 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
);
1429 bar
= XSCROLL_BAR (bar
)->next
)
1430 XSetWindowBackground (FRAME_X_DISPLAY (f
),
1431 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
1432 f
->output_data
.x
->background_pixel
);
1436 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1438 if (FRAME_VISIBLE_P (f
))
1444 x_set_mouse_color (f
, arg
, oldval
)
1446 Lisp_Object arg
, oldval
;
1448 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1451 unsigned long pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1452 unsigned long mask_color
= f
->output_data
.x
->background_pixel
;
1454 /* Don't let pointers be invisible. */
1455 if (mask_color
== pixel
1456 && mask_color
== f
->output_data
.x
->background_pixel
)
1457 pixel
= f
->output_data
.x
->foreground_pixel
;
1459 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
1460 f
->output_data
.x
->mouse_pixel
= pixel
;
1464 /* It's not okay to crash if the user selects a screwy cursor. */
1465 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
1467 if (!EQ (Qnil
, Vx_pointer_shape
))
1469 CHECK_NUMBER (Vx_pointer_shape
, 0);
1470 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XINT (Vx_pointer_shape
));
1473 cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1474 x_check_errors (FRAME_X_DISPLAY (f
), "bad text pointer cursor: %s");
1476 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1478 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1479 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1480 XINT (Vx_nontext_pointer_shape
));
1483 nontext_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_left_ptr
);
1484 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1486 if (!EQ (Qnil
, Vx_busy_pointer_shape
))
1488 CHECK_NUMBER (Vx_busy_pointer_shape
, 0);
1489 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1490 XINT (Vx_busy_pointer_shape
));
1493 busy_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_watch
);
1494 x_check_errors (FRAME_X_DISPLAY (f
), "bad busy pointer cursor: %s");
1496 x_check_errors (FRAME_X_DISPLAY (f
), "bad nontext pointer cursor: %s");
1497 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1499 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1500 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
),
1501 XINT (Vx_mode_pointer_shape
));
1504 mode_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_xterm
);
1505 x_check_errors (FRAME_X_DISPLAY (f
), "bad modeline pointer cursor: %s");
1507 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1509 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1511 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1512 XINT (Vx_sensitive_text_pointer_shape
));
1515 cross_cursor
= XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_crosshair
);
1517 /* Check and report errors with the above calls. */
1518 x_check_errors (FRAME_X_DISPLAY (f
), "can't set cursor shape: %s");
1519 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
1522 XColor fore_color
, back_color
;
1524 fore_color
.pixel
= f
->output_data
.x
->mouse_pixel
;
1525 back_color
.pixel
= mask_color
;
1526 XQueryColor (FRAME_X_DISPLAY (f
),
1527 DefaultColormap (FRAME_X_DISPLAY (f
),
1528 DefaultScreen (FRAME_X_DISPLAY (f
))),
1530 XQueryColor (FRAME_X_DISPLAY (f
),
1531 DefaultColormap (FRAME_X_DISPLAY (f
),
1532 DefaultScreen (FRAME_X_DISPLAY (f
))),
1534 XRecolorCursor (FRAME_X_DISPLAY (f
), cursor
,
1535 &fore_color
, &back_color
);
1536 XRecolorCursor (FRAME_X_DISPLAY (f
), nontext_cursor
,
1537 &fore_color
, &back_color
);
1538 XRecolorCursor (FRAME_X_DISPLAY (f
), mode_cursor
,
1539 &fore_color
, &back_color
);
1540 XRecolorCursor (FRAME_X_DISPLAY (f
), cross_cursor
,
1541 &fore_color
, &back_color
);
1542 XRecolorCursor (FRAME_X_DISPLAY (f
), busy_cursor
,
1543 &fore_color
, &back_color
);
1546 if (FRAME_X_WINDOW (f
) != 0)
1547 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
1549 if (cursor
!= f
->output_data
.x
->text_cursor
&& f
->output_data
.x
->text_cursor
!= 0)
1550 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
1551 f
->output_data
.x
->text_cursor
= cursor
;
1553 if (nontext_cursor
!= f
->output_data
.x
->nontext_cursor
1554 && f
->output_data
.x
->nontext_cursor
!= 0)
1555 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
1556 f
->output_data
.x
->nontext_cursor
= nontext_cursor
;
1558 if (busy_cursor
!= f
->output_data
.x
->busy_cursor
1559 && f
->output_data
.x
->busy_cursor
!= 0)
1560 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_cursor
);
1561 f
->output_data
.x
->busy_cursor
= busy_cursor
;
1563 if (mode_cursor
!= f
->output_data
.x
->modeline_cursor
1564 && f
->output_data
.x
->modeline_cursor
!= 0)
1565 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
1566 f
->output_data
.x
->modeline_cursor
= mode_cursor
;
1568 if (cross_cursor
!= f
->output_data
.x
->cross_cursor
1569 && f
->output_data
.x
->cross_cursor
!= 0)
1570 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cross_cursor
);
1571 f
->output_data
.x
->cross_cursor
= cross_cursor
;
1573 XFlush (FRAME_X_DISPLAY (f
));
1576 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1580 x_set_cursor_color (f
, arg
, oldval
)
1582 Lisp_Object arg
, oldval
;
1584 unsigned long fore_pixel
, pixel
;
1586 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1587 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1588 WHITE_PIX_DEFAULT (f
));
1590 fore_pixel
= f
->output_data
.x
->background_pixel
;
1591 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1593 /* Make sure that the cursor color differs from the background color. */
1594 if (pixel
== f
->output_data
.x
->background_pixel
)
1596 pixel
= f
->output_data
.x
->mouse_pixel
;
1597 if (pixel
== fore_pixel
)
1598 fore_pixel
= f
->output_data
.x
->background_pixel
;
1601 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
1602 f
->output_data
.x
->cursor_foreground_pixel
= fore_pixel
;
1604 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
1605 f
->output_data
.x
->cursor_pixel
= pixel
;
1607 if (FRAME_X_WINDOW (f
) != 0)
1610 XSetBackground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1611 f
->output_data
.x
->cursor_pixel
);
1612 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
1616 if (FRAME_VISIBLE_P (f
))
1618 x_update_cursor (f
, 0);
1619 x_update_cursor (f
, 1);
1623 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1626 /* Set the border-color of frame F to value described by ARG.
1627 ARG can be a string naming a color.
1628 The border-color is used for the border that is drawn by the X server.
1629 Note that this does not fully take effect if done before
1630 F has an x-window; it must be redone when the window is created.
1632 Note: this is done in two routines because of the way X10 works.
1634 Note: under X11, this is normally the province of the window manager,
1635 and so emacs' border colors may be overridden. */
1638 x_set_border_color (f
, arg
, oldval
)
1640 Lisp_Object arg
, oldval
;
1644 CHECK_STRING (arg
, 0);
1645 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1646 x_set_border_pixel (f
, pix
);
1647 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1650 /* Set the border-color of frame F to pixel value PIX.
1651 Note that this does not fully take effect if done before
1652 F has an x-window. */
1655 x_set_border_pixel (f
, pix
)
1659 unload_color (f
, f
->output_data
.x
->border_pixel
);
1660 f
->output_data
.x
->border_pixel
= pix
;
1662 if (FRAME_X_WINDOW (f
) != 0 && f
->output_data
.x
->border_width
> 0)
1665 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1666 (unsigned long)pix
);
1669 if (FRAME_VISIBLE_P (f
))
1675 x_set_cursor_type (f
, arg
, oldval
)
1677 Lisp_Object arg
, oldval
;
1681 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1682 f
->output_data
.x
->cursor_width
= 2;
1684 else if (CONSP (arg
) && EQ (XCAR (arg
), Qbar
)
1685 && INTEGERP (XCDR (arg
)))
1687 FRAME_DESIRED_CURSOR (f
) = BAR_CURSOR
;
1688 f
->output_data
.x
->cursor_width
= XINT (XCDR (arg
));
1691 /* Treat anything unknown as "box cursor".
1692 It was bad to signal an error; people have trouble fixing
1693 .Xdefaults with Emacs, when it has something bad in it. */
1694 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
1696 /* Make sure the cursor gets redrawn. This is overkill, but how
1697 often do people change cursor types? */
1698 update_mode_lines
++;
1702 x_set_icon_type (f
, arg
, oldval
)
1704 Lisp_Object arg
, oldval
;
1710 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1713 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1718 result
= x_text_icon (f
,
1719 (char *) XSTRING ((!NILP (f
->icon_name
)
1723 result
= x_bitmap_icon (f
, arg
);
1728 error ("No icon window available");
1731 XFlush (FRAME_X_DISPLAY (f
));
1735 /* Return non-nil if frame F wants a bitmap icon. */
1743 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1751 x_set_icon_name (f
, arg
, oldval
)
1753 Lisp_Object arg
, oldval
;
1759 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1762 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1767 if (f
->output_data
.x
->icon_bitmap
!= 0)
1772 result
= x_text_icon (f
,
1773 (char *) XSTRING ((!NILP (f
->icon_name
)
1782 error ("No icon window available");
1785 XFlush (FRAME_X_DISPLAY (f
));
1790 x_set_font (f
, arg
, oldval
)
1792 Lisp_Object arg
, oldval
;
1795 Lisp_Object fontset_name
;
1798 CHECK_STRING (arg
, 1);
1800 fontset_name
= Fquery_fontset (arg
, Qnil
);
1803 result
= (STRINGP (fontset_name
)
1804 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
1805 : x_new_font (f
, XSTRING (arg
)->data
));
1808 if (EQ (result
, Qnil
))
1809 error ("Font `%s' is not defined", XSTRING (arg
)->data
);
1810 else if (EQ (result
, Qt
))
1811 error ("The characters of the given font have varying widths");
1812 else if (STRINGP (result
))
1814 store_frame_param (f
, Qfont
, result
);
1815 recompute_basic_faces (f
);
1820 do_pending_window_change (0);
1822 /* Don't call `face-set-after-frame-default' when faces haven't been
1823 initialized yet. This is the case when called from
1824 Fx_create_frame. In that case, the X widget or window doesn't
1825 exist either, and we can end up in x_report_frame_params with a
1826 null widget which gives a segfault. */
1827 if (FRAME_FACE_CACHE (f
))
1829 XSETFRAME (frame
, f
);
1830 call1 (Qface_set_after_frame_default
, frame
);
1835 x_set_border_width (f
, arg
, oldval
)
1837 Lisp_Object arg
, oldval
;
1839 CHECK_NUMBER (arg
, 0);
1841 if (XINT (arg
) == f
->output_data
.x
->border_width
)
1844 if (FRAME_X_WINDOW (f
) != 0)
1845 error ("Cannot change the border width of a window");
1847 f
->output_data
.x
->border_width
= XINT (arg
);
1851 x_set_internal_border_width (f
, arg
, oldval
)
1853 Lisp_Object arg
, oldval
;
1855 int old
= f
->output_data
.x
->internal_border_width
;
1857 CHECK_NUMBER (arg
, 0);
1858 f
->output_data
.x
->internal_border_width
= XINT (arg
);
1859 if (f
->output_data
.x
->internal_border_width
< 0)
1860 f
->output_data
.x
->internal_border_width
= 0;
1862 #ifdef USE_X_TOOLKIT
1863 if (f
->output_data
.x
->edit_widget
)
1864 widget_store_internal_border (f
->output_data
.x
->edit_widget
);
1867 if (f
->output_data
.x
->internal_border_width
== old
)
1870 if (FRAME_X_WINDOW (f
) != 0)
1872 x_set_window_size (f
, 0, f
->width
, f
->height
);
1873 SET_FRAME_GARBAGED (f
);
1874 do_pending_window_change (0);
1879 x_set_visibility (f
, value
, oldval
)
1881 Lisp_Object value
, oldval
;
1884 XSETFRAME (frame
, f
);
1887 Fmake_frame_invisible (frame
, Qt
);
1888 else if (EQ (value
, Qicon
))
1889 Ficonify_frame (frame
);
1891 Fmake_frame_visible (frame
);
1895 x_set_menu_bar_lines_1 (window
, n
)
1899 struct window
*w
= XWINDOW (window
);
1901 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
1902 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
1904 /* Handle just the top child in a vertical split. */
1905 if (!NILP (w
->vchild
))
1906 x_set_menu_bar_lines_1 (w
->vchild
, n
);
1908 /* Adjust all children in a horizontal split. */
1909 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
1911 w
= XWINDOW (window
);
1912 x_set_menu_bar_lines_1 (window
, n
);
1917 x_set_menu_bar_lines (f
, value
, oldval
)
1919 Lisp_Object value
, oldval
;
1922 #ifndef USE_X_TOOLKIT
1923 int olines
= FRAME_MENU_BAR_LINES (f
);
1926 /* Right now, menu bars don't work properly in minibuf-only frames;
1927 most of the commands try to apply themselves to the minibuffer
1928 frame itself, and get an error because you can't switch buffers
1929 in or split the minibuffer window. */
1930 if (FRAME_MINIBUF_ONLY_P (f
))
1933 if (INTEGERP (value
))
1934 nlines
= XINT (value
);
1938 /* Make sure we redisplay all windows in this frame. */
1939 windows_or_buffers_changed
++;
1941 #ifdef USE_X_TOOLKIT
1942 FRAME_MENU_BAR_LINES (f
) = 0;
1945 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1946 if (FRAME_X_P (f
) && f
->output_data
.x
->menubar_widget
== 0)
1947 /* Make sure next redisplay shows the menu bar. */
1948 XWINDOW (FRAME_SELECTED_WINDOW (f
))->update_mode_line
= Qt
;
1952 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1953 free_frame_menubar (f
);
1954 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1956 f
->output_data
.x
->menubar_widget
= 0;
1958 #else /* not USE_X_TOOLKIT */
1959 FRAME_MENU_BAR_LINES (f
) = nlines
;
1960 x_set_menu_bar_lines_1 (f
->root_window
, nlines
- olines
);
1961 #endif /* not USE_X_TOOLKIT */
1966 /* Set the number of lines used for the tool bar of frame F to VALUE.
1967 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1968 is the old number of tool bar lines. This function changes the
1969 height of all windows on frame F to match the new tool bar height.
1970 The frame's height doesn't change. */
1973 x_set_tool_bar_lines (f
, value
, oldval
)
1975 Lisp_Object value
, oldval
;
1979 /* Use VALUE only if an integer >= 0. */
1980 if (INTEGERP (value
) && XINT (value
) >= 0)
1981 nlines
= XFASTINT (value
);
1985 /* Make sure we redisplay all windows in this frame. */
1986 ++windows_or_buffers_changed
;
1988 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
1989 FRAME_TOOL_BAR_LINES (f
) = nlines
;
1990 x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f
), delta
);
1995 /* Set the foreground color for scroll bars on frame F to VALUE.
1996 VALUE should be a string, a color name. If it isn't a string or
1997 isn't a valid color name, do nothing. OLDVAL is the old value of
1998 the frame parameter. */
2001 x_set_scroll_bar_foreground (f
, value
, oldval
)
2003 Lisp_Object value
, oldval
;
2005 unsigned long pixel
;
2007 if (STRINGP (value
))
2008 pixel
= x_decode_color (f
, value
, BLACK_PIX_DEFAULT (f
));
2012 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
2013 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
2015 f
->output_data
.x
->scroll_bar_foreground_pixel
= pixel
;
2016 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2018 /* Remove all scroll bars because they have wrong colors. */
2019 if (condemn_scroll_bars_hook
)
2020 (*condemn_scroll_bars_hook
) (f
);
2021 if (judge_scroll_bars_hook
)
2022 (*judge_scroll_bars_hook
) (f
);
2024 update_face_from_frame_parameter (f
, Qscroll_bar_foreground
, value
);
2030 /* Set the background color for scroll bars on frame F to VALUE VALUE
2031 should be a string, a color name. If it isn't a string or isn't a
2032 valid color name, do nothing. OLDVAL is the old value of the frame
2036 x_set_scroll_bar_background (f
, value
, oldval
)
2038 Lisp_Object value
, oldval
;
2040 unsigned long pixel
;
2042 if (STRINGP (value
))
2043 pixel
= x_decode_color (f
, value
, WHITE_PIX_DEFAULT (f
));
2047 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
2048 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
2050 f
->output_data
.x
->scroll_bar_background_pixel
= pixel
;
2051 if (FRAME_X_WINDOW (f
) && FRAME_VISIBLE_P (f
))
2053 /* Remove all scroll bars because they have wrong colors. */
2054 if (condemn_scroll_bars_hook
)
2055 (*condemn_scroll_bars_hook
) (f
);
2056 if (judge_scroll_bars_hook
)
2057 (*judge_scroll_bars_hook
) (f
);
2059 update_face_from_frame_parameter (f
, Qscroll_bar_background
, value
);
2065 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2068 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2069 name; if NAME is a string, set F's name to NAME and set
2070 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2072 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2073 suggesting a new name, which lisp code should override; if
2074 F->explicit_name is set, ignore the new name; otherwise, set it. */
2077 x_set_name (f
, name
, explicit)
2082 /* Make sure that requests from lisp code override requests from
2083 Emacs redisplay code. */
2086 /* If we're switching from explicit to implicit, we had better
2087 update the mode lines and thereby update the title. */
2088 if (f
->explicit_name
&& NILP (name
))
2089 update_mode_lines
= 1;
2091 f
->explicit_name
= ! NILP (name
);
2093 else if (f
->explicit_name
)
2096 /* If NAME is nil, set the name to the x_id_name. */
2099 /* Check for no change needed in this very common case
2100 before we do any consing. */
2101 if (!strcmp (FRAME_X_DISPLAY_INFO (f
)->x_id_name
,
2102 XSTRING (f
->name
)->data
))
2104 name
= build_string (FRAME_X_DISPLAY_INFO (f
)->x_id_name
);
2107 CHECK_STRING (name
, 0);
2109 /* Don't change the name if it's already NAME. */
2110 if (! NILP (Fstring_equal (name
, f
->name
)))
2115 /* For setting the frame title, the title parameter should override
2116 the name parameter. */
2117 if (! NILP (f
->title
))
2120 if (FRAME_X_WINDOW (f
))
2125 XTextProperty text
, icon
;
2126 Lisp_Object icon_name
;
2128 text
.value
= XSTRING (name
)->data
;
2129 text
.encoding
= XA_STRING
;
2131 text
.nitems
= STRING_BYTES (XSTRING (name
));
2133 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2135 icon
.value
= XSTRING (icon_name
)->data
;
2136 icon
.encoding
= XA_STRING
;
2138 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2139 #ifdef USE_X_TOOLKIT
2140 XSetWMName (FRAME_X_DISPLAY (f
),
2141 XtWindow (f
->output_data
.x
->widget
), &text
);
2142 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2144 #else /* not USE_X_TOOLKIT */
2145 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2146 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2147 #endif /* not USE_X_TOOLKIT */
2149 #else /* not HAVE_X11R4 */
2150 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2151 XSTRING (name
)->data
);
2152 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2153 XSTRING (name
)->data
);
2154 #endif /* not HAVE_X11R4 */
2159 /* This function should be called when the user's lisp code has
2160 specified a name for the frame; the name will override any set by the
2163 x_explicitly_set_name (f
, arg
, oldval
)
2165 Lisp_Object arg
, oldval
;
2167 x_set_name (f
, arg
, 1);
2170 /* This function should be called by Emacs redisplay code to set the
2171 name; names set this way will never override names set by the user's
2174 x_implicitly_set_name (f
, arg
, oldval
)
2176 Lisp_Object arg
, oldval
;
2178 x_set_name (f
, arg
, 0);
2181 /* Change the title of frame F to NAME.
2182 If NAME is nil, use the frame name as the title.
2184 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2185 name; if NAME is a string, set F's name to NAME and set
2186 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2188 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2189 suggesting a new name, which lisp code should override; if
2190 F->explicit_name is set, ignore the new name; otherwise, set it. */
2193 x_set_title (f
, name
, old_name
)
2195 Lisp_Object name
, old_name
;
2197 /* Don't change the title if it's already NAME. */
2198 if (EQ (name
, f
->title
))
2201 update_mode_lines
= 1;
2208 CHECK_STRING (name
, 0);
2210 if (FRAME_X_WINDOW (f
))
2215 XTextProperty text
, icon
;
2216 Lisp_Object icon_name
;
2218 text
.value
= XSTRING (name
)->data
;
2219 text
.encoding
= XA_STRING
;
2221 text
.nitems
= STRING_BYTES (XSTRING (name
));
2223 icon_name
= (!NILP (f
->icon_name
) ? f
->icon_name
: name
);
2225 icon
.value
= XSTRING (icon_name
)->data
;
2226 icon
.encoding
= XA_STRING
;
2228 icon
.nitems
= STRING_BYTES (XSTRING (icon_name
));
2229 #ifdef USE_X_TOOLKIT
2230 XSetWMName (FRAME_X_DISPLAY (f
),
2231 XtWindow (f
->output_data
.x
->widget
), &text
);
2232 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
2234 #else /* not USE_X_TOOLKIT */
2235 XSetWMName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
2236 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &icon
);
2237 #endif /* not USE_X_TOOLKIT */
2239 #else /* not HAVE_X11R4 */
2240 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2241 XSTRING (name
)->data
);
2242 XStoreName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2243 XSTRING (name
)->data
);
2244 #endif /* not HAVE_X11R4 */
2250 x_set_autoraise (f
, arg
, oldval
)
2252 Lisp_Object arg
, oldval
;
2254 f
->auto_raise
= !EQ (Qnil
, arg
);
2258 x_set_autolower (f
, arg
, oldval
)
2260 Lisp_Object arg
, oldval
;
2262 f
->auto_lower
= !EQ (Qnil
, arg
);
2266 x_set_unsplittable (f
, arg
, oldval
)
2268 Lisp_Object arg
, oldval
;
2270 f
->no_split
= !NILP (arg
);
2274 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2276 Lisp_Object arg
, oldval
;
2278 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2279 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2280 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2281 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2283 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
)
2285 ? vertical_scroll_bar_none
2287 ? vertical_scroll_bar_right
2288 : vertical_scroll_bar_left
);
2290 /* We set this parameter before creating the X window for the
2291 frame, so we can get the geometry right from the start.
2292 However, if the window hasn't been created yet, we shouldn't
2293 call x_set_window_size. */
2294 if (FRAME_X_WINDOW (f
))
2295 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2296 do_pending_window_change (0);
2301 x_set_scroll_bar_width (f
, arg
, oldval
)
2303 Lisp_Object arg
, oldval
;
2305 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
2309 #ifdef USE_TOOLKIT_SCROLL_BARS
2310 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2311 int width
= 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2312 FRAME_SCROLL_BAR_COLS (f
) = (width
+ wid
- 1) / wid
;
2313 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = width
;
2315 /* Make the actual width at least 14 pixels and a multiple of a
2317 FRAME_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2319 /* Use all of that space (aside from required margins) for the
2321 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2324 if (FRAME_X_WINDOW (f
))
2325 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2326 do_pending_window_change (0);
2328 else if (INTEGERP (arg
) && XINT (arg
) > 0
2329 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2331 if (XFASTINT (arg
) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
2332 XSETINT (arg
, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM
+ 1);
2334 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2335 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2336 if (FRAME_X_WINDOW (f
))
2337 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2340 change_frame_size (f
, 0, FRAME_WIDTH (f
), 0, 0, 0);
2341 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.hpos
= 0;
2342 XWINDOW (FRAME_SELECTED_WINDOW (f
))->cursor
.x
= 0;
2347 /* Subroutines of creating an X frame. */
2349 /* Make sure that Vx_resource_name is set to a reasonable value.
2350 Fix it up, or set it to `emacs' if it is too hopeless. */
2353 validate_x_resource_name ()
2356 /* Number of valid characters in the resource name. */
2358 /* Number of invalid characters in the resource name. */
2363 if (!STRINGP (Vx_resource_class
))
2364 Vx_resource_class
= build_string (EMACS_CLASS
);
2366 if (STRINGP (Vx_resource_name
))
2368 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2371 len
= STRING_BYTES (XSTRING (Vx_resource_name
));
2373 /* Only letters, digits, - and _ are valid in resource names.
2374 Count the valid characters and count the invalid ones. */
2375 for (i
= 0; i
< len
; i
++)
2378 if (! ((c
>= 'a' && c
<= 'z')
2379 || (c
>= 'A' && c
<= 'Z')
2380 || (c
>= '0' && c
<= '9')
2381 || c
== '-' || c
== '_'))
2388 /* Not a string => completely invalid. */
2389 bad_count
= 5, good_count
= 0;
2391 /* If name is valid already, return. */
2395 /* If name is entirely invalid, or nearly so, use `emacs'. */
2397 || (good_count
== 1 && bad_count
> 0))
2399 Vx_resource_name
= build_string ("emacs");
2403 /* Name is partly valid. Copy it and replace the invalid characters
2404 with underscores. */
2406 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2408 for (i
= 0; i
< len
; i
++)
2410 int c
= XSTRING (new)->data
[i
];
2411 if (! ((c
>= 'a' && c
<= 'z')
2412 || (c
>= 'A' && c
<= 'Z')
2413 || (c
>= '0' && c
<= '9')
2414 || c
== '-' || c
== '_'))
2415 XSTRING (new)->data
[i
] = '_';
2420 extern char *x_get_string_resource ();
2422 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2423 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2424 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2425 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2426 the name specified by the `-name' or `-rn' command-line arguments.\n\
2428 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2429 class, respectively. You must specify both of them or neither.\n\
2430 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2431 and the class is `Emacs.CLASS.SUBCLASS'.")
2432 (attribute
, class, component
, subclass
)
2433 Lisp_Object attribute
, class, component
, subclass
;
2435 register char *value
;
2441 CHECK_STRING (attribute
, 0);
2442 CHECK_STRING (class, 0);
2444 if (!NILP (component
))
2445 CHECK_STRING (component
, 1);
2446 if (!NILP (subclass
))
2447 CHECK_STRING (subclass
, 2);
2448 if (NILP (component
) != NILP (subclass
))
2449 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2451 validate_x_resource_name ();
2453 /* Allocate space for the components, the dots which separate them,
2454 and the final '\0'. Make them big enough for the worst case. */
2455 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2456 + (STRINGP (component
)
2457 ? STRING_BYTES (XSTRING (component
)) : 0)
2458 + STRING_BYTES (XSTRING (attribute
))
2461 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2462 + STRING_BYTES (XSTRING (class))
2463 + (STRINGP (subclass
)
2464 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2467 /* Start with emacs.FRAMENAME for the name (the specific one)
2468 and with `Emacs' for the class key (the general one). */
2469 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2470 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2472 strcat (class_key
, ".");
2473 strcat (class_key
, XSTRING (class)->data
);
2475 if (!NILP (component
))
2477 strcat (class_key
, ".");
2478 strcat (class_key
, XSTRING (subclass
)->data
);
2480 strcat (name_key
, ".");
2481 strcat (name_key
, XSTRING (component
)->data
);
2484 strcat (name_key
, ".");
2485 strcat (name_key
, XSTRING (attribute
)->data
);
2487 value
= x_get_string_resource (check_x_display_info (Qnil
)->xrdb
,
2488 name_key
, class_key
);
2490 if (value
!= (char *) 0)
2491 return build_string (value
);
2496 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2499 display_x_get_resource (dpyinfo
, attribute
, class, component
, subclass
)
2500 struct x_display_info
*dpyinfo
;
2501 Lisp_Object attribute
, class, component
, subclass
;
2503 register char *value
;
2509 CHECK_STRING (attribute
, 0);
2510 CHECK_STRING (class, 0);
2512 if (!NILP (component
))
2513 CHECK_STRING (component
, 1);
2514 if (!NILP (subclass
))
2515 CHECK_STRING (subclass
, 2);
2516 if (NILP (component
) != NILP (subclass
))
2517 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2519 validate_x_resource_name ();
2521 /* Allocate space for the components, the dots which separate them,
2522 and the final '\0'. Make them big enough for the worst case. */
2523 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name
))
2524 + (STRINGP (component
)
2525 ? STRING_BYTES (XSTRING (component
)) : 0)
2526 + STRING_BYTES (XSTRING (attribute
))
2529 class_key
= (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class
))
2530 + STRING_BYTES (XSTRING (class))
2531 + (STRINGP (subclass
)
2532 ? STRING_BYTES (XSTRING (subclass
)) : 0)
2535 /* Start with emacs.FRAMENAME for the name (the specific one)
2536 and with `Emacs' for the class key (the general one). */
2537 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2538 strcpy (class_key
, XSTRING (Vx_resource_class
)->data
);
2540 strcat (class_key
, ".");
2541 strcat (class_key
, XSTRING (class)->data
);
2543 if (!NILP (component
))
2545 strcat (class_key
, ".");
2546 strcat (class_key
, XSTRING (subclass
)->data
);
2548 strcat (name_key
, ".");
2549 strcat (name_key
, XSTRING (component
)->data
);
2552 strcat (name_key
, ".");
2553 strcat (name_key
, XSTRING (attribute
)->data
);
2555 value
= x_get_string_resource (dpyinfo
->xrdb
, name_key
, class_key
);
2557 if (value
!= (char *) 0)
2558 return build_string (value
);
2563 /* Used when C code wants a resource value. */
2566 x_get_resource_string (attribute
, class)
2567 char *attribute
, *class;
2571 struct frame
*sf
= SELECTED_FRAME ();
2573 /* Allocate space for the components, the dots which separate them,
2574 and the final '\0'. */
2575 name_key
= (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name
))
2576 + strlen (attribute
) + 2);
2577 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2578 + strlen (class) + 2);
2580 sprintf (name_key
, "%s.%s",
2581 XSTRING (Vinvocation_name
)->data
,
2583 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2585 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf
)->xrdb
,
2586 name_key
, class_key
);
2589 /* Types we might convert a resource string into. */
2599 /* Return the value of parameter PARAM.
2601 First search ALIST, then Vdefault_frame_alist, then the X defaults
2602 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2604 Convert the resource to the type specified by desired_type.
2606 If no default is specified, return Qunbound. If you call
2607 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2608 and don't let it get stored in any Lisp-visible variables! */
2611 x_get_arg (dpyinfo
, alist
, param
, attribute
, class, type
)
2612 struct x_display_info
*dpyinfo
;
2613 Lisp_Object alist
, param
;
2616 enum resource_types type
;
2618 register Lisp_Object tem
;
2620 tem
= Fassq (param
, alist
);
2622 tem
= Fassq (param
, Vdefault_frame_alist
);
2628 tem
= display_x_get_resource (dpyinfo
,
2629 build_string (attribute
),
2630 build_string (class),
2638 case RES_TYPE_NUMBER
:
2639 return make_number (atoi (XSTRING (tem
)->data
));
2641 case RES_TYPE_FLOAT
:
2642 return make_float (atof (XSTRING (tem
)->data
));
2644 case RES_TYPE_BOOLEAN
:
2645 tem
= Fdowncase (tem
);
2646 if (!strcmp (XSTRING (tem
)->data
, "on")
2647 || !strcmp (XSTRING (tem
)->data
, "true"))
2652 case RES_TYPE_STRING
:
2655 case RES_TYPE_SYMBOL
:
2656 /* As a special case, we map the values `true' and `on'
2657 to Qt, and `false' and `off' to Qnil. */
2660 lower
= Fdowncase (tem
);
2661 if (!strcmp (XSTRING (lower
)->data
, "on")
2662 || !strcmp (XSTRING (lower
)->data
, "true"))
2664 else if (!strcmp (XSTRING (lower
)->data
, "off")
2665 || !strcmp (XSTRING (lower
)->data
, "false"))
2668 return Fintern (tem
, Qnil
);
2681 /* Like x_get_arg, but also record the value in f->param_alist. */
2684 x_get_and_record_arg (f
, alist
, param
, attribute
, class, type
)
2686 Lisp_Object alist
, param
;
2689 enum resource_types type
;
2693 value
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, param
,
2694 attribute
, class, type
);
2696 store_frame_param (f
, param
, value
);
2701 /* Record in frame F the specified or default value according to ALIST
2702 of the parameter named PROP (a Lisp symbol).
2703 If no value is specified for PROP, look for an X default for XPROP
2704 on the frame named NAME.
2705 If that is not found either, use the value DEFLT. */
2708 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2715 enum resource_types type
;
2719 tem
= x_get_arg (FRAME_X_DISPLAY_INFO (f
), alist
, prop
, xprop
, xclass
, type
);
2720 if (EQ (tem
, Qunbound
))
2722 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2727 /* Record in frame F the specified or default value according to ALIST
2728 of the parameter named PROP (a Lisp symbol). If no value is
2729 specified for PROP, look for an X default for XPROP on the frame
2730 named NAME. If that is not found either, use the value DEFLT. */
2733 x_default_scroll_bar_color_parameter (f
, alist
, prop
, xprop
, xclass
,
2742 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2745 tem
= x_get_arg (dpyinfo
, alist
, prop
, xprop
, xclass
, RES_TYPE_STRING
);
2746 if (EQ (tem
, Qunbound
))
2748 #ifdef USE_TOOLKIT_SCROLL_BARS
2750 /* See if an X resource for the scroll bar color has been
2752 tem
= display_x_get_resource (dpyinfo
,
2753 build_string (foreground_p
2757 build_string ("verticalScrollBar"),
2761 /* If nothing has been specified, scroll bars will use a
2762 toolkit-dependent default. Because these defaults are
2763 difficult to get at without actually creating a scroll
2764 bar, use nil to indicate that no color has been
2769 #else /* not USE_TOOLKIT_SCROLL_BARS */
2773 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2776 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2782 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2783 "Parse an X-style geometry string STRING.\n\
2784 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2785 The properties returned may include `top', `left', `height', and `width'.\n\
2786 The value of `left' or `top' may be an integer,\n\
2787 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2788 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2793 unsigned int width
, height
;
2796 CHECK_STRING (string
, 0);
2798 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2799 &x
, &y
, &width
, &height
);
2802 if (!!(geometry
& XValue
) != !!(geometry
& YValue
))
2803 error ("Must specify both x and y position, or neither");
2807 if (geometry
& XValue
)
2809 Lisp_Object element
;
2811 if (x
>= 0 && (geometry
& XNegative
))
2812 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2813 else if (x
< 0 && ! (geometry
& XNegative
))
2814 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2816 element
= Fcons (Qleft
, make_number (x
));
2817 result
= Fcons (element
, result
);
2820 if (geometry
& YValue
)
2822 Lisp_Object element
;
2824 if (y
>= 0 && (geometry
& YNegative
))
2825 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2826 else if (y
< 0 && ! (geometry
& YNegative
))
2827 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2829 element
= Fcons (Qtop
, make_number (y
));
2830 result
= Fcons (element
, result
);
2833 if (geometry
& WidthValue
)
2834 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2835 if (geometry
& HeightValue
)
2836 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2841 /* Calculate the desired size and position of this window,
2842 and return the flags saying which aspects were specified.
2844 This function does not make the coordinates positive. */
2846 #define DEFAULT_ROWS 40
2847 #define DEFAULT_COLS 80
2850 x_figure_window_size (f
, parms
)
2854 register Lisp_Object tem0
, tem1
, tem2
;
2855 long window_prompting
= 0;
2856 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2858 /* Default values if we fall through.
2859 Actually, if that happens we should get
2860 window manager prompting. */
2861 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2862 f
->height
= DEFAULT_ROWS
;
2863 /* Window managers expect that if program-specified
2864 positions are not (0,0), they're intentional, not defaults. */
2865 f
->output_data
.x
->top_pos
= 0;
2866 f
->output_data
.x
->left_pos
= 0;
2868 tem0
= x_get_arg (dpyinfo
, parms
, Qheight
, 0, 0, RES_TYPE_NUMBER
);
2869 tem1
= x_get_arg (dpyinfo
, parms
, Qwidth
, 0, 0, RES_TYPE_NUMBER
);
2870 tem2
= x_get_arg (dpyinfo
, parms
, Quser_size
, 0, 0, RES_TYPE_NUMBER
);
2871 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2873 if (!EQ (tem0
, Qunbound
))
2875 CHECK_NUMBER (tem0
, 0);
2876 f
->height
= XINT (tem0
);
2878 if (!EQ (tem1
, Qunbound
))
2880 CHECK_NUMBER (tem1
, 0);
2881 SET_FRAME_WIDTH (f
, XINT (tem1
));
2883 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2884 window_prompting
|= USSize
;
2886 window_prompting
|= PSize
;
2889 f
->output_data
.x
->vertical_scroll_bar_extra
2890 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2892 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
2893 f
->output_data
.x
->flags_areas_extra
2894 = FRAME_FLAGS_AREA_WIDTH (f
);
2895 f
->output_data
.x
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2896 f
->output_data
.x
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2898 tem0
= x_get_arg (dpyinfo
, parms
, Qtop
, 0, 0, RES_TYPE_NUMBER
);
2899 tem1
= x_get_arg (dpyinfo
, parms
, Qleft
, 0, 0, RES_TYPE_NUMBER
);
2900 tem2
= x_get_arg (dpyinfo
, parms
, Quser_position
, 0, 0, RES_TYPE_NUMBER
);
2901 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2903 if (EQ (tem0
, Qminus
))
2905 f
->output_data
.x
->top_pos
= 0;
2906 window_prompting
|= YNegative
;
2908 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qminus
)
2909 && CONSP (XCDR (tem0
))
2910 && INTEGERP (XCAR (XCDR (tem0
))))
2912 f
->output_data
.x
->top_pos
= - XINT (XCAR (XCDR (tem0
)));
2913 window_prompting
|= YNegative
;
2915 else if (CONSP (tem0
) && EQ (XCAR (tem0
), Qplus
)
2916 && CONSP (XCDR (tem0
))
2917 && INTEGERP (XCAR (XCDR (tem0
))))
2919 f
->output_data
.x
->top_pos
= XINT (XCAR (XCDR (tem0
)));
2921 else if (EQ (tem0
, Qunbound
))
2922 f
->output_data
.x
->top_pos
= 0;
2925 CHECK_NUMBER (tem0
, 0);
2926 f
->output_data
.x
->top_pos
= XINT (tem0
);
2927 if (f
->output_data
.x
->top_pos
< 0)
2928 window_prompting
|= YNegative
;
2931 if (EQ (tem1
, Qminus
))
2933 f
->output_data
.x
->left_pos
= 0;
2934 window_prompting
|= XNegative
;
2936 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qminus
)
2937 && CONSP (XCDR (tem1
))
2938 && INTEGERP (XCAR (XCDR (tem1
))))
2940 f
->output_data
.x
->left_pos
= - XINT (XCAR (XCDR (tem1
)));
2941 window_prompting
|= XNegative
;
2943 else if (CONSP (tem1
) && EQ (XCAR (tem1
), Qplus
)
2944 && CONSP (XCDR (tem1
))
2945 && INTEGERP (XCAR (XCDR (tem1
))))
2947 f
->output_data
.x
->left_pos
= XINT (XCAR (XCDR (tem1
)));
2949 else if (EQ (tem1
, Qunbound
))
2950 f
->output_data
.x
->left_pos
= 0;
2953 CHECK_NUMBER (tem1
, 0);
2954 f
->output_data
.x
->left_pos
= XINT (tem1
);
2955 if (f
->output_data
.x
->left_pos
< 0)
2956 window_prompting
|= XNegative
;
2959 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2960 window_prompting
|= USPosition
;
2962 window_prompting
|= PPosition
;
2965 return window_prompting
;
2968 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
2971 XSetWMProtocols (dpy
, w
, protocols
, count
)
2978 prop
= XInternAtom (dpy
, "WM_PROTOCOLS", False
);
2979 if (prop
== None
) return False
;
2980 XChangeProperty (dpy
, w
, prop
, XA_ATOM
, 32, PropModeReplace
,
2981 (unsigned char *) protocols
, count
);
2984 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
2986 #ifdef USE_X_TOOLKIT
2988 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2989 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2990 already be present because of the toolkit (Motif adds some of them,
2991 for example, but Xt doesn't). */
2994 hack_wm_protocols (f
, widget
)
2998 Display
*dpy
= XtDisplay (widget
);
2999 Window w
= XtWindow (widget
);
3000 int need_delete
= 1;
3006 Atom type
, *atoms
= 0;
3008 unsigned long nitems
= 0;
3009 unsigned long bytes_after
;
3011 if ((XGetWindowProperty (dpy
, w
,
3012 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3013 (long)0, (long)100, False
, XA_ATOM
,
3014 &type
, &format
, &nitems
, &bytes_after
,
3015 (unsigned char **) &atoms
)
3017 && format
== 32 && type
== XA_ATOM
)
3021 if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
)
3023 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
)
3025 else if (atoms
[nitems
] == FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
)
3028 if (atoms
) XFree ((char *) atoms
);
3034 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3036 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_take_focus
;
3038 props
[count
++] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3040 XChangeProperty (dpy
, w
, FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3041 XA_ATOM
, 32, PropModeAppend
,
3042 (unsigned char *) props
, count
);
3050 /* Support routines for XIC (X Input Context). */
3054 static XFontSet xic_create_xfontset
P_ ((struct frame
*, char *));
3055 static XIMStyle best_xim_style
P_ ((XIMStyles
*, XIMStyles
*));
3058 /* Supported XIM styles, ordered by preferenc. */
3060 static XIMStyle supported_xim_styles
[] =
3062 XIMPreeditPosition
| XIMStatusArea
,
3063 XIMPreeditPosition
| XIMStatusNothing
,
3064 XIMPreeditPosition
| XIMStatusNone
,
3065 XIMPreeditNothing
| XIMStatusArea
,
3066 XIMPreeditNothing
| XIMStatusNothing
,
3067 XIMPreeditNothing
| XIMStatusNone
,
3068 XIMPreeditNone
| XIMStatusArea
,
3069 XIMPreeditNone
| XIMStatusNothing
,
3070 XIMPreeditNone
| XIMStatusNone
,
3075 /* Create an X fontset on frame F with base font name
3079 xic_create_xfontset (f
, base_fontname
)
3081 char *base_fontname
;
3084 char **missing_list
;
3088 xfs
= XCreateFontSet (FRAME_X_DISPLAY (f
),
3089 base_fontname
, &missing_list
,
3090 &missing_count
, &def_string
);
3092 XFreeStringList (missing_list
);
3094 /* No need to free def_string. */
3099 /* Value is the best input style, given user preferences USER (already
3100 checked to be supported by Emacs), and styles supported by the
3101 input method XIM. */
3104 best_xim_style (user
, xim
)
3110 for (i
= 0; i
< user
->count_styles
; ++i
)
3111 for (j
= 0; j
< xim
->count_styles
; ++j
)
3112 if (user
->supported_styles
[i
] == xim
->supported_styles
[j
])
3113 return user
->supported_styles
[i
];
3115 /* Return the default style. */
3116 return XIMPreeditNothing
| XIMStatusNothing
;
3119 /* Create XIC for frame F. */
3122 create_frame_xic (f
)
3125 #ifndef X_I18N_INHIBITED
3128 XFontSet xfs
= NULL
;
3129 static XIMStyle xic_style
;
3134 xim
= FRAME_X_XIM (f
);
3139 XVaNestedList preedit_attr
;
3140 XVaNestedList status_attr
;
3141 char *base_fontname
;
3144 s_area
.x
= 0; s_area
.y
= 0; s_area
.width
= 1; s_area
.height
= 1;
3145 spot
.x
= 0; spot
.y
= 1;
3146 /* Create X fontset. */
3147 fontset
= FRAME_FONTSET (f
);
3149 base_fontname
= "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3152 struct fontset_info
*fontsetp
;
3156 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
3157 for (i
= 0; i
<= MAX_CHARSET
; i
++)
3158 if (fontsetp
->fontname
[i
])
3159 len
+= strlen (fontsetp
->fontname
[i
]) + 1;
3160 base_fontname
= alloca (len
);
3161 strcpy (base_fontname
, fontsetp
->fontname
[CHARSET_ASCII
]);
3162 for (i
= MIN_CHARSET_OFFICIAL_DIMENSION1
; i
<= MAX_CHARSET
; i
++)
3163 if (fontsetp
->fontname
[i
])
3165 strcat (base_fontname
, ",");
3166 strcat (base_fontname
, fontsetp
->fontname
[i
]);
3169 xfs
= xic_create_xfontset (f
, base_fontname
);
3171 /* Determine XIC style. */
3174 XIMStyles supported_list
;
3175 supported_list
.count_styles
= (sizeof supported_xim_styles
3176 / sizeof supported_xim_styles
[0]);
3177 supported_list
.supported_styles
= supported_xim_styles
;
3178 xic_style
= best_xim_style (&supported_list
,
3179 FRAME_X_XIM_STYLES (f
));
3182 preedit_attr
= XVaCreateNestedList (0,
3185 FRAME_FOREGROUND_PIXEL (f
),
3187 FRAME_BACKGROUND_PIXEL (f
),
3188 (xic_style
& XIMPreeditPosition
3193 status_attr
= XVaCreateNestedList (0,
3199 FRAME_FOREGROUND_PIXEL (f
),
3201 FRAME_BACKGROUND_PIXEL (f
),
3204 xic
= XCreateIC (xim
,
3205 XNInputStyle
, xic_style
,
3206 XNClientWindow
, FRAME_X_WINDOW(f
),
3207 XNFocusWindow
, FRAME_X_WINDOW(f
),
3208 XNStatusAttributes
, status_attr
,
3209 XNPreeditAttributes
, preedit_attr
,
3211 XFree (preedit_attr
);
3212 XFree (status_attr
);
3215 FRAME_XIC (f
) = xic
;
3216 FRAME_XIC_STYLE (f
) = xic_style
;
3217 FRAME_XIC_FONTSET (f
) = xfs
;
3218 #else /* X_I18N_INHIBITED */
3219 FRAME_XIC (f
) = NULL
;
3220 FRAME_XIC_STYLE (f
) = 0;
3221 FRAME_XIC_FONTSET (f
) = NULL
;
3222 #endif /* X_I18N_INHIBITED */
3226 /* Destroy XIC and free XIC fontset of frame F, if any. */
3232 if (FRAME_XIC (f
) == NULL
)
3235 XDestroyIC (FRAME_XIC (f
));
3236 if (FRAME_XIC_FONTSET (f
))
3237 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3239 FRAME_XIC (f
) = NULL
;
3240 FRAME_XIC_FONTSET (f
) = NULL
;
3244 /* Place preedit area for XIC of window W's frame to specified
3245 pixel position X/Y. X and Y are relative to window W. */
3248 xic_set_preeditarea (w
, x
, y
)
3252 struct frame
*f
= XFRAME (w
->frame
);
3256 spot
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, x
);
3257 spot
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, y
) + FONT_BASE (FRAME_FONT (f
));
3258 attr
= XVaCreateNestedList (0, XNSpotLocation
, &spot
, NULL
);
3259 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3264 /* Place status area for XIC in bottom right corner of frame F.. */
3267 xic_set_statusarea (f
)
3270 XIC xic
= FRAME_XIC (f
);
3275 /* Negotiate geometry of status area. If input method has existing
3276 status area, use its current size. */
3277 area
.x
= area
.y
= area
.width
= area
.height
= 0;
3278 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &area
, NULL
);
3279 XSetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3282 attr
= XVaCreateNestedList (0, XNAreaNeeded
, &needed
, NULL
);
3283 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3286 if (needed
->width
== 0) /* Use XNArea instead of XNAreaNeeded */
3288 attr
= XVaCreateNestedList (0, XNArea
, &needed
, NULL
);
3289 XGetICValues (xic
, XNStatusAttributes
, attr
, NULL
);
3293 area
.width
= needed
->width
;
3294 area
.height
= needed
->height
;
3295 area
.x
= PIXEL_WIDTH (f
) - area
.width
- FRAME_INTERNAL_BORDER_WIDTH (f
);
3296 area
.y
= (PIXEL_HEIGHT (f
) - area
.height
3297 - FRAME_MENUBAR_HEIGHT (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
));
3300 attr
= XVaCreateNestedList (0, XNArea
, &area
, NULL
);
3301 XSetICValues(xic
, XNStatusAttributes
, attr
, NULL
);
3306 /* Set X fontset for XIC of frame F, using base font name
3307 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3310 xic_set_xfontset (f
, base_fontname
)
3312 char *base_fontname
;
3317 xfs
= xic_create_xfontset (f
, base_fontname
);
3319 attr
= XVaCreateNestedList (0, XNFontSet
, xfs
, NULL
);
3320 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
3321 XSetICValues (FRAME_XIC (f
), XNPreeditAttributes
, attr
, NULL
);
3322 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
3323 XSetICValues (FRAME_XIC (f
), XNStatusAttributes
, attr
, NULL
);
3326 if (FRAME_XIC_FONTSET (f
))
3327 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
3328 FRAME_XIC_FONTSET (f
) = xfs
;
3331 #endif /* HAVE_X_I18N */
3335 #ifdef USE_X_TOOLKIT
3337 /* Create and set up the X widget for frame F. */
3340 x_window (f
, window_prompting
, minibuffer_only
)
3342 long window_prompting
;
3343 int minibuffer_only
;
3345 XClassHint class_hints
;
3346 XSetWindowAttributes attributes
;
3347 unsigned long attribute_mask
;
3349 Widget shell_widget
;
3351 Widget frame_widget
;
3357 /* Use the resource name as the top-level widget name
3358 for looking up resources. Make a non-Lisp copy
3359 for the window manager, so GC relocation won't bother it.
3361 Elsewhere we specify the window name for the window manager. */
3364 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3365 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3366 strcpy (f
->namebuf
, str
);
3370 XtSetArg (al
[ac
], XtNallowShellResize
, 1); ac
++;
3371 XtSetArg (al
[ac
], XtNinput
, 1); ac
++;
3372 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3373 XtSetArg (al
[ac
], XtNborderWidth
, f
->output_data
.x
->border_width
); ac
++;
3374 shell_widget
= XtAppCreateShell (f
->namebuf
, EMACS_CLASS
,
3375 applicationShellWidgetClass
,
3376 FRAME_X_DISPLAY (f
), al
, ac
);
3378 f
->output_data
.x
->widget
= shell_widget
;
3379 /* maybe_set_screen_title_format (shell_widget); */
3381 pane_widget
= lw_create_widget ("main", "pane", widget_id_tick
++,
3382 (widget_value
*) NULL
,
3383 shell_widget
, False
,
3387 (lw_callback
) NULL
);
3389 f
->output_data
.x
->column_widget
= pane_widget
;
3391 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3392 the emacs screen when changing menubar. This reduces flickering. */
3395 XtSetArg (al
[ac
], XtNmappedWhenManaged
, 0); ac
++;
3396 XtSetArg (al
[ac
], XtNshowGrip
, 0); ac
++;
3397 XtSetArg (al
[ac
], XtNallowResize
, 1); ac
++;
3398 XtSetArg (al
[ac
], XtNresizeToPreferred
, 1); ac
++;
3399 XtSetArg (al
[ac
], XtNemacsFrame
, f
); ac
++;
3400 frame_widget
= XtCreateWidget (f
->namebuf
,
3402 pane_widget
, al
, ac
);
3404 f
->output_data
.x
->edit_widget
= frame_widget
;
3406 XtManageChild (frame_widget
);
3408 /* Do some needed geometry management. */
3411 char *tem
, shell_position
[32];
3414 int extra_borders
= 0;
3416 = (f
->output_data
.x
->menubar_widget
3417 ? (f
->output_data
.x
->menubar_widget
->core
.height
3418 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
3421 #if 0 /* Experimentally, we now get the right results
3422 for -geometry -0-0 without this. 24 Aug 96, rms. */
3423 if (FRAME_EXTERNAL_MENU_BAR (f
))
3426 XtVaGetValues (pane_widget
, XtNinternalBorderWidth
, &ibw
, NULL
);
3427 menubar_size
+= ibw
;
3431 f
->output_data
.x
->menubar_height
= menubar_size
;
3434 /* Motif seems to need this amount added to the sizes
3435 specified for the shell widget. The Athena/Lucid widgets don't.
3436 Both conclusions reached experimentally. -- rms. */
3437 XtVaGetValues (f
->output_data
.x
->edit_widget
, XtNinternalBorderWidth
,
3438 &extra_borders
, NULL
);
3442 /* Convert our geometry parameters into a geometry string
3444 Note that we do not specify here whether the position
3445 is a user-specified or program-specified one.
3446 We pass that information later, in x_wm_set_size_hints. */
3448 int left
= f
->output_data
.x
->left_pos
;
3449 int xneg
= window_prompting
& XNegative
;
3450 int top
= f
->output_data
.x
->top_pos
;
3451 int yneg
= window_prompting
& YNegative
;
3457 if (window_prompting
& USPosition
)
3458 sprintf (shell_position
, "=%dx%d%c%d%c%d",
3459 PIXEL_WIDTH (f
) + extra_borders
,
3460 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
,
3461 (xneg
? '-' : '+'), left
,
3462 (yneg
? '-' : '+'), top
);
3464 sprintf (shell_position
, "=%dx%d",
3465 PIXEL_WIDTH (f
) + extra_borders
,
3466 PIXEL_HEIGHT (f
) + menubar_size
+ extra_borders
);
3469 len
= strlen (shell_position
) + 1;
3470 /* We don't free this because we don't know whether
3471 it is safe to free it while the frame exists.
3472 It isn't worth the trouble of arranging to free it
3473 when the frame is deleted. */
3474 tem
= (char *) xmalloc (len
);
3475 strncpy (tem
, shell_position
, len
);
3476 XtSetArg (al
[ac
], XtNgeometry
, tem
); ac
++;
3477 XtSetValues (shell_widget
, al
, ac
);
3480 XtManageChild (pane_widget
);
3481 XtRealizeWidget (shell_widget
);
3483 FRAME_X_WINDOW (f
) = XtWindow (frame_widget
);
3485 validate_x_resource_name ();
3487 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3488 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3489 XSetClassHint (FRAME_X_DISPLAY (f
), XtWindow (shell_widget
), &class_hints
);
3492 FRAME_XIC (f
) = NULL
;
3493 create_frame_xic (f
);
3496 f
->output_data
.x
->wm_hints
.input
= True
;
3497 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3498 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3499 &f
->output_data
.x
->wm_hints
);
3501 hack_wm_protocols (f
, shell_widget
);
3504 XtAddEventHandler (shell_widget
, 0, True
, _XEditResCheckMessages
, 0);
3507 /* Do a stupid property change to force the server to generate a
3508 PropertyNotify event so that the event_stream server timestamp will
3509 be initialized to something relevant to the time we created the window.
3511 XChangeProperty (XtDisplay (frame_widget
), XtWindow (frame_widget
),
3512 FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_protocols
,
3513 XA_ATOM
, 32, PropModeAppend
,
3514 (unsigned char*) NULL
, 0);
3516 /* Make all the standard events reach the Emacs frame. */
3517 attributes
.event_mask
= STANDARD_EVENT_SET
;
3522 /* XIM server might require some X events. */
3523 unsigned long fevent
= NoEventMask
;
3524 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3525 attributes
.event_mask
|= fevent
;
3527 #endif /* HAVE_X_I18N */
3529 attribute_mask
= CWEventMask
;
3530 XChangeWindowAttributes (XtDisplay (shell_widget
), XtWindow (shell_widget
),
3531 attribute_mask
, &attributes
);
3533 XtMapWidget (frame_widget
);
3535 /* x_set_name normally ignores requests to set the name if the
3536 requested name is the same as the current name. This is the one
3537 place where that assumption isn't correct; f->name is set, but
3538 the X server hasn't been told. */
3541 int explicit = f
->explicit_name
;
3543 f
->explicit_name
= 0;
3546 x_set_name (f
, name
, explicit);
3549 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3550 f
->output_data
.x
->text_cursor
);
3554 /* This is a no-op, except under Motif. Make sure main areas are
3555 set to something reasonable, in case we get an error later. */
3556 lw_set_main_areas (pane_widget
, 0, frame_widget
);
3559 #else /* not USE_X_TOOLKIT */
3561 /* Create and set up the X window for frame F. */
3568 XClassHint class_hints
;
3569 XSetWindowAttributes attributes
;
3570 unsigned long attribute_mask
;
3572 attributes
.background_pixel
= f
->output_data
.x
->background_pixel
;
3573 attributes
.border_pixel
= f
->output_data
.x
->border_pixel
;
3574 attributes
.bit_gravity
= StaticGravity
;
3575 attributes
.backing_store
= NotUseful
;
3576 attributes
.save_under
= True
;
3577 attributes
.event_mask
= STANDARD_EVENT_SET
;
3578 attribute_mask
= (CWBackPixel
| CWBorderPixel
| CWBitGravity
3580 | CWBackingStore
| CWSaveUnder
3586 = XCreateWindow (FRAME_X_DISPLAY (f
),
3587 f
->output_data
.x
->parent_desc
,
3588 f
->output_data
.x
->left_pos
,
3589 f
->output_data
.x
->top_pos
,
3590 PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
),
3591 f
->output_data
.x
->border_width
,
3592 CopyFromParent
, /* depth */
3593 InputOutput
, /* class */
3594 FRAME_X_DISPLAY_INFO (f
)->visual
,
3595 attribute_mask
, &attributes
);
3598 create_frame_xic (f
);
3601 /* XIM server might require some X events. */
3602 unsigned long fevent
= NoEventMask
;
3603 XGetICValues(FRAME_XIC (f
), XNFilterEvents
, &fevent
, NULL
);
3604 attributes
.event_mask
|= fevent
;
3605 attribute_mask
= CWEventMask
;
3606 XChangeWindowAttributes (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3607 attribute_mask
, &attributes
);
3609 #endif /* HAVE_X_I18N */
3611 validate_x_resource_name ();
3613 class_hints
.res_name
= (char *) XSTRING (Vx_resource_name
)->data
;
3614 class_hints
.res_class
= (char *) XSTRING (Vx_resource_class
)->data
;
3615 XSetClassHint (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &class_hints
);
3617 /* The menubar is part of the ordinary display;
3618 it does not count in addition to the height of the window. */
3619 f
->output_data
.x
->menubar_height
= 0;
3621 /* This indicates that we use the "Passive Input" input model.
3622 Unless we do this, we don't get the Focus{In,Out} events that we
3623 need to draw the cursor correctly. Accursed bureaucrats.
3624 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3626 f
->output_data
.x
->wm_hints
.input
= True
;
3627 f
->output_data
.x
->wm_hints
.flags
|= InputHint
;
3628 XSetWMHints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3629 &f
->output_data
.x
->wm_hints
);
3630 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
3632 /* Request "save yourself" and "delete window" commands from wm. */
3635 protocols
[0] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_delete_window
;
3636 protocols
[1] = FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_save_yourself
;
3637 XSetWMProtocols (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), protocols
, 2);
3640 /* x_set_name normally ignores requests to set the name if the
3641 requested name is the same as the current name. This is the one
3642 place where that assumption isn't correct; f->name is set, but
3643 the X server hasn't been told. */
3646 int explicit = f
->explicit_name
;
3648 f
->explicit_name
= 0;
3651 x_set_name (f
, name
, explicit);
3654 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3655 f
->output_data
.x
->text_cursor
);
3659 if (FRAME_X_WINDOW (f
) == 0)
3660 error ("Unable to create window");
3663 #endif /* not USE_X_TOOLKIT */
3665 /* Handle the icon stuff for this window. Perhaps later we might
3666 want an x_set_icon_position which can be called interactively as
3674 Lisp_Object icon_x
, icon_y
;
3675 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3677 /* Set the position of the icon. Note that twm groups all
3678 icons in an icon window. */
3679 icon_x
= x_get_and_record_arg (f
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
3680 icon_y
= x_get_and_record_arg (f
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
3681 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
3683 CHECK_NUMBER (icon_x
, 0);
3684 CHECK_NUMBER (icon_y
, 0);
3686 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
3687 error ("Both left and top icon corners of icon must be specified");
3691 if (! EQ (icon_x
, Qunbound
))
3692 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
3694 /* Start up iconic or window? */
3695 x_wm_set_window_state
3696 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
),
3701 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
3708 /* Make the GC's needed for this window, setting the
3709 background, border and mouse colors; also create the
3710 mouse cursor and the gray border tile. */
3712 static char cursor_bits
[] =
3714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3724 XGCValues gc_values
;
3728 /* Create the GC's of this frame.
3729 Note that many default values are used. */
3732 gc_values
.font
= f
->output_data
.x
->font
->fid
;
3733 gc_values
.foreground
= f
->output_data
.x
->foreground_pixel
;
3734 gc_values
.background
= f
->output_data
.x
->background_pixel
;
3735 gc_values
.line_width
= 0; /* Means 1 using fast algorithm. */
3736 f
->output_data
.x
->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3738 GCLineWidth
| GCFont
3739 | GCForeground
| GCBackground
,
3742 /* Reverse video style. */
3743 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3744 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
3745 f
->output_data
.x
->reverse_gc
= XCreateGC (FRAME_X_DISPLAY (f
),
3747 GCFont
| GCForeground
| GCBackground
3751 /* Cursor has cursor-color background, background-color foreground. */
3752 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
3753 gc_values
.background
= f
->output_data
.x
->cursor_pixel
;
3754 gc_values
.fill_style
= FillOpaqueStippled
;
3756 = XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
3757 FRAME_X_DISPLAY_INFO (f
)->root_window
,
3758 cursor_bits
, 16, 16);
3759 f
->output_data
.x
->cursor_gc
3760 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3761 (GCFont
| GCForeground
| GCBackground
3762 | GCFillStyle
/* | GCStipple */ | GCLineWidth
),
3766 f
->output_data
.x
->white_relief
.gc
= 0;
3767 f
->output_data
.x
->black_relief
.gc
= 0;
3769 /* Create the gray border tile used when the pointer is not in
3770 the frame. Since this depends on the frame's pixel values,
3771 this must be done on a per-frame basis. */
3772 f
->output_data
.x
->border_tile
3773 = (XCreatePixmapFromBitmapData
3774 (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
3775 gray_bits
, gray_width
, gray_height
,
3776 f
->output_data
.x
->foreground_pixel
,
3777 f
->output_data
.x
->background_pixel
,
3778 DefaultDepth (FRAME_X_DISPLAY (f
),
3779 XScreenNumberOfScreen (FRAME_X_SCREEN (f
)))));
3784 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
3786 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3787 Returns an Emacs frame object.\n\
3788 ALIST is an alist of frame parameters.\n\
3789 If the parameters specify that the frame should not have a minibuffer,\n\
3790 and do not specify a specific minibuffer window to use,\n\
3791 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3792 be shared by the new frame.\n\
3794 This function is an internal primitive--use `make-frame' instead.")
3799 Lisp_Object frame
, tem
;
3801 int minibuffer_only
= 0;
3802 long window_prompting
= 0;
3804 int count
= specpdl_ptr
- specpdl
;
3805 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3806 Lisp_Object display
;
3807 struct x_display_info
*dpyinfo
= NULL
;
3813 /* Use this general default value to start with
3814 until we know if this frame has a specified name. */
3815 Vx_resource_name
= Vinvocation_name
;
3817 display
= x_get_arg (dpyinfo
, parms
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
3818 if (EQ (display
, Qunbound
))
3820 dpyinfo
= check_x_display_info (display
);
3822 kb
= dpyinfo
->kboard
;
3824 kb
= &the_only_kboard
;
3827 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
3829 && ! EQ (name
, Qunbound
)
3831 error ("Invalid frame name--not a string or nil");
3834 Vx_resource_name
= name
;
3836 /* See if parent window is specified. */
3837 parent
= x_get_arg (dpyinfo
, parms
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
3838 if (EQ (parent
, Qunbound
))
3840 if (! NILP (parent
))
3841 CHECK_NUMBER (parent
, 0);
3843 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3844 /* No need to protect DISPLAY because that's not used after passing
3845 it to make_frame_without_minibuffer. */
3847 GCPRO4 (parms
, parent
, name
, frame
);
3848 tem
= x_get_arg (dpyinfo
, parms
, Qminibuffer
, "minibuffer", "Minibuffer",
3850 if (EQ (tem
, Qnone
) || NILP (tem
))
3851 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
3852 else if (EQ (tem
, Qonly
))
3854 f
= make_minibuffer_frame ();
3855 minibuffer_only
= 1;
3857 else if (WINDOWP (tem
))
3858 f
= make_frame_without_minibuffer (tem
, kb
, display
);
3862 XSETFRAME (frame
, f
);
3864 /* Note that X Windows does support scroll bars. */
3865 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
3867 f
->output_method
= output_x_window
;
3868 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
3869 bzero (f
->output_data
.x
, sizeof (struct x_output
));
3870 f
->output_data
.x
->icon_bitmap
= -1;
3871 f
->output_data
.x
->fontset
= -1;
3872 f
->output_data
.x
->scroll_bar_foreground_pixel
= -1;
3873 f
->output_data
.x
->scroll_bar_background_pixel
= -1;
3876 = x_get_arg (dpyinfo
, parms
, Qicon_name
, "iconName", "Title",
3878 if (! STRINGP (f
->icon_name
))
3879 f
->icon_name
= Qnil
;
3881 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
3883 FRAME_KBOARD (f
) = kb
;
3886 /* Specify the parent under which to make this X window. */
3890 f
->output_data
.x
->parent_desc
= (Window
) XFASTINT (parent
);
3891 f
->output_data
.x
->explicit_parent
= 1;
3895 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
3896 f
->output_data
.x
->explicit_parent
= 0;
3899 /* Set the name; the functions to which we pass f expect the name to
3901 if (EQ (name
, Qunbound
) || NILP (name
))
3903 f
->name
= build_string (dpyinfo
->x_id_name
);
3904 f
->explicit_name
= 0;
3909 f
->explicit_name
= 1;
3910 /* use the frame's title when getting resources for this frame. */
3911 specbind (Qx_resource_name
, name
);
3914 /* Create fontsets from `global_fontset_alist' before handling fonts. */
3915 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCDR (tem
))
3916 fs_register_fontset (f
, XCAR (tem
));
3918 /* Extract the window parameters from the supplied values
3919 that are needed to determine window geometry. */
3923 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
3926 /* First, try whatever font the caller has specified. */
3929 tem
= Fquery_fontset (font
, Qnil
);
3931 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
3933 font
= x_new_font (f
, XSTRING (font
)->data
);
3936 /* Try out a font which we hope has bold and italic variations. */
3937 if (!STRINGP (font
))
3938 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
3939 if (!STRINGP (font
))
3940 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3941 if (! STRINGP (font
))
3942 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
3943 if (! STRINGP (font
))
3944 /* This was formerly the first thing tried, but it finds too many fonts
3945 and takes too long. */
3946 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
3947 /* If those didn't work, look for something which will at least work. */
3948 if (! STRINGP (font
))
3949 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
3951 if (! STRINGP (font
))
3952 font
= build_string ("fixed");
3954 x_default_parameter (f
, parms
, Qfont
, font
,
3955 "font", "Font", RES_TYPE_STRING
);
3959 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
3960 whereby it fails to get any font. */
3961 xlwmenu_default_font
= f
->output_data
.x
->font
;
3964 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
3965 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
3967 /* This defaults to 2 in order to match xterm. We recognize either
3968 internalBorderWidth or internalBorder (which is what xterm calls
3970 if (NILP (Fassq (Qinternal_border_width
, parms
)))
3974 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
3975 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
3976 if (! EQ (value
, Qunbound
))
3977 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
3980 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
3981 "internalBorderWidth", "internalBorderWidth",
3983 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qleft
,
3984 "verticalScrollBars", "ScrollBars",
3987 /* Also do the stuff which must be set before the window exists. */
3988 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
3989 "foreground", "Foreground", RES_TYPE_STRING
);
3990 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
3991 "background", "Background", RES_TYPE_STRING
);
3992 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
3993 "pointerColor", "Foreground", RES_TYPE_STRING
);
3994 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
3995 "cursorColor", "Foreground", RES_TYPE_STRING
);
3996 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
3997 "borderColor", "BorderColor", RES_TYPE_STRING
);
3998 x_default_parameter (f
, parms
, Qscreen_gamma
, Qnil
,
3999 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4001 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_foreground
,
4002 "scrollBarForeground",
4003 "ScrollBarForeground", 1);
4004 x_default_scroll_bar_color_parameter (f
, parms
, Qscroll_bar_background
,
4005 "scrollBarBackground",
4006 "ScrollBarBackground", 0);
4008 /* Init faces before x_default_parameter is called for scroll-bar
4009 parameters because that function calls x_set_scroll_bar_width,
4010 which calls change_frame_size, which calls Fset_window_buffer,
4011 which runs hooks, which call Fvertical_motion. At the end, we
4012 end up in init_iterator with a null face cache, which should not
4014 init_frame_faces (f
);
4016 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4017 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4018 x_default_parameter (f
, parms
, Qtool_bar_lines
, make_number (0),
4019 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4020 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4021 "bufferPredicate", "BufferPredicate",
4023 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4024 "title", "Title", RES_TYPE_STRING
);
4026 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
4027 window_prompting
= x_figure_window_size (f
, parms
);
4029 if (window_prompting
& XNegative
)
4031 if (window_prompting
& YNegative
)
4032 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
4034 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
4038 if (window_prompting
& YNegative
)
4039 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
4041 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4044 f
->output_data
.x
->size_hint_flags
= window_prompting
;
4046 tem
= x_get_arg (dpyinfo
, parms
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4047 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4049 /* Create the X widget or window. Add the tool-bar height to the
4050 initial frame height so that the user gets a text display area of
4051 the size he specified with -g or via .Xdefaults. Later changes
4052 of the tool-bar height don't change the frame size. This is done
4053 so that users can create tall Emacs frames without having to
4054 guess how tall the tool-bar will get. */
4055 f
->height
+= FRAME_TOOL_BAR_LINES (f
);
4057 #ifdef USE_X_TOOLKIT
4058 x_window (f
, window_prompting
, minibuffer_only
);
4066 /* Now consider the frame official. */
4067 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
4068 Vframe_list
= Fcons (frame
, Vframe_list
);
4070 /* We need to do this after creating the X window, so that the
4071 icon-creation functions can say whose icon they're describing. */
4072 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4073 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4075 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4076 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4077 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4078 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4079 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4080 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4081 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4082 "scrollBarWidth", "ScrollBarWidth",
4085 /* Dimensions, especially f->height, must be done via change_frame_size.
4086 Change will not be effected unless different from the current
4091 SET_FRAME_WIDTH (f
, 0);
4092 change_frame_size (f
, height
, width
, 1, 0, 0);
4094 /* Set up faces after all frame parameters are known. */
4095 call1 (Qface_set_after_frame_default
, frame
);
4097 #ifdef USE_X_TOOLKIT
4098 /* Create the menu bar. */
4099 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4101 /* If this signals an error, we haven't set size hints for the
4102 frame and we didn't make it visible. */
4103 initialize_frame_menubar (f
);
4105 /* This is a no-op, except under Motif where it arranges the
4106 main window for the widgets on it. */
4107 lw_set_main_areas (f
->output_data
.x
->column_widget
,
4108 f
->output_data
.x
->menubar_widget
,
4109 f
->output_data
.x
->edit_widget
);
4111 #endif /* USE_X_TOOLKIT */
4113 /* Tell the server what size and position, etc, we want, and how
4114 badly we want them. This should be done after we have the menu
4115 bar so that its size can be taken into account. */
4117 x_wm_set_size_hint (f
, window_prompting
, 0);
4120 /* Make the window appear on the frame and enable display, unless
4121 the caller says not to. However, with explicit parent, Emacs
4122 cannot control visibility, so don't try. */
4123 if (! f
->output_data
.x
->explicit_parent
)
4125 Lisp_Object visibility
;
4127 visibility
= x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0,
4129 if (EQ (visibility
, Qunbound
))
4132 if (EQ (visibility
, Qicon
))
4133 x_iconify_frame (f
);
4134 else if (! NILP (visibility
))
4135 x_make_frame_visible (f
);
4137 /* Must have been Qnil. */
4142 return unbind_to (count
, frame
);
4145 /* FRAME is used only to get a handle on the X display. We don't pass the
4146 display info directly because we're called from frame.c, which doesn't
4147 know about that structure. */
4150 x_get_focus_frame (frame
)
4151 struct frame
*frame
;
4153 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (frame
);
4155 if (! dpyinfo
->x_focus_frame
)
4158 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
4163 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4164 "Internal function called by `color-defined-p', which see.")
4166 Lisp_Object color
, frame
;
4169 FRAME_PTR f
= check_x_frame (frame
);
4171 CHECK_STRING (color
, 1);
4173 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4179 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4180 "Internal function called by `color-values', which see.")
4182 Lisp_Object color
, frame
;
4185 FRAME_PTR f
= check_x_frame (frame
);
4187 CHECK_STRING (color
, 1);
4189 if (x_defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
4193 rgb
[0] = make_number (foo
.red
);
4194 rgb
[1] = make_number (foo
.green
);
4195 rgb
[2] = make_number (foo
.blue
);
4196 return Flist (3, rgb
);
4202 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4203 "Internal function called by `display-color-p', which see.")
4205 Lisp_Object display
;
4207 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4209 if (dpyinfo
->n_planes
<= 2)
4212 switch (dpyinfo
->visual
->class)
4225 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
4227 "Return t if the X display supports shades of gray.\n\
4228 Note that color displays do support shades of gray.\n\
4229 The optional argument DISPLAY specifies which display to ask about.\n\
4230 DISPLAY should be either a frame or a display name (a string).\n\
4231 If omitted or nil, that stands for the selected frame's display.")
4233 Lisp_Object display
;
4235 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4237 if (dpyinfo
->n_planes
<= 1)
4240 switch (dpyinfo
->visual
->class)
4255 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
4257 "Returns the width in pixels of the X display DISPLAY.\n\
4258 The optional argument DISPLAY specifies which display to ask about.\n\
4259 DISPLAY should be either a frame or a display name (a string).\n\
4260 If omitted or nil, that stands for the selected frame's display.")
4262 Lisp_Object display
;
4264 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4266 return make_number (dpyinfo
->width
);
4269 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4270 Sx_display_pixel_height
, 0, 1, 0,
4271 "Returns the height in pixels of the X display DISPLAY.\n\
4272 The optional argument DISPLAY specifies which display to ask about.\n\
4273 DISPLAY should be either a frame or a display name (a string).\n\
4274 If omitted or nil, that stands for the selected frame's display.")
4276 Lisp_Object display
;
4278 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4280 return make_number (dpyinfo
->height
);
4283 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4285 "Returns the number of bitplanes of the X display DISPLAY.\n\
4286 The optional argument DISPLAY specifies which display to ask about.\n\
4287 DISPLAY should be either a frame or a display name (a string).\n\
4288 If omitted or nil, that stands for the selected frame's display.")
4290 Lisp_Object display
;
4292 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4294 return make_number (dpyinfo
->n_planes
);
4297 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4299 "Returns the number of color cells of the X display DISPLAY.\n\
4300 The optional argument DISPLAY specifies which display to ask about.\n\
4301 DISPLAY should be either a frame or a display name (a string).\n\
4302 If omitted or nil, that stands for the selected frame's display.")
4304 Lisp_Object display
;
4306 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4308 return make_number (DisplayCells (dpyinfo
->display
,
4309 XScreenNumberOfScreen (dpyinfo
->screen
)));
4312 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4313 Sx_server_max_request_size
,
4315 "Returns the maximum request size of the X server of display DISPLAY.\n\
4316 The optional argument DISPLAY specifies which display to ask about.\n\
4317 DISPLAY should be either a frame or a display name (a string).\n\
4318 If omitted or nil, that stands for the selected frame's display.")
4320 Lisp_Object display
;
4322 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4324 return make_number (MAXREQUEST (dpyinfo
->display
));
4327 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4328 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4329 The optional argument DISPLAY specifies which display to ask about.\n\
4330 DISPLAY should be either a frame or a display name (a string).\n\
4331 If omitted or nil, that stands for the selected frame's display.")
4333 Lisp_Object display
;
4335 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4336 char *vendor
= ServerVendor (dpyinfo
->display
);
4338 if (! vendor
) vendor
= "";
4339 return build_string (vendor
);
4342 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4343 "Returns the version numbers of the X server of display DISPLAY.\n\
4344 The value is a list of three integers: the major and minor\n\
4345 version numbers of the X Protocol in use, and the vendor-specific release\n\
4346 number. See also the function `x-server-vendor'.\n\n\
4347 The optional argument DISPLAY specifies which display to ask about.\n\
4348 DISPLAY should be either a frame or a display name (a string).\n\
4349 If omitted or nil, that stands for the selected frame's display.")
4351 Lisp_Object display
;
4353 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4354 Display
*dpy
= dpyinfo
->display
;
4356 return Fcons (make_number (ProtocolVersion (dpy
)),
4357 Fcons (make_number (ProtocolRevision (dpy
)),
4358 Fcons (make_number (VendorRelease (dpy
)), Qnil
)));
4361 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4362 "Returns the number of screens on the X server of display DISPLAY.\n\
4363 The optional argument DISPLAY specifies which display to ask about.\n\
4364 DISPLAY should be either a frame or a display name (a string).\n\
4365 If omitted or nil, that stands for the selected frame's display.")
4367 Lisp_Object display
;
4369 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4371 return make_number (ScreenCount (dpyinfo
->display
));
4374 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
4375 "Returns the height in millimeters of the X display DISPLAY.\n\
4376 The optional argument DISPLAY specifies which display to ask about.\n\
4377 DISPLAY should be either a frame or a display name (a string).\n\
4378 If omitted or nil, that stands for the selected frame's display.")
4380 Lisp_Object display
;
4382 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4384 return make_number (HeightMMOfScreen (dpyinfo
->screen
));
4387 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4388 "Returns the width in millimeters of the X display DISPLAY.\n\
4389 The optional argument DISPLAY specifies which display to ask about.\n\
4390 DISPLAY should be either a frame or a display name (a string).\n\
4391 If omitted or nil, that stands for the selected frame's display.")
4393 Lisp_Object display
;
4395 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4397 return make_number (WidthMMOfScreen (dpyinfo
->screen
));
4400 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4401 Sx_display_backing_store
, 0, 1, 0,
4402 "Returns an indication of whether X display DISPLAY does backing store.\n\
4403 The value may be `always', `when-mapped', or `not-useful'.\n\
4404 The optional argument DISPLAY specifies which display to ask about.\n\
4405 DISPLAY should be either a frame or a display name (a string).\n\
4406 If omitted or nil, that stands for the selected frame's display.")
4408 Lisp_Object display
;
4410 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4412 switch (DoesBackingStore (dpyinfo
->screen
))
4415 return intern ("always");
4418 return intern ("when-mapped");
4421 return intern ("not-useful");
4424 error ("Strange value for BackingStore parameter of screen");
4428 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4429 Sx_display_visual_class
, 0, 1, 0,
4430 "Returns the visual class of the X display DISPLAY.\n\
4431 The value is one of the symbols `static-gray', `gray-scale',\n\
4432 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4433 The optional argument DISPLAY specifies which display to ask about.\n\
4434 DISPLAY should be either a frame or a display name (a string).\n\
4435 If omitted or nil, that stands for the selected frame's display.")
4437 Lisp_Object display
;
4439 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4441 switch (dpyinfo
->visual
->class)
4443 case StaticGray
: return (intern ("static-gray"));
4444 case GrayScale
: return (intern ("gray-scale"));
4445 case StaticColor
: return (intern ("static-color"));
4446 case PseudoColor
: return (intern ("pseudo-color"));
4447 case TrueColor
: return (intern ("true-color"));
4448 case DirectColor
: return (intern ("direct-color"));
4450 error ("Display has an unknown visual class");
4454 DEFUN ("x-display-save-under", Fx_display_save_under
,
4455 Sx_display_save_under
, 0, 1, 0,
4456 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4457 The optional argument DISPLAY specifies which display to ask about.\n\
4458 DISPLAY should be either a frame or a display name (a string).\n\
4459 If omitted or nil, that stands for the selected frame's display.")
4461 Lisp_Object display
;
4463 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
4465 if (DoesSaveUnders (dpyinfo
->screen
) == True
)
4473 register struct frame
*f
;
4475 return PIXEL_WIDTH (f
);
4480 register struct frame
*f
;
4482 return PIXEL_HEIGHT (f
);
4487 register struct frame
*f
;
4489 return FONT_WIDTH (f
->output_data
.x
->font
);
4494 register struct frame
*f
;
4496 return f
->output_data
.x
->line_height
;
4501 register struct frame
*f
;
4503 return FRAME_X_DISPLAY_INFO (f
)->n_planes
;
4506 #if 0 /* These no longer seem like the right way to do things. */
4508 /* Draw a rectangle on the frame with left top corner including
4509 the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
4510 CHARS by LINES wide and long and is the color of the cursor. */
4513 x_rectangle (f
, gc
, left_char
, top_char
, chars
, lines
)
4514 register struct frame
*f
;
4516 register int top_char
, left_char
, chars
, lines
;
4520 int left
= (left_char
* FONT_WIDTH (f
->output_data
.x
->font
)
4521 + f
->output_data
.x
->internal_border_width
);
4522 int top
= (top_char
* f
->output_data
.x
->line_height
4523 + f
->output_data
.x
->internal_border_width
);
4526 width
= FONT_WIDTH (f
->output_data
.x
->font
) / 2;
4528 width
= FONT_WIDTH (f
->output_data
.x
->font
) * chars
;
4530 height
= f
->output_data
.x
->line_height
/ 2;
4532 height
= f
->output_data
.x
->line_height
* lines
;
4534 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4535 gc
, left
, top
, width
, height
);
4538 DEFUN ("x-draw-rectangle", Fx_draw_rectangle
, Sx_draw_rectangle
, 5, 5, 0,
4539 "Draw a rectangle on FRAME between coordinates specified by\n\
4540 numbers X0, Y0, X1, Y1 in the cursor pixel.")
4541 (frame
, X0
, Y0
, X1
, Y1
)
4542 register Lisp_Object frame
, X0
, X1
, Y0
, Y1
;
4544 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4546 CHECK_LIVE_FRAME (frame
, 0);
4547 CHECK_NUMBER (X0
, 0);
4548 CHECK_NUMBER (Y0
, 1);
4549 CHECK_NUMBER (X1
, 2);
4550 CHECK_NUMBER (Y1
, 3);
4560 n_lines
= y1
- y0
+ 1;
4565 n_lines
= y0
- y1
+ 1;
4571 n_chars
= x1
- x0
+ 1;
4576 n_chars
= x0
- x1
+ 1;
4580 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->cursor_gc
,
4581 left
, top
, n_chars
, n_lines
);
4587 DEFUN ("x-erase-rectangle", Fx_erase_rectangle
, Sx_erase_rectangle
, 5, 5, 0,
4588 "Draw a rectangle drawn on FRAME between coordinates\n\
4589 X0, Y0, X1, Y1 in the regular background-pixel.")
4590 (frame
, X0
, Y0
, X1
, Y1
)
4591 register Lisp_Object frame
, X0
, Y0
, X1
, Y1
;
4593 register int x0
, y0
, x1
, y1
, top
, left
, n_chars
, n_lines
;
4595 CHECK_LIVE_FRAME (frame
, 0);
4596 CHECK_NUMBER (X0
, 0);
4597 CHECK_NUMBER (Y0
, 1);
4598 CHECK_NUMBER (X1
, 2);
4599 CHECK_NUMBER (Y1
, 3);
4609 n_lines
= y1
- y0
+ 1;
4614 n_lines
= y0
- y1
+ 1;
4620 n_chars
= x1
- x0
+ 1;
4625 n_chars
= x0
- x1
+ 1;
4629 x_rectangle (XFRAME (frame
), XFRAME (frame
)->output_data
.x
->reverse_gc
,
4630 left
, top
, n_chars
, n_lines
);
4636 /* Draw lines around the text region beginning at the character position
4637 TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
4638 pixel and line characteristics. */
4640 #define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
4643 outline_region (f
, gc
, top_x
, top_y
, bottom_x
, bottom_y
)
4644 register struct frame
*f
;
4646 int top_x
, top_y
, bottom_x
, bottom_y
;
4648 register int ibw
= f
->output_data
.x
->internal_border_width
;
4649 register int font_w
= FONT_WIDTH (f
->output_data
.x
->font
);
4650 register int font_h
= f
->output_data
.x
->line_height
;
4652 int x
= line_len (y
);
4653 XPoint
*pixel_points
4654 = (XPoint
*) alloca (((bottom_y
- top_y
+ 2) * 4) * sizeof (XPoint
));
4655 register XPoint
*this_point
= pixel_points
;
4657 /* Do the horizontal top line/lines */
4660 this_point
->x
= ibw
;
4661 this_point
->y
= ibw
+ (font_h
* top_y
);
4664 this_point
->x
= ibw
+ (font_w
/ 2); /* Half-size for newline chars. */
4666 this_point
->x
= ibw
+ (font_w
* x
);
4667 this_point
->y
= (this_point
- 1)->y
;
4671 this_point
->x
= ibw
;
4672 this_point
->y
= ibw
+ (font_h
* (top_y
+ 1));
4674 this_point
->x
= ibw
+ (font_w
* top_x
);
4675 this_point
->y
= (this_point
- 1)->y
;
4677 this_point
->x
= (this_point
- 1)->x
;
4678 this_point
->y
= ibw
+ (font_h
* top_y
);
4680 this_point
->x
= ibw
+ (font_w
* x
);
4681 this_point
->y
= (this_point
- 1)->y
;
4684 /* Now do the right side. */
4685 while (y
< bottom_y
)
4686 { /* Right vertical edge */
4688 this_point
->x
= (this_point
- 1)->x
;
4689 this_point
->y
= ibw
+ (font_h
* (y
+ 1));
4692 y
++; /* Horizontal connection to next line */
4695 this_point
->x
= ibw
+ (font_w
/ 2);
4697 this_point
->x
= ibw
+ (font_w
* x
);
4699 this_point
->y
= (this_point
- 1)->y
;
4702 /* Now do the bottom and connect to the top left point. */
4703 this_point
->x
= ibw
+ (font_w
* (bottom_x
+ 1));
4706 this_point
->x
= (this_point
- 1)->x
;
4707 this_point
->y
= ibw
+ (font_h
* (bottom_y
+ 1));
4709 this_point
->x
= ibw
;
4710 this_point
->y
= (this_point
- 1)->y
;
4712 this_point
->x
= pixel_points
->x
;
4713 this_point
->y
= pixel_points
->y
;
4715 XDrawLines (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4717 (this_point
- pixel_points
+ 1), CoordModeOrigin
);
4720 DEFUN ("x-contour-region", Fx_contour_region
, Sx_contour_region
, 1, 1, 0,
4721 "Highlight the region between point and the character under the mouse\n\
4724 register Lisp_Object event
;
4726 register int x0
, y0
, x1
, y1
;
4727 register struct frame
*f
= selected_frame
;
4728 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4729 register int p1
, p2
;
4731 CHECK_CONS (event
, 0);
4734 x0
= XINT (Fcar (Fcar (event
)));
4735 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4737 /* If the mouse is past the end of the line, don't that area. */
4738 /* ReWrite this... */
4740 /* Where the cursor is. */
4741 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4742 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4744 if (y1
> y0
) /* point below mouse */
4745 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4747 else if (y1
< y0
) /* point above mouse */
4748 outline_region (f
, f
->output_data
.x
->cursor_gc
,
4750 else /* same line: draw horizontal rectangle */
4753 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4754 x0
, y0
, (x1
- x0
+ 1), 1);
4756 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
4757 x1
, y1
, (x0
- x1
+ 1), 1);
4760 XFlush (FRAME_X_DISPLAY (f
));
4766 DEFUN ("x-uncontour-region", Fx_uncontour_region
, Sx_uncontour_region
, 1, 1, 0,
4767 "Erase any highlighting of the region between point and the character\n\
4768 at X, Y on the selected frame.")
4770 register Lisp_Object event
;
4772 register int x0
, y0
, x1
, y1
;
4773 register struct frame
*f
= selected_frame
;
4774 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4777 x0
= XINT (Fcar (Fcar (event
)));
4778 y0
= XINT (Fcar (Fcdr (Fcar (event
))));
4779 x1
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4780 y1
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4782 if (y1
> y0
) /* point below mouse */
4783 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4785 else if (y1
< y0
) /* point above mouse */
4786 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4788 else /* same line: draw horizontal rectangle */
4791 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4792 x0
, y0
, (x1
- x0
+ 1), 1);
4794 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
4795 x1
, y1
, (x0
- x1
+ 1), 1);
4803 int contour_begin_x
, contour_begin_y
;
4804 int contour_end_x
, contour_end_y
;
4805 int contour_npoints
;
4807 /* Clip the top part of the contour lines down (and including) line Y_POS.
4808 If X_POS is in the middle (rather than at the end) of the line, drop
4809 down a line at that character. */
4812 clip_contour_top (y_pos
, x_pos
)
4814 register XPoint
*begin
= contour_lines
[y_pos
].top_left
;
4815 register XPoint
*end
;
4816 register int npoints
;
4817 register struct display_line
*line
= selected_frame
->phys_lines
[y_pos
+ 1];
4819 if (x_pos
>= line
->len
- 1) /* Draw one, straight horizontal line. */
4821 end
= contour_lines
[y_pos
].top_right
;
4822 npoints
= (end
- begin
+ 1);
4823 XDrawLines (x_current_display
, contour_window
,
4824 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4826 bcopy (end
, begin
+ 1, contour_last_point
- end
+ 1);
4827 contour_last_point
-= (npoints
- 2);
4828 XDrawLines (x_current_display
, contour_window
,
4829 contour_erase_gc
, begin
, 2, CoordModeOrigin
);
4830 XFlush (x_current_display
);
4832 /* Now, update contour_lines structure. */
4837 register XPoint
*p
= begin
+ 1;
4838 end
= contour_lines
[y_pos
].bottom_right
;
4839 npoints
= (end
- begin
+ 1);
4840 XDrawLines (x_current_display
, contour_window
,
4841 contour_erase_gc
, begin_erase
, npoints
, CoordModeOrigin
);
4844 p
->x
= ibw
+ (font_w
* (x_pos
+ 1));
4846 p
->y
= begin
->y
+ font_h
;
4848 bcopy (end
, begin
+ 3, contour_last_point
- end
+ 1);
4849 contour_last_point
-= (npoints
- 5);
4850 XDrawLines (x_current_display
, contour_window
,
4851 contour_erase_gc
, begin
, 4, CoordModeOrigin
);
4852 XFlush (x_current_display
);
4854 /* Now, update contour_lines structure. */
4858 /* Erase the top horizontal lines of the contour, and then extend
4859 the contour upwards. */
4862 extend_contour_top (line
)
4867 clip_contour_bottom (x_pos
, y_pos
)
4873 extend_contour_bottom (x_pos
, y_pos
)
4877 DEFUN ("x-select-region", Fx_select_region
, Sx_select_region
, 1, 1, "e",
4882 register struct frame
*f
= selected_frame
;
4883 struct window
*w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
4884 register int point_x
= WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
);
4885 register int point_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
);
4886 register int mouse_below_point
;
4887 register Lisp_Object obj
;
4888 register int x_contour_x
, x_contour_y
;
4890 x_contour_x
= x_mouse_x
;
4891 x_contour_y
= x_mouse_y
;
4892 if (x_contour_y
> point_y
|| (x_contour_y
== point_y
4893 && x_contour_x
> point_x
))
4895 mouse_below_point
= 1;
4896 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4897 x_contour_x
, x_contour_y
);
4901 mouse_below_point
= 0;
4902 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_contour_x
, x_contour_y
,
4908 obj
= read_char (-1, 0, 0, Qnil
, 0);
4912 if (mouse_below_point
)
4914 if (x_mouse_y
<= point_y
) /* Flipped. */
4916 mouse_below_point
= 0;
4918 outline_region (f
, f
->output_data
.x
->reverse_gc
, point_x
, point_y
,
4919 x_contour_x
, x_contour_y
);
4920 outline_region (f
, f
->output_data
.x
->cursor_gc
, x_mouse_x
, x_mouse_y
,
4923 else if (x_mouse_y
< x_contour_y
) /* Bottom clipped. */
4925 clip_contour_bottom (x_mouse_y
);
4927 else if (x_mouse_y
> x_contour_y
) /* Bottom extended. */
4929 extend_bottom_contour (x_mouse_y
);
4932 x_contour_x
= x_mouse_x
;
4933 x_contour_y
= x_mouse_y
;
4935 else /* mouse above or same line as point */
4937 if (x_mouse_y
>= point_y
) /* Flipped. */
4939 mouse_below_point
= 1;
4941 outline_region (f
, f
->output_data
.x
->reverse_gc
,
4942 x_contour_x
, x_contour_y
, point_x
, point_y
);
4943 outline_region (f
, f
->output_data
.x
->cursor_gc
, point_x
, point_y
,
4944 x_mouse_x
, x_mouse_y
);
4946 else if (x_mouse_y
> x_contour_y
) /* Top clipped. */
4948 clip_contour_top (x_mouse_y
);
4950 else if (x_mouse_y
< x_contour_y
) /* Top extended. */
4952 extend_contour_top (x_mouse_y
);
4957 unread_command_event
= obj
;
4958 if (mouse_below_point
)
4960 contour_begin_x
= point_x
;
4961 contour_begin_y
= point_y
;
4962 contour_end_x
= x_contour_x
;
4963 contour_end_y
= x_contour_y
;
4967 contour_begin_x
= x_contour_x
;
4968 contour_begin_y
= x_contour_y
;
4969 contour_end_x
= point_x
;
4970 contour_end_y
= point_y
;
4975 DEFUN ("x-horizontal-line", Fx_horizontal_line
, Sx_horizontal_line
, 1, 1, "e",
4980 register Lisp_Object obj
;
4981 struct frame
*f
= selected_frame
;
4982 register struct window
*w
= XWINDOW (selected_window
);
4983 register GC line_gc
= f
->output_data
.x
->cursor_gc
;
4984 register GC erase_gc
= f
->output_data
.x
->reverse_gc
;
4986 char dash_list
[] = {6, 4, 6, 4};
4988 XGCValues gc_values
;
4990 register int previous_y
;
4991 register int line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
4992 + f
->output_data
.x
->internal_border_width
;
4993 register int left
= f
->output_data
.x
->internal_border_width
4994 + (WINDOW_LEFT_MARGIN (w
)
4995 * FONT_WIDTH (f
->output_data
.x
->font
));
4996 register int right
= left
+ (w
->width
4997 * FONT_WIDTH (f
->output_data
.x
->font
))
4998 - f
->output_data
.x
->internal_border_width
;
5002 gc_values
.foreground
= f
->output_data
.x
->cursor_pixel
;
5003 gc_values
.background
= f
->output_data
.x
->background_pixel
;
5004 gc_values
.line_width
= 1;
5005 gc_values
.line_style
= LineOnOffDash
;
5006 gc_values
.cap_style
= CapRound
;
5007 gc_values
.join_style
= JoinRound
;
5009 line_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5010 GCLineStyle
| GCJoinStyle
| GCCapStyle
5011 | GCLineWidth
| GCForeground
| GCBackground
,
5013 XSetDashes (FRAME_X_DISPLAY (f
), line_gc
, 0, dash_list
, dashes
);
5014 gc_values
.foreground
= f
->output_data
.x
->background_pixel
;
5015 gc_values
.background
= f
->output_data
.x
->foreground_pixel
;
5016 erase_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5017 GCLineStyle
| GCJoinStyle
| GCCapStyle
5018 | GCLineWidth
| GCForeground
| GCBackground
,
5020 XSetDashes (FRAME_X_DISPLAY (f
), erase_gc
, 0, dash_list
, dashes
);
5027 if (x_mouse_y
>= XINT (w
->top
)
5028 && x_mouse_y
< XINT (w
->top
) + XINT (w
->height
) - 1)
5030 previous_y
= x_mouse_y
;
5031 line
= (x_mouse_y
+ 1) * f
->output_data
.x
->line_height
5032 + f
->output_data
.x
->internal_border_width
;
5033 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5034 line_gc
, left
, line
, right
, line
);
5036 XFlush (FRAME_X_DISPLAY (f
));
5041 obj
= read_char (-1, 0, 0, Qnil
, 0);
5043 || (! EQ (Fcar (Fcdr (Fcdr (obj
))),
5044 Qvertical_scroll_bar
))
5048 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5049 erase_gc
, left
, line
, right
, line
);
5050 unread_command_event
= obj
;
5052 XFreeGC (FRAME_X_DISPLAY (f
), line_gc
);
5053 XFreeGC (FRAME_X_DISPLAY (f
), erase_gc
);
5059 while (x_mouse_y
== previous_y
);
5062 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5063 erase_gc
, left
, line
, right
, line
);
5070 /* These keep track of the rectangle following the pointer. */
5071 int mouse_track_top
, mouse_track_left
, mouse_track_width
;
5073 /* Offset in buffer of character under the pointer, or 0. */
5074 int mouse_buffer_offset
;
5076 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 0, 0, 0,
5077 "Track the pointer.")
5080 static Cursor current_pointer_shape
;
5081 FRAME_PTR f
= x_mouse_frame
;
5084 if (EQ (Vmouse_frame_part
, Qtext_part
)
5085 && (current_pointer_shape
!= f
->output_data
.x
->nontext_cursor
))
5090 current_pointer_shape
= f
->output_data
.x
->nontext_cursor
;
5091 XDefineCursor (FRAME_X_DISPLAY (f
),
5093 current_pointer_shape
);
5095 buf
= XBUFFER (XWINDOW (Vmouse_window
)->buffer
);
5096 c
= *(BUF_CHAR_ADDRESS (buf
, mouse_buffer_offset
));
5098 else if (EQ (Vmouse_frame_part
, Qmodeline_part
)
5099 && (current_pointer_shape
!= f
->output_data
.x
->modeline_cursor
))
5101 current_pointer_shape
= f
->output_data
.x
->modeline_cursor
;
5102 XDefineCursor (FRAME_X_DISPLAY (f
),
5104 current_pointer_shape
);
5107 XFlush (FRAME_X_DISPLAY (f
));
5113 DEFUN ("x-track-pointer", Fx_track_pointer
, Sx_track_pointer
, 1, 1, "e",
5114 "Draw rectangle around character under mouse pointer, if there is one.")
5118 struct window
*w
= XWINDOW (Vmouse_window
);
5119 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5120 struct buffer
*b
= XBUFFER (w
->buffer
);
5123 if (! EQ (Vmouse_window
, selected_window
))
5126 if (EQ (event
, Qnil
))
5130 x_read_mouse_position (selected_frame
, &x
, &y
);
5134 mouse_track_width
= 0;
5135 mouse_track_left
= mouse_track_top
= -1;
5139 if ((x_mouse_x
!= mouse_track_left
5140 && (x_mouse_x
< mouse_track_left
5141 || x_mouse_x
> (mouse_track_left
+ mouse_track_width
)))
5142 || x_mouse_y
!= mouse_track_top
)
5144 int hp
= 0; /* Horizontal position */
5145 int len
= FRAME_CURRENT_GLYPHS (f
)->used
[x_mouse_y
];
5146 int p
= FRAME_CURRENT_GLYPHS (f
)->bufp
[x_mouse_y
];
5147 int tab_width
= XINT (b
->tab_width
);
5148 int ctl_arrow_p
= !NILP (b
->ctl_arrow
);
5150 int mode_line_vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
5151 int in_mode_line
= 0;
5153 if (! FRAME_CURRENT_GLYPHS (f
)->enable
[x_mouse_y
])
5156 /* Erase previous rectangle. */
5157 if (mouse_track_width
)
5159 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
5160 mouse_track_left
, mouse_track_top
,
5161 mouse_track_width
, 1);
5163 if ((mouse_track_left
== f
->phys_cursor_x
5164 || mouse_track_left
== f
->phys_cursor_x
- 1)
5165 && mouse_track_top
== f
->phys_cursor_y
)
5167 x_display_cursor (f
, 1);
5171 mouse_track_left
= x_mouse_x
;
5172 mouse_track_top
= x_mouse_y
;
5173 mouse_track_width
= 0;
5175 if (mouse_track_left
> len
) /* Past the end of line. */
5178 if (mouse_track_top
== mode_line_vpos
)
5184 if (tab_width
<= 0 || tab_width
> 20) tab_width
= 8;
5188 if (len
== f
->width
&& hp
== len
- 1 && c
!= '\n')
5194 mouse_track_width
= tab_width
- (hp
% tab_width
);
5196 hp
+= mouse_track_width
;
5199 mouse_track_left
= hp
- mouse_track_width
;
5205 mouse_track_width
= -1;
5209 if (ctl_arrow_p
&& (c
< 040 || c
== 0177))
5214 mouse_track_width
= 2;
5219 mouse_track_left
= hp
- mouse_track_width
;
5225 mouse_track_width
= 1;
5232 while (hp
<= x_mouse_x
);
5235 if (mouse_track_width
) /* Over text; use text pointer shape. */
5237 XDefineCursor (FRAME_X_DISPLAY (f
),
5239 f
->output_data
.x
->text_cursor
);
5240 x_rectangle (f
, f
->output_data
.x
->cursor_gc
,
5241 mouse_track_left
, mouse_track_top
,
5242 mouse_track_width
, 1);
5244 else if (in_mode_line
)
5245 XDefineCursor (FRAME_X_DISPLAY (f
),
5247 f
->output_data
.x
->modeline_cursor
);
5249 XDefineCursor (FRAME_X_DISPLAY (f
),
5251 f
->output_data
.x
->nontext_cursor
);
5254 XFlush (FRAME_X_DISPLAY (f
));
5257 obj
= read_char (-1, 0, 0, Qnil
, 0);
5260 while (CONSP (obj
) /* Mouse event */
5261 && EQ (Fcar (Fcdr (Fcdr (obj
))), Qnil
) /* Not scroll bar */
5262 && EQ (Vmouse_depressed
, Qnil
) /* Only motion events */
5263 && EQ (Vmouse_window
, selected_window
) /* In this window */
5266 unread_command_event
= obj
;
5268 if (mouse_track_width
)
5270 x_rectangle (f
, f
->output_data
.x
->reverse_gc
,
5271 mouse_track_left
, mouse_track_top
,
5272 mouse_track_width
, 1);
5273 mouse_track_width
= 0;
5274 if ((mouse_track_left
== f
->phys_cursor_x
5275 || mouse_track_left
- 1 == f
->phys_cursor_x
)
5276 && mouse_track_top
== f
->phys_cursor_y
)
5278 x_display_cursor (f
, 1);
5281 XDefineCursor (FRAME_X_DISPLAY (f
),
5283 f
->output_data
.x
->nontext_cursor
);
5284 XFlush (FRAME_X_DISPLAY (f
));
5294 /* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
5295 on the frame F at position X, Y. */
5297 x_draw_pixmap (f
, x
, y
, image_data
, width
, height
)
5299 int x
, y
, width
, height
;
5304 image
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
),
5305 FRAME_X_WINDOW (f
), image_data
,
5307 XCopyPlane (FRAME_X_DISPLAY (f
), image
, FRAME_X_WINDOW (f
),
5308 f
->output_data
.x
->normal_gc
, 0, 0, width
, height
, x
, y
);
5312 #if 0 /* I'm told these functions are superfluous
5313 given the ability to bind function keys. */
5316 DEFUN ("x-rebind-key", Fx_rebind_key
, Sx_rebind_key
, 3, 3, 0,
5317 "Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
5318 KEYSYM is a string which conforms to the X keysym definitions found\n\
5319 in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
5320 list of strings specifying modifier keys such as Control_L, which must\n\
5321 also be depressed for NEWSTRING to appear.")
5322 (x_keysym
, modifiers
, newstring
)
5323 register Lisp_Object x_keysym
;
5324 register Lisp_Object modifiers
;
5325 register Lisp_Object newstring
;
5328 register KeySym keysym
;
5329 KeySym modifier_list
[16];
5332 CHECK_STRING (x_keysym
, 1);
5333 CHECK_STRING (newstring
, 3);
5335 keysym
= XStringToKeysym ((char *) XSTRING (x_keysym
)->data
);
5336 if (keysym
== NoSymbol
)
5337 error ("Keysym does not exist");
5339 if (NILP (modifiers
))
5340 XRebindKeysym (x_current_display
, keysym
, modifier_list
, 0,
5341 XSTRING (newstring
)->data
,
5342 STRING_BYTES (XSTRING (newstring
)));
5345 register Lisp_Object rest
, mod
;
5348 for (rest
= modifiers
; !NILP (rest
); rest
= Fcdr (rest
))
5351 error ("Can't have more than 16 modifiers");
5354 CHECK_STRING (mod
, 3);
5355 modifier_list
[i
] = XStringToKeysym ((char *) XSTRING (mod
)->data
);
5357 if (modifier_list
[i
] == NoSymbol
5358 || !(IsModifierKey (modifier_list
[i
])
5359 || ((unsigned)(modifier_list
[i
]) == XK_Mode_switch
)
5360 || ((unsigned)(modifier_list
[i
]) == XK_Num_Lock
)))
5362 if (modifier_list
[i
] == NoSymbol
5363 || !IsModifierKey (modifier_list
[i
]))
5365 error ("Element is not a modifier keysym");
5369 XRebindKeysym (x_current_display
, keysym
, modifier_list
, i
,
5370 XSTRING (newstring
)->data
,
5371 STRING_BYTES (XSTRING (newstring
)));
5377 DEFUN ("x-rebind-keys", Fx_rebind_keys
, Sx_rebind_keys
, 2, 2, 0,
5378 "Rebind KEYCODE to list of strings STRINGS.\n\
5379 STRINGS should be a list of 16 elements, one for each shift combination.\n\
5380 nil as element means don't change.\n\
5381 See the documentation of `x-rebind-key' for more information.")
5383 register Lisp_Object keycode
;
5384 register Lisp_Object strings
;
5386 register Lisp_Object item
;
5387 register unsigned char *rawstring
;
5388 KeySym rawkey
, modifier
[1];
5390 register unsigned i
;
5393 CHECK_NUMBER (keycode
, 1);
5394 CHECK_CONS (strings
, 2);
5395 rawkey
= (KeySym
) ((unsigned) (XINT (keycode
))) & 255;
5396 for (i
= 0; i
<= 15; strings
= Fcdr (strings
), i
++)
5398 item
= Fcar (strings
);
5401 CHECK_STRING (item
, 2);
5402 strsize
= STRING_BYTES (XSTRING (item
));
5403 rawstring
= (unsigned char *) xmalloc (strsize
);
5404 bcopy (XSTRING (item
)->data
, rawstring
, strsize
);
5405 modifier
[1] = 1 << i
;
5406 XRebindKeysym (x_current_display
, rawkey
, modifier
, 1,
5407 rawstring
, strsize
);
5412 #endif /* HAVE_X11 */
5415 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5417 XScreenNumberOfScreen (scr
)
5418 register Screen
*scr
;
5420 register Display
*dpy
;
5421 register Screen
*dpyscr
;
5425 dpyscr
= dpy
->screens
;
5427 for (i
= 0; i
< dpy
->nscreens
; i
++, dpyscr
++)
5433 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5436 select_visual (dpy
, screen
, depth
)
5439 unsigned int *depth
;
5442 XVisualInfo
*vinfo
, vinfo_template
;
5445 v
= DefaultVisualOfScreen (screen
);
5448 vinfo_template
.visualid
= XVisualIDFromVisual (v
);
5450 vinfo_template
.visualid
= v
->visualid
;
5453 vinfo_template
.screen
= XScreenNumberOfScreen (screen
);
5455 vinfo
= XGetVisualInfo (dpy
,
5456 VisualIDMask
| VisualScreenMask
, &vinfo_template
,
5459 fatal ("Can't get proper X visual info");
5461 if ((1 << vinfo
->depth
) == vinfo
->colormap_size
)
5462 *depth
= vinfo
->depth
;
5466 int n
= vinfo
->colormap_size
- 1;
5475 XFree ((char *) vinfo
);
5479 /* Return the X display structure for the display named NAME.
5480 Open a new connection if necessary. */
5482 struct x_display_info
*
5483 x_display_info_for_name (name
)
5487 struct x_display_info
*dpyinfo
;
5489 CHECK_STRING (name
, 0);
5491 if (! EQ (Vwindow_system
, intern ("x")))
5492 error ("Not using X Windows");
5494 for (dpyinfo
= x_display_list
, names
= x_display_name_list
;
5496 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
5499 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
5504 /* Use this general default value to start with. */
5505 Vx_resource_name
= Vinvocation_name
;
5507 validate_x_resource_name ();
5509 dpyinfo
= x_term_init (name
, (unsigned char *)0,
5510 (char *) XSTRING (Vx_resource_name
)->data
);
5513 error ("Cannot connect to X server %s", XSTRING (name
)->data
);
5516 XSETFASTINT (Vwindow_system_version
, 11);
5521 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5522 1, 3, 0, "Open a connection to an X server.\n\
5523 DISPLAY is the name of the display to connect to.\n\
5524 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5525 If the optional third arg MUST-SUCCEED is non-nil,\n\
5526 terminate Emacs if we can't open the connection.")
5527 (display
, xrm_string
, must_succeed
)
5528 Lisp_Object display
, xrm_string
, must_succeed
;
5530 unsigned char *xrm_option
;
5531 struct x_display_info
*dpyinfo
;
5533 CHECK_STRING (display
, 0);
5534 if (! NILP (xrm_string
))
5535 CHECK_STRING (xrm_string
, 1);
5537 if (! EQ (Vwindow_system
, intern ("x")))
5538 error ("Not using X Windows");
5540 if (! NILP (xrm_string
))
5541 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5543 xrm_option
= (unsigned char *) 0;
5545 validate_x_resource_name ();
5547 /* This is what opens the connection and sets x_current_display.
5548 This also initializes many symbols, such as those used for input. */
5549 dpyinfo
= x_term_init (display
, xrm_option
,
5550 (char *) XSTRING (Vx_resource_name
)->data
);
5554 if (!NILP (must_succeed
))
5555 fatal ("Cannot connect to X server %s.\n\
5556 Check the DISPLAY environment variable or use `-d'.\n\
5557 Also use the `xhost' program to verify that it is set to permit\n\
5558 connections from your machine.\n",
5559 XSTRING (display
)->data
);
5561 error ("Cannot connect to X server %s", XSTRING (display
)->data
);
5566 XSETFASTINT (Vwindow_system_version
, 11);
5570 DEFUN ("x-close-connection", Fx_close_connection
,
5571 Sx_close_connection
, 1, 1, 0,
5572 "Close the connection to DISPLAY's X server.\n\
5573 For DISPLAY, specify either a frame or a display name (a string).\n\
5574 If DISPLAY is nil, that stands for the selected frame's display.")
5576 Lisp_Object display
;
5578 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5581 if (dpyinfo
->reference_count
> 0)
5582 error ("Display still has frames on it");
5585 /* Free the fonts in the font table. */
5586 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5587 if (dpyinfo
->font_table
[i
].name
)
5589 xfree (dpyinfo
->font_table
[i
].name
);
5590 /* Don't free the full_name string;
5591 it is always shared with something else. */
5592 XFreeFont (dpyinfo
->display
, dpyinfo
->font_table
[i
].font
);
5595 x_destroy_all_bitmaps (dpyinfo
);
5596 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
5598 #ifdef USE_X_TOOLKIT
5599 XtCloseDisplay (dpyinfo
->display
);
5601 XCloseDisplay (dpyinfo
->display
);
5604 x_delete_display (dpyinfo
);
5610 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5611 "Return the list of display names that Emacs has connections to.")
5614 Lisp_Object tail
, result
;
5617 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
5618 result
= Fcons (XCAR (XCAR (tail
)), result
);
5623 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5624 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5625 If ON is nil, allow buffering of requests.\n\
5626 Turning on synchronization prohibits the Xlib routines from buffering\n\
5627 requests and seriously degrades performance, but makes debugging much\n\
5629 The optional second argument DISPLAY specifies which display to act on.\n\
5630 DISPLAY should be either a frame or a display name (a string).\n\
5631 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5633 Lisp_Object display
, on
;
5635 struct x_display_info
*dpyinfo
= check_x_display_info (display
);
5637 XSynchronize (dpyinfo
->display
, !EQ (on
, Qnil
));
5642 /* Wait for responses to all X commands issued so far for frame F. */
5649 XSync (FRAME_X_DISPLAY (f
), False
);
5654 /***********************************************************************
5656 ***********************************************************************/
5658 /* Value is the number of elements of vector VECTOR. */
5660 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5662 /* List of supported image types. Use define_image_type to add new
5663 types. Use lookup_image_type to find a type for a given symbol. */
5665 static struct image_type
*image_types
;
5667 /* A list of symbols, one for each supported image type. */
5669 Lisp_Object Vimage_types
;
5671 /* The symbol `image' which is the car of the lists used to represent
5674 extern Lisp_Object Qimage
;
5676 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5682 Lisp_Object QCtype
, QCdata
, QCascent
, QCmargin
, QCrelief
;
5683 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
5684 Lisp_Object QCalgorithm
, QCcolor_symbols
, QCheuristic_mask
;
5685 Lisp_Object QCindex
;
5687 /* Other symbols. */
5689 Lisp_Object Qlaplace
;
5691 /* Time in seconds after which images should be removed from the cache
5692 if not displayed. */
5694 Lisp_Object Vimage_cache_eviction_delay
;
5696 /* Function prototypes. */
5698 static void define_image_type
P_ ((struct image_type
*type
));
5699 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
5700 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
5701 static void x_laplace
P_ ((struct frame
*, struct image
*));
5702 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
5706 /* Define a new image type from TYPE. This adds a copy of TYPE to
5707 image_types and adds the symbol *TYPE->type to Vimage_types. */
5710 define_image_type (type
)
5711 struct image_type
*type
;
5713 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5714 The initialized data segment is read-only. */
5715 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
5716 bcopy (type
, p
, sizeof *p
);
5717 p
->next
= image_types
;
5719 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
5723 /* Look up image type SYMBOL, and return a pointer to its image_type
5724 structure. Value is null if SYMBOL is not a known image type. */
5726 static INLINE
struct image_type
*
5727 lookup_image_type (symbol
)
5730 struct image_type
*type
;
5732 for (type
= image_types
; type
; type
= type
->next
)
5733 if (EQ (symbol
, *type
->type
))
5740 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5741 valid image specification is a list whose car is the symbol
5742 `image', and whose rest is a property list. The property list must
5743 contain a value for key `:type'. That value must be the name of a
5744 supported image type. The rest of the property list depends on the
5748 valid_image_p (object
)
5753 if (CONSP (object
) && EQ (XCAR (object
), Qimage
))
5755 Lisp_Object symbol
= Fplist_get (XCDR (object
), QCtype
);
5756 struct image_type
*type
= lookup_image_type (symbol
);
5759 valid_p
= type
->valid_p (object
);
5766 /* Log error message with format string FORMAT and argument ARG.
5767 Signaling an error, e.g. when an image cannot be loaded, is not a
5768 good idea because this would interrupt redisplay, and the error
5769 message display would lead to another redisplay. This function
5770 therefore simply displays a message. */
5773 image_error (format
, arg1
, arg2
)
5775 Lisp_Object arg1
, arg2
;
5777 add_to_log (format
, arg1
, arg2
);
5782 /***********************************************************************
5783 Image specifications
5784 ***********************************************************************/
5786 enum image_value_type
5788 IMAGE_DONT_CHECK_VALUE_TYPE
,
5791 IMAGE_POSITIVE_INTEGER_VALUE
,
5792 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
5793 IMAGE_INTEGER_VALUE
,
5794 IMAGE_FUNCTION_VALUE
,
5799 /* Structure used when parsing image specifications. */
5801 struct image_keyword
5803 /* Name of keyword. */
5806 /* The type of value allowed. */
5807 enum image_value_type type
;
5809 /* Non-zero means key must be present. */
5812 /* Used to recognize duplicate keywords in a property list. */
5815 /* The value that was found. */
5820 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
5822 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
5825 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5826 has the format (image KEYWORD VALUE ...). One of the keyword/
5827 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5828 image_keywords structures of size NKEYWORDS describing other
5829 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5832 parse_image_spec (spec
, keywords
, nkeywords
, type
)
5834 struct image_keyword
*keywords
;
5841 if (!CONSP (spec
) || !EQ (XCAR (spec
), Qimage
))
5844 plist
= XCDR (spec
);
5845 while (CONSP (plist
))
5847 Lisp_Object key
, value
;
5849 /* First element of a pair must be a symbol. */
5851 plist
= XCDR (plist
);
5855 /* There must follow a value. */
5858 value
= XCAR (plist
);
5859 plist
= XCDR (plist
);
5861 /* Find key in KEYWORDS. Error if not found. */
5862 for (i
= 0; i
< nkeywords
; ++i
)
5863 if (strcmp (keywords
[i
].name
, XSYMBOL (key
)->name
->data
) == 0)
5869 /* Record that we recognized the keyword. If a keywords
5870 was found more than once, it's an error. */
5871 keywords
[i
].value
= value
;
5872 ++keywords
[i
].count
;
5874 if (keywords
[i
].count
> 1)
5877 /* Check type of value against allowed type. */
5878 switch (keywords
[i
].type
)
5880 case IMAGE_STRING_VALUE
:
5881 if (!STRINGP (value
))
5885 case IMAGE_SYMBOL_VALUE
:
5886 if (!SYMBOLP (value
))
5890 case IMAGE_POSITIVE_INTEGER_VALUE
:
5891 if (!INTEGERP (value
) || XINT (value
) <= 0)
5895 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
5896 if (!INTEGERP (value
) || XINT (value
) < 0)
5900 case IMAGE_DONT_CHECK_VALUE_TYPE
:
5903 case IMAGE_FUNCTION_VALUE
:
5904 value
= indirect_function (value
);
5906 || COMPILEDP (value
)
5907 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
5911 case IMAGE_NUMBER_VALUE
:
5912 if (!INTEGERP (value
) && !FLOATP (value
))
5916 case IMAGE_INTEGER_VALUE
:
5917 if (!INTEGERP (value
))
5921 case IMAGE_BOOL_VALUE
:
5922 if (!NILP (value
) && !EQ (value
, Qt
))
5931 if (EQ (key
, QCtype
) && !EQ (type
, value
))
5935 /* Check that all mandatory fields are present. */
5936 for (i
= 0; i
< nkeywords
; ++i
)
5937 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
5940 return NILP (plist
);
5944 /* Return the value of KEY in image specification SPEC. Value is nil
5945 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5946 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5949 image_spec_value (spec
, key
, found
)
5950 Lisp_Object spec
, key
;
5955 xassert (valid_image_p (spec
));
5957 for (tail
= XCDR (spec
);
5958 CONSP (tail
) && CONSP (XCDR (tail
));
5959 tail
= XCDR (XCDR (tail
)))
5961 if (EQ (XCAR (tail
), key
))
5965 return XCAR (XCDR (tail
));
5977 /***********************************************************************
5978 Image type independent image structures
5979 ***********************************************************************/
5981 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
5982 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
5985 /* Allocate and return a new image structure for image specification
5986 SPEC. SPEC has a hash value of HASH. */
5988 static struct image
*
5989 make_image (spec
, hash
)
5993 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
5995 xassert (valid_image_p (spec
));
5996 bzero (img
, sizeof *img
);
5997 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
5998 xassert (img
->type
!= NULL
);
6000 img
->data
.lisp_val
= Qnil
;
6001 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
6007 /* Free image IMG which was used on frame F, including its resources. */
6016 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6018 /* Remove IMG from the hash table of its cache. */
6020 img
->prev
->next
= img
->next
;
6022 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
6025 img
->next
->prev
= img
->prev
;
6027 c
->images
[img
->id
] = NULL
;
6029 /* Free resources, then free IMG. */
6030 img
->type
->free (f
, img
);
6036 /* Prepare image IMG for display on frame F. Must be called before
6037 drawing an image. */
6040 prepare_image_for_display (f
, img
)
6046 /* We're about to display IMG, so set its timestamp to `now'. */
6048 img
->timestamp
= EMACS_SECS (t
);
6050 /* If IMG doesn't have a pixmap yet, load it now, using the image
6051 type dependent loader function. */
6052 if (img
->pixmap
== 0 && !img
->load_failed_p
)
6053 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6058 /***********************************************************************
6059 Helper functions for X image types
6060 ***********************************************************************/
6062 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
6063 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
6065 Lisp_Object color_name
,
6066 unsigned long dflt
));
6068 /* Free X resources of image IMG which is used on frame F. */
6071 x_clear_image (f
, img
)
6078 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6085 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
6087 /* If display has an immutable color map, freeing colors is not
6088 necessary and some servers don't allow it. So don't do it. */
6089 if (class != StaticColor
6090 && class != StaticGray
6091 && class != TrueColor
)
6095 cmap
= DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f
)->screen
);
6096 XFreeColors (FRAME_X_DISPLAY (f
), cmap
, img
->colors
,
6101 xfree (img
->colors
);
6108 /* Allocate color COLOR_NAME for image IMG on frame F. If color
6109 cannot be allocated, use DFLT. Add a newly allocated color to
6110 IMG->colors, so that it can be freed again. Value is the pixel
6113 static unsigned long
6114 x_alloc_image_color (f
, img
, color_name
, dflt
)
6117 Lisp_Object color_name
;
6121 unsigned long result
;
6123 xassert (STRINGP (color_name
));
6125 if (x_defined_color (f
, XSTRING (color_name
)->data
, &color
, 1))
6127 /* This isn't called frequently so we get away with simply
6128 reallocating the color vector to the needed size, here. */
6131 (unsigned long *) xrealloc (img
->colors
,
6132 img
->ncolors
* sizeof *img
->colors
);
6133 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
6134 result
= color
.pixel
;
6144 /***********************************************************************
6146 ***********************************************************************/
6148 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
6151 /* Return a new, initialized image cache that is allocated from the
6152 heap. Call free_image_cache to free an image cache. */
6154 struct image_cache
*
6157 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
6160 bzero (c
, sizeof *c
);
6162 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
6163 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
6164 c
->buckets
= (struct image
**) xmalloc (size
);
6165 bzero (c
->buckets
, size
);
6170 /* Free image cache of frame F. Be aware that X frames share images
6174 free_image_cache (f
)
6177 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6182 /* Cache should not be referenced by any frame when freed. */
6183 xassert (c
->refcount
== 0);
6185 for (i
= 0; i
< c
->used
; ++i
)
6186 free_image (f
, c
->images
[i
]);
6190 FRAME_X_IMAGE_CACHE (f
) = NULL
;
6195 /* Clear image cache of frame F. FORCE_P non-zero means free all
6196 images. FORCE_P zero means clear only images that haven't been
6197 displayed for some time. Should be called from time to time to
6198 reduce the number of loaded images. If image-eviction-seconds is
6199 non-nil, this frees images in the cache which weren't displayed for
6200 at least that many seconds. */
6203 clear_image_cache (f
, force_p
)
6207 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6209 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
6213 int i
, any_freed_p
= 0;
6216 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
6218 for (i
= 0; i
< c
->used
; ++i
)
6220 struct image
*img
= c
->images
[i
];
6223 || (img
->timestamp
> old
)))
6225 free_image (f
, img
);
6230 /* We may be clearing the image cache because, for example,
6231 Emacs was iconified for a longer period of time. In that
6232 case, current matrices may still contain references to
6233 images freed above. So, clear these matrices. */
6236 clear_current_matrices (f
);
6237 ++windows_or_buffers_changed
;
6243 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
6245 "Clear the image cache of FRAME.\n\
6246 FRAME nil or omitted means use the selected frame.\n\
6247 FRAME t means clear the image caches of all frames.")
6255 FOR_EACH_FRAME (tail
, frame
)
6256 if (FRAME_X_P (XFRAME (frame
)))
6257 clear_image_cache (XFRAME (frame
), 1);
6260 clear_image_cache (check_x_frame (frame
), 1);
6266 /* Return the id of image with Lisp specification SPEC on frame F.
6267 SPEC must be a valid Lisp image specification (see valid_image_p). */
6270 lookup_image (f
, spec
)
6274 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6278 struct gcpro gcpro1
;
6281 /* F must be a window-system frame, and SPEC must be a valid image
6283 xassert (FRAME_WINDOW_P (f
));
6284 xassert (valid_image_p (spec
));
6288 /* Look up SPEC in the hash table of the image cache. */
6289 hash
= sxhash (spec
, 0);
6290 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6292 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
6293 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
6296 /* If not found, create a new image and cache it. */
6299 img
= make_image (spec
, hash
);
6300 cache_image (f
, img
);
6301 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
6302 xassert (!interrupt_input_blocked
);
6304 /* If we can't load the image, and we don't have a width and
6305 height, use some arbitrary width and height so that we can
6306 draw a rectangle for it. */
6307 if (img
->load_failed_p
)
6311 value
= image_spec_value (spec
, QCwidth
, NULL
);
6312 img
->width
= (INTEGERP (value
)
6313 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
6314 value
= image_spec_value (spec
, QCheight
, NULL
);
6315 img
->height
= (INTEGERP (value
)
6316 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
6320 /* Handle image type independent image attributes
6321 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
6322 Lisp_Object ascent
, margin
, relief
, algorithm
, heuristic_mask
;
6325 ascent
= image_spec_value (spec
, QCascent
, NULL
);
6326 if (INTEGERP (ascent
))
6327 img
->ascent
= XFASTINT (ascent
);
6329 margin
= image_spec_value (spec
, QCmargin
, NULL
);
6330 if (INTEGERP (margin
) && XINT (margin
) >= 0)
6331 img
->margin
= XFASTINT (margin
);
6333 relief
= image_spec_value (spec
, QCrelief
, NULL
);
6334 if (INTEGERP (relief
))
6336 img
->relief
= XINT (relief
);
6337 img
->margin
+= abs (img
->relief
);
6340 /* Should we apply a Laplace edge-detection algorithm? */
6341 algorithm
= image_spec_value (spec
, QCalgorithm
, NULL
);
6342 if (img
->pixmap
&& EQ (algorithm
, Qlaplace
))
6345 /* Should we built a mask heuristically? */
6346 heuristic_mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
6347 if (img
->pixmap
&& !img
->mask
&& !NILP (heuristic_mask
))
6348 x_build_heuristic_mask (f
, img
, heuristic_mask
);
6352 /* We're using IMG, so set its timestamp to `now'. */
6353 EMACS_GET_TIME (now
);
6354 img
->timestamp
= EMACS_SECS (now
);
6358 /* Value is the image id. */
6363 /* Cache image IMG in the image cache of frame F. */
6366 cache_image (f
, img
)
6370 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6373 /* Find a free slot in c->images. */
6374 for (i
= 0; i
< c
->used
; ++i
)
6375 if (c
->images
[i
] == NULL
)
6378 /* If no free slot found, maybe enlarge c->images. */
6379 if (i
== c
->used
&& c
->used
== c
->size
)
6382 c
->images
= (struct image
**) xrealloc (c
->images
,
6383 c
->size
* sizeof *c
->images
);
6386 /* Add IMG to c->images, and assign IMG an id. */
6392 /* Add IMG to the cache's hash table. */
6393 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
6394 img
->next
= c
->buckets
[i
];
6396 img
->next
->prev
= img
;
6398 c
->buckets
[i
] = img
;
6402 /* Call FN on every image in the image cache of frame F. Used to mark
6403 Lisp Objects in the image cache. */
6406 forall_images_in_image_cache (f
, fn
)
6408 void (*fn
) P_ ((struct image
*img
));
6410 if (FRAME_LIVE_P (f
) && FRAME_X_P (f
))
6412 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
6416 for (i
= 0; i
< c
->used
; ++i
)
6425 /***********************************************************************
6427 ***********************************************************************/
6429 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
6430 XImage
**, Pixmap
*));
6431 static void x_destroy_x_image
P_ ((XImage
*));
6432 static void x_put_x_image
P_ ((struct frame
*, XImage
*, Pixmap
, int, int));
6435 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6436 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6437 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6438 via xmalloc. Print error messages via image_error if an error
6439 occurs. Value is non-zero if successful. */
6442 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
6444 int width
, height
, depth
;
6448 Display
*display
= FRAME_X_DISPLAY (f
);
6449 Screen
*screen
= FRAME_X_SCREEN (f
);
6450 Window window
= FRAME_X_WINDOW (f
);
6452 xassert (interrupt_input_blocked
);
6455 depth
= DefaultDepthOfScreen (screen
);
6456 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
6457 depth
, ZPixmap
, 0, NULL
, width
, height
,
6458 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
6461 image_error ("Unable to allocate X image", Qnil
, Qnil
);
6465 /* Allocate image raster. */
6466 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
6468 /* Allocate a pixmap of the same size. */
6469 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
6472 x_destroy_x_image (*ximg
);
6474 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
6482 /* Destroy XImage XIMG. Free XIMG->data. */
6485 x_destroy_x_image (ximg
)
6488 xassert (interrupt_input_blocked
);
6493 XDestroyImage (ximg
);
6498 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6499 are width and height of both the image and pixmap. */
6502 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
6509 xassert (interrupt_input_blocked
);
6510 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
6511 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
6512 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
6517 /***********************************************************************
6519 ***********************************************************************/
6521 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
6523 /* Find image file FILE. Look in data-directory, then
6524 x-bitmap-file-path. Value is the full name of the file found, or
6525 nil if not found. */
6528 x_find_image_file (file
)
6531 Lisp_Object file_found
, search_path
;
6532 struct gcpro gcpro1
, gcpro2
;
6536 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
6537 GCPRO2 (file_found
, search_path
);
6539 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6540 fd
= openp (search_path
, file
, "", &file_found
, 0);
6553 /***********************************************************************
6555 ***********************************************************************/
6557 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
6558 static int xbm_load_image_from_file
P_ ((struct frame
*f
, struct image
*img
,
6560 static int xbm_image_p
P_ ((Lisp_Object object
));
6561 static int xbm_read_bitmap_file_data
P_ ((char *, int *, int *,
6565 /* Indices of image specification fields in xbm_format, below. */
6567 enum xbm_keyword_index
6584 /* Vector of image_keyword structures describing the format
6585 of valid XBM image specifications. */
6587 static struct image_keyword xbm_format
[XBM_LAST
] =
6589 {":type", IMAGE_SYMBOL_VALUE
, 1},
6590 {":file", IMAGE_STRING_VALUE
, 0},
6591 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6592 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6593 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6594 {":foreground", IMAGE_STRING_VALUE
, 0},
6595 {":background", IMAGE_STRING_VALUE
, 0},
6596 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6597 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
6598 {":relief", IMAGE_INTEGER_VALUE
, 0},
6599 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6600 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
6603 /* Structure describing the image type XBM. */
6605 static struct image_type xbm_type
=
6614 /* Tokens returned from xbm_scan. */
6623 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6624 A valid specification is a list starting with the symbol `image'
6625 The rest of the list is a property list which must contain an
6628 If the specification specifies a file to load, it must contain
6629 an entry `:file FILENAME' where FILENAME is a string.
6631 If the specification is for a bitmap loaded from memory it must
6632 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6633 WIDTH and HEIGHT are integers > 0. DATA may be:
6635 1. a string large enough to hold the bitmap data, i.e. it must
6636 have a size >= (WIDTH + 7) / 8 * HEIGHT
6638 2. a bool-vector of size >= WIDTH * HEIGHT
6640 3. a vector of strings or bool-vectors, one for each line of the
6643 Both the file and data forms may contain the additional entries
6644 `:background COLOR' and `:foreground COLOR'. If not present,
6645 foreground and background of the frame on which the image is
6646 displayed, is used. */
6649 xbm_image_p (object
)
6652 struct image_keyword kw
[XBM_LAST
];
6654 bcopy (xbm_format
, kw
, sizeof kw
);
6655 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
6658 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
6660 if (kw
[XBM_FILE
].count
)
6662 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
6670 /* Entries for `:width', `:height' and `:data' must be present. */
6671 if (!kw
[XBM_WIDTH
].count
6672 || !kw
[XBM_HEIGHT
].count
6673 || !kw
[XBM_DATA
].count
)
6676 data
= kw
[XBM_DATA
].value
;
6677 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
6678 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
6680 /* Check type of data, and width and height against contents of
6686 /* Number of elements of the vector must be >= height. */
6687 if (XVECTOR (data
)->size
< height
)
6690 /* Each string or bool-vector in data must be large enough
6691 for one line of the image. */
6692 for (i
= 0; i
< height
; ++i
)
6694 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
6698 if (XSTRING (elt
)->size
6699 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
6702 else if (BOOL_VECTOR_P (elt
))
6704 if (XBOOL_VECTOR (elt
)->size
< width
)
6711 else if (STRINGP (data
))
6713 if (XSTRING (data
)->size
6714 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
6717 else if (BOOL_VECTOR_P (data
))
6719 if (XBOOL_VECTOR (data
)->size
< width
* height
)
6726 /* Baseline must be a value between 0 and 100 (a percentage). */
6727 if (kw
[XBM_ASCENT
].count
6728 && XFASTINT (kw
[XBM_ASCENT
].value
) > 100)
6735 /* Scan a bitmap file. FP is the stream to read from. Value is
6736 either an enumerator from enum xbm_token, or a character for a
6737 single-character token, or 0 at end of file. If scanning an
6738 identifier, store the lexeme of the identifier in SVAL. If
6739 scanning a number, store its value in *IVAL. */
6742 xbm_scan (fp
, sval
, ival
)
6749 /* Skip white space. */
6750 while ((c
= fgetc (fp
)) != EOF
&& isspace (c
))
6755 else if (isdigit (c
))
6757 int value
= 0, digit
;
6762 if (c
== 'x' || c
== 'X')
6764 while ((c
= fgetc (fp
)) != EOF
)
6768 else if (c
>= 'a' && c
<= 'f')
6769 digit
= c
- 'a' + 10;
6770 else if (c
>= 'A' && c
<= 'F')
6771 digit
= c
- 'A' + 10;
6774 value
= 16 * value
+ digit
;
6777 else if (isdigit (c
))
6780 while ((c
= fgetc (fp
)) != EOF
6782 value
= 8 * value
+ c
- '0';
6788 while ((c
= fgetc (fp
)) != EOF
6790 value
= 10 * value
+ c
- '0';
6798 else if (isalpha (c
) || c
== '_')
6801 while ((c
= fgetc (fp
)) != EOF
6802 && (isalnum (c
) || c
== '_'))
6814 /* Replacement for XReadBitmapFileData which isn't available under old
6815 X versions. FILE is the name of the bitmap file to read. Set
6816 *WIDTH and *HEIGHT to the width and height of the image. Return in
6817 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
6821 xbm_read_bitmap_file_data (file
, width
, height
, data
)
6823 int *width
, *height
;
6824 unsigned char **data
;
6827 char buffer
[BUFSIZ
];
6830 int bytes_per_line
, i
, nbytes
;
6836 LA1 = xbm_scan (fp, buffer, &value)
6838 #define expect(TOKEN) \
6839 if (LA1 != (TOKEN)) \
6844 #define expect_ident(IDENT) \
6845 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6850 fp
= fopen (file
, "r");
6854 *width
= *height
= -1;
6856 LA1
= xbm_scan (fp
, buffer
, &value
);
6858 /* Parse defines for width, height and hot-spots. */
6862 expect_ident ("define");
6863 expect (XBM_TK_IDENT
);
6865 if (LA1
== XBM_TK_NUMBER
);
6867 char *p
= strrchr (buffer
, '_');
6868 p
= p
? p
+ 1 : buffer
;
6869 if (strcmp (p
, "width") == 0)
6871 else if (strcmp (p
, "height") == 0)
6874 expect (XBM_TK_NUMBER
);
6877 if (*width
< 0 || *height
< 0)
6880 /* Parse bits. Must start with `static'. */
6881 expect_ident ("static");
6882 if (LA1
== XBM_TK_IDENT
)
6884 if (strcmp (buffer
, "unsigned") == 0)
6887 expect_ident ("char");
6889 else if (strcmp (buffer
, "short") == 0)
6893 if (*width
% 16 && *width
% 16 < 9)
6896 else if (strcmp (buffer
, "char") == 0)
6904 expect (XBM_TK_IDENT
);
6910 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
6911 nbytes
= bytes_per_line
* *height
;
6912 p
= *data
= (char *) xmalloc (nbytes
);
6917 for (i
= 0; i
< nbytes
; i
+= 2)
6920 expect (XBM_TK_NUMBER
);
6923 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
6926 if (LA1
== ',' || LA1
== '}')
6934 for (i
= 0; i
< nbytes
; ++i
)
6937 expect (XBM_TK_NUMBER
);
6941 if (LA1
== ',' || LA1
== '}')
6967 /* Load XBM image IMG which will be displayed on frame F from file
6968 SPECIFIED_FILE. Value is non-zero if successful. */
6971 xbm_load_image_from_file (f
, img
, specified_file
)
6974 Lisp_Object specified_file
;
6977 unsigned char *data
;
6980 struct gcpro gcpro1
;
6982 xassert (STRINGP (specified_file
));
6986 file
= x_find_image_file (specified_file
);
6987 if (!STRINGP (file
))
6989 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6994 rc
= xbm_read_bitmap_file_data (XSTRING (file
)->data
, &img
->width
,
6995 &img
->height
, &data
);
6998 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
6999 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7000 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7003 xassert (img
->width
> 0 && img
->height
> 0);
7005 /* Get foreground and background colors, maybe allocate colors. */
7006 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
7008 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
7010 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7012 background
= x_alloc_image_color (f
, img
, value
, background
);
7016 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7019 img
->width
, img
->height
,
7020 foreground
, background
,
7024 if (img
->pixmap
== 0)
7026 x_clear_image (f
, img
);
7027 image_error ("Unable to create X pixmap for `%s'", file
, Qnil
);
7035 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
7042 /* Fill image IMG which is used on frame F with pixmap data. Value is
7043 non-zero if successful. */
7051 Lisp_Object file_name
;
7053 xassert (xbm_image_p (img
->spec
));
7055 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7056 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7057 if (STRINGP (file_name
))
7058 success_p
= xbm_load_image_from_file (f
, img
, file_name
);
7061 struct image_keyword fmt
[XBM_LAST
];
7064 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
7065 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
7069 /* Parse the list specification. */
7070 bcopy (xbm_format
, fmt
, sizeof fmt
);
7071 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
7074 /* Get specified width, and height. */
7075 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
7076 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
7077 xassert (img
->width
> 0 && img
->height
> 0);
7081 if (fmt
[XBM_ASCENT
].count
)
7082 img
->ascent
= XFASTINT (fmt
[XBM_ASCENT
].value
);
7084 /* Get foreground and background colors, maybe allocate colors. */
7085 if (fmt
[XBM_FOREGROUND
].count
)
7086 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
7088 if (fmt
[XBM_BACKGROUND
].count
)
7089 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
7092 /* Set bits to the bitmap image data. */
7093 data
= fmt
[XBM_DATA
].value
;
7098 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
7100 p
= bits
= (char *) alloca (nbytes
* img
->height
);
7101 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
7103 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
7105 bcopy (XSTRING (line
)->data
, p
, nbytes
);
7107 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
7110 else if (STRINGP (data
))
7111 bits
= XSTRING (data
)->data
;
7113 bits
= XBOOL_VECTOR (data
)->data
;
7115 /* Create the pixmap. */
7116 depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
7118 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
7121 img
->width
, img
->height
,
7122 foreground
, background
,
7128 image_error ("Unable to create pixmap for XBM image `%s'",
7130 x_clear_image (f
, img
);
7141 /***********************************************************************
7143 ***********************************************************************/
7147 static int xpm_image_p
P_ ((Lisp_Object object
));
7148 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
7149 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
7151 #include "X11/xpm.h"
7153 /* The symbol `xpm' identifying XPM-format images. */
7157 /* Indices of image specification fields in xpm_format, below. */
7159 enum xpm_keyword_index
7173 /* Vector of image_keyword structures describing the format
7174 of valid XPM image specifications. */
7176 static struct image_keyword xpm_format
[XPM_LAST
] =
7178 {":type", IMAGE_SYMBOL_VALUE
, 1},
7179 {":file", IMAGE_STRING_VALUE
, 0},
7180 {":data", IMAGE_STRING_VALUE
, 0},
7181 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7182 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7183 {":relief", IMAGE_INTEGER_VALUE
, 0},
7184 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7185 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7186 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7189 /* Structure describing the image type XBM. */
7191 static struct image_type xpm_type
=
7201 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7202 for XPM images. Such a list must consist of conses whose car and
7206 xpm_valid_color_symbols_p (color_symbols
)
7207 Lisp_Object color_symbols
;
7209 while (CONSP (color_symbols
))
7211 Lisp_Object sym
= XCAR (color_symbols
);
7213 || !STRINGP (XCAR (sym
))
7214 || !STRINGP (XCDR (sym
)))
7216 color_symbols
= XCDR (color_symbols
);
7219 return NILP (color_symbols
);
7223 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7226 xpm_image_p (object
)
7229 struct image_keyword fmt
[XPM_LAST
];
7230 bcopy (xpm_format
, fmt
, sizeof fmt
);
7231 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
7232 /* Either `:file' or `:data' must be present. */
7233 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
7234 /* Either no `:color-symbols' or it's a list of conses
7235 whose car and cdr are strings. */
7236 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
7237 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
))
7238 && (fmt
[XPM_ASCENT
].count
== 0
7239 || XFASTINT (fmt
[XPM_ASCENT
].value
) < 100));
7243 /* Load image IMG which will be displayed on frame F. Value is
7244 non-zero if successful. */
7252 XpmAttributes attrs
;
7253 Lisp_Object specified_file
, color_symbols
;
7255 /* Configure the XPM lib. Use the visual of frame F. Allocate
7256 close colors. Return colors allocated. */
7257 bzero (&attrs
, sizeof attrs
);
7258 attrs
.visual
= FRAME_X_DISPLAY_INFO (f
)->visual
;
7259 attrs
.valuemask
|= XpmVisual
;
7260 attrs
.valuemask
|= XpmReturnAllocPixels
;
7261 #ifdef XpmAllocCloseColors
7262 attrs
.alloc_close_colors
= 1;
7263 attrs
.valuemask
|= XpmAllocCloseColors
;
7265 attrs
.closeness
= 600;
7266 attrs
.valuemask
|= XpmCloseness
;
7269 /* If image specification contains symbolic color definitions, add
7270 these to `attrs'. */
7271 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
7272 if (CONSP (color_symbols
))
7275 XpmColorSymbol
*xpm_syms
;
7278 attrs
.valuemask
|= XpmColorSymbols
;
7280 /* Count number of symbols. */
7281 attrs
.numsymbols
= 0;
7282 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
7285 /* Allocate an XpmColorSymbol array. */
7286 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
7287 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
7288 bzero (xpm_syms
, size
);
7289 attrs
.colorsymbols
= xpm_syms
;
7291 /* Fill the color symbol array. */
7292 for (tail
= color_symbols
, i
= 0;
7294 ++i
, tail
= XCDR (tail
))
7296 Lisp_Object name
= XCAR (XCAR (tail
));
7297 Lisp_Object color
= XCDR (XCAR (tail
));
7298 xpm_syms
[i
].name
= (char *) alloca (XSTRING (name
)->size
+ 1);
7299 strcpy (xpm_syms
[i
].name
, XSTRING (name
)->data
);
7300 xpm_syms
[i
].value
= (char *) alloca (XSTRING (color
)->size
+ 1);
7301 strcpy (xpm_syms
[i
].value
, XSTRING (color
)->data
);
7305 /* Create a pixmap for the image, either from a file, or from a
7306 string buffer containing data in the same format as an XPM file. */
7308 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7309 if (STRINGP (specified_file
))
7311 Lisp_Object file
= x_find_image_file (specified_file
);
7312 if (!STRINGP (file
))
7314 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7319 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7320 XSTRING (file
)->data
, &img
->pixmap
, &img
->mask
,
7325 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
7326 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7327 XSTRING (buffer
)->data
,
7328 &img
->pixmap
, &img
->mask
,
7333 if (rc
== XpmSuccess
)
7335 /* Remember allocated colors. */
7336 img
->ncolors
= attrs
.nalloc_pixels
;
7337 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
7338 * sizeof *img
->colors
);
7339 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
7340 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
7342 img
->width
= attrs
.width
;
7343 img
->height
= attrs
.height
;
7344 xassert (img
->width
> 0 && img
->height
> 0);
7346 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7348 XpmFreeAttributes (&attrs
);
7356 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
7359 case XpmFileInvalid
:
7360 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
7364 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
7367 case XpmColorFailed
:
7368 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
7372 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
7377 return rc
== XpmSuccess
;
7380 #endif /* HAVE_XPM != 0 */
7383 /***********************************************************************
7385 ***********************************************************************/
7387 /* An entry in the color table mapping an RGB color to a pixel color. */
7392 unsigned long pixel
;
7394 /* Next in color table collision list. */
7395 struct ct_color
*next
;
7398 /* The bucket vector size to use. Must be prime. */
7402 /* Value is a hash of the RGB color given by R, G, and B. */
7404 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7406 /* The color hash table. */
7408 struct ct_color
**ct_table
;
7410 /* Number of entries in the color table. */
7412 int ct_colors_allocated
;
7414 /* Function prototypes. */
7416 static void init_color_table
P_ ((void));
7417 static void free_color_table
P_ ((void));
7418 static unsigned long *colors_in_color_table
P_ ((int *n
));
7419 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
7420 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
7423 /* Initialize the color table. */
7428 int size
= CT_SIZE
* sizeof (*ct_table
);
7429 ct_table
= (struct ct_color
**) xmalloc (size
);
7430 bzero (ct_table
, size
);
7431 ct_colors_allocated
= 0;
7435 /* Free memory associated with the color table. */
7441 struct ct_color
*p
, *next
;
7443 for (i
= 0; i
< CT_SIZE
; ++i
)
7444 for (p
= ct_table
[i
]; p
; p
= next
)
7455 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7456 entry for that color already is in the color table, return the
7457 pixel color of that entry. Otherwise, allocate a new color for R,
7458 G, B, and make an entry in the color table. */
7460 static unsigned long
7461 lookup_rgb_color (f
, r
, g
, b
)
7465 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
7466 int i
= hash
% CT_SIZE
;
7469 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7470 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
7484 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7485 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7490 ++ct_colors_allocated
;
7492 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7496 p
->pixel
= color
.pixel
;
7497 p
->next
= ct_table
[i
];
7501 return FRAME_FOREGROUND_PIXEL (f
);
7508 /* Look up pixel color PIXEL which is used on frame F in the color
7509 table. If not already present, allocate it. Value is PIXEL. */
7511 static unsigned long
7512 lookup_pixel_color (f
, pixel
)
7514 unsigned long pixel
;
7516 int i
= pixel
% CT_SIZE
;
7519 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7520 if (p
->pixel
== pixel
)
7531 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7532 color
.pixel
= pixel
;
7533 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
7534 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
7539 ++ct_colors_allocated
;
7541 p
= (struct ct_color
*) xmalloc (sizeof *p
);
7546 p
->next
= ct_table
[i
];
7550 return FRAME_FOREGROUND_PIXEL (f
);
7557 /* Value is a vector of all pixel colors contained in the color table,
7558 allocated via xmalloc. Set *N to the number of colors. */
7560 static unsigned long *
7561 colors_in_color_table (n
)
7566 unsigned long *colors
;
7568 if (ct_colors_allocated
== 0)
7575 colors
= (unsigned long *) xmalloc (ct_colors_allocated
7577 *n
= ct_colors_allocated
;
7579 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
7580 for (p
= ct_table
[i
]; p
; p
= p
->next
)
7581 colors
[j
++] = p
->pixel
;
7589 /***********************************************************************
7591 ***********************************************************************/
7593 static void x_laplace_write_row
P_ ((struct frame
*, long *,
7594 int, XImage
*, int));
7595 static void x_laplace_read_row
P_ ((struct frame
*, Colormap
,
7596 XColor
*, int, XImage
*, int));
7599 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
7600 frame we operate on, CMAP is the color-map in effect, and WIDTH is
7601 the width of one row in the image. */
7604 x_laplace_read_row (f
, cmap
, colors
, width
, ximg
, y
)
7614 for (x
= 0; x
< width
; ++x
)
7615 colors
[x
].pixel
= XGetPixel (ximg
, x
, y
);
7617 XQueryColors (FRAME_X_DISPLAY (f
), cmap
, colors
, width
);
7621 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
7622 containing the pixel colors to write. F is the frame we are
7626 x_laplace_write_row (f
, pixels
, width
, ximg
, y
)
7635 for (x
= 0; x
< width
; ++x
)
7636 XPutPixel (ximg
, x
, y
, pixels
[x
]);
7640 /* Transform image IMG which is used on frame F with a Laplace
7641 edge-detection algorithm. The result is an image that can be used
7642 to draw disabled buttons, for example. */
7649 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7650 XImage
*ximg
, *oimg
;
7656 int in_y
, out_y
, rc
;
7661 /* Get the X image IMG->pixmap. */
7662 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7663 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7665 /* Allocate 3 input rows, and one output row of colors. */
7666 for (i
= 0; i
< 3; ++i
)
7667 in
[i
] = (XColor
*) alloca (img
->width
* sizeof (XColor
));
7668 out
= (long *) alloca (img
->width
* sizeof (long));
7670 /* Create an X image for output. */
7671 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
7674 /* Fill first two rows. */
7675 x_laplace_read_row (f
, cmap
, in
[0], img
->width
, ximg
, 0);
7676 x_laplace_read_row (f
, cmap
, in
[1], img
->width
, ximg
, 1);
7679 /* Write first row, all zeros. */
7680 init_color_table ();
7681 pixel
= lookup_rgb_color (f
, 0, 0, 0);
7682 for (x
= 0; x
< img
->width
; ++x
)
7684 x_laplace_write_row (f
, out
, img
->width
, oimg
, 0);
7687 for (y
= 2; y
< img
->height
; ++y
)
7690 int rowb
= (y
+ 2) % 3;
7692 x_laplace_read_row (f
, cmap
, in
[rowa
], img
->width
, ximg
, in_y
++);
7694 for (x
= 0; x
< img
->width
- 2; ++x
)
7696 int r
= in
[rowa
][x
].red
+ mv2
- in
[rowb
][x
+ 2].red
;
7697 int g
= in
[rowa
][x
].green
+ mv2
- in
[rowb
][x
+ 2].green
;
7698 int b
= in
[rowa
][x
].blue
+ mv2
- in
[rowb
][x
+ 2].blue
;
7700 out
[x
+ 1] = lookup_rgb_color (f
, r
& 0xffff, g
& 0xffff,
7704 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
++);
7707 /* Write last line, all zeros. */
7708 for (x
= 0; x
< img
->width
; ++x
)
7710 x_laplace_write_row (f
, out
, img
->width
, oimg
, out_y
);
7712 /* Free the input image, and free resources of IMG. */
7713 XDestroyImage (ximg
);
7714 x_clear_image (f
, img
);
7716 /* Put the output image into pixmap, and destroy it. */
7717 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
7718 x_destroy_x_image (oimg
);
7720 /* Remember new pixmap and colors in IMG. */
7721 img
->pixmap
= pixmap
;
7722 img
->colors
= colors_in_color_table (&img
->ncolors
);
7723 free_color_table ();
7729 /* Build a mask for image IMG which is used on frame F. FILE is the
7730 name of an image file, for error messages. HOW determines how to
7731 determine the background color of IMG. If it is a list '(R G B)',
7732 with R, G, and B being integers >= 0, take that as the color of the
7733 background. Otherwise, determine the background color of IMG
7734 heuristically. Value is non-zero if successful. */
7737 x_build_heuristic_mask (f
, img
, how
)
7742 Display
*dpy
= FRAME_X_DISPLAY (f
);
7743 XImage
*ximg
, *mask_img
;
7744 int x
, y
, rc
, look_at_corners_p
;
7749 /* Create an image and pixmap serving as mask. */
7750 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
7751 &mask_img
, &img
->mask
);
7758 /* Get the X image of IMG->pixmap. */
7759 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
7762 /* Determine the background color of ximg. If HOW is `(R G B)'
7763 take that as color. Otherwise, try to determine the color
7765 look_at_corners_p
= 1;
7773 && NATNUMP (XCAR (how
)))
7775 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
7779 if (i
== 3 && NILP (how
))
7781 char color_name
[30];
7782 XColor exact
, color
;
7785 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
7787 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
7788 if (XLookupColor (dpy
, cmap
, color_name
, &exact
, &color
))
7791 look_at_corners_p
= 0;
7796 if (look_at_corners_p
)
7798 unsigned long corners
[4];
7801 /* Get the colors at the corners of ximg. */
7802 corners
[0] = XGetPixel (ximg
, 0, 0);
7803 corners
[1] = XGetPixel (ximg
, img
->width
- 1, 0);
7804 corners
[2] = XGetPixel (ximg
, img
->width
- 1, img
->height
- 1);
7805 corners
[3] = XGetPixel (ximg
, 0, img
->height
- 1);
7807 /* Choose the most frequently found color as background. */
7808 for (i
= best_count
= 0; i
< 4; ++i
)
7812 for (j
= n
= 0; j
< 4; ++j
)
7813 if (corners
[i
] == corners
[j
])
7817 bg
= corners
[i
], best_count
= n
;
7821 /* Set all bits in mask_img to 1 whose color in ximg is different
7822 from the background color bg. */
7823 for (y
= 0; y
< img
->height
; ++y
)
7824 for (x
= 0; x
< img
->width
; ++x
)
7825 XPutPixel (mask_img
, x
, y
, XGetPixel (ximg
, x
, y
) != bg
);
7827 /* Put mask_img into img->mask. */
7828 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7829 x_destroy_x_image (mask_img
);
7830 XDestroyImage (ximg
);
7838 /***********************************************************************
7839 PBM (mono, gray, color)
7840 ***********************************************************************/
7842 static int pbm_image_p
P_ ((Lisp_Object object
));
7843 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
7844 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
7846 /* The symbol `pbm' identifying images of this type. */
7850 /* Indices of image specification fields in gs_format, below. */
7852 enum pbm_keyword_index
7865 /* Vector of image_keyword structures describing the format
7866 of valid user-defined image specifications. */
7868 static struct image_keyword pbm_format
[PBM_LAST
] =
7870 {":type", IMAGE_SYMBOL_VALUE
, 1},
7871 {":file", IMAGE_STRING_VALUE
, 0},
7872 {":data", IMAGE_STRING_VALUE
, 0},
7873 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7874 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
7875 {":relief", IMAGE_INTEGER_VALUE
, 0},
7876 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7877 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
7880 /* Structure describing the image type `pbm'. */
7882 static struct image_type pbm_type
=
7892 /* Return non-zero if OBJECT is a valid PBM image specification. */
7895 pbm_image_p (object
)
7898 struct image_keyword fmt
[PBM_LAST
];
7900 bcopy (pbm_format
, fmt
, sizeof fmt
);
7902 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
)
7903 || (fmt
[PBM_ASCENT
].count
7904 && XFASTINT (fmt
[PBM_ASCENT
].value
) > 100))
7907 /* Must specify either :data or :file. */
7908 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
7912 /* Scan a decimal number from *S and return it. Advance *S while
7913 reading the number. END is the end of the string. Value is -1 at
7917 pbm_scan_number (s
, end
)
7918 unsigned char **s
, *end
;
7924 /* Skip white-space. */
7925 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
7930 /* Skip comment to end of line. */
7931 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
7934 else if (isdigit (c
))
7936 /* Read decimal number. */
7938 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
7939 val
= 10 * val
+ c
- '0';
7950 /* Read FILE into memory. Value is a pointer to a buffer allocated
7951 with xmalloc holding FILE's contents. Value is null if an error
7952 occured. *SIZE is set to the size of the file. */
7955 pbm_read_file (file
, size
)
7963 if (stat (XSTRING (file
)->data
, &st
) == 0
7964 && (fp
= fopen (XSTRING (file
)->data
, "r")) != NULL
7965 && (buf
= (char *) xmalloc (st
.st_size
),
7966 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
7986 /* Load PBM image IMG for use on frame F. */
7994 int width
, height
, max_color_idx
= 0;
7996 Lisp_Object file
, specified_file
;
7997 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
7998 struct gcpro gcpro1
;
7999 unsigned char *contents
= NULL
;
8000 unsigned char *end
, *p
;
8003 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8007 if (STRINGP (specified_file
))
8009 file
= x_find_image_file (specified_file
);
8010 if (!STRINGP (file
))
8012 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8017 contents
= pbm_read_file (file
, &size
);
8018 if (contents
== NULL
)
8020 image_error ("Error reading `%s'", file
, Qnil
);
8026 end
= contents
+ size
;
8031 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8032 p
= XSTRING (data
)->data
;
8033 end
= p
+ STRING_BYTES (XSTRING (data
));
8036 /* Check magic number. */
8037 if (end
- p
< 2 || *p
++ != 'P')
8039 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8049 raw_p
= 0, type
= PBM_MONO
;
8053 raw_p
= 0, type
= PBM_GRAY
;
8057 raw_p
= 0, type
= PBM_COLOR
;
8061 raw_p
= 1, type
= PBM_MONO
;
8065 raw_p
= 1, type
= PBM_GRAY
;
8069 raw_p
= 1, type
= PBM_COLOR
;
8073 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
8077 /* Read width, height, maximum color-component. Characters
8078 starting with `#' up to the end of a line are ignored. */
8079 width
= pbm_scan_number (&p
, end
);
8080 height
= pbm_scan_number (&p
, end
);
8082 if (type
!= PBM_MONO
)
8084 max_color_idx
= pbm_scan_number (&p
, end
);
8085 if (raw_p
&& max_color_idx
> 255)
8086 max_color_idx
= 255;
8091 || (type
!= PBM_MONO
&& max_color_idx
< 0))
8095 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
8096 &ximg
, &img
->pixmap
))
8102 /* Initialize the color hash table. */
8103 init_color_table ();
8105 if (type
== PBM_MONO
)
8109 for (y
= 0; y
< height
; ++y
)
8110 for (x
= 0; x
< width
; ++x
)
8120 g
= pbm_scan_number (&p
, end
);
8122 XPutPixel (ximg
, x
, y
, (g
8123 ? FRAME_FOREGROUND_PIXEL (f
)
8124 : FRAME_BACKGROUND_PIXEL (f
)));
8129 for (y
= 0; y
< height
; ++y
)
8130 for (x
= 0; x
< width
; ++x
)
8134 if (type
== PBM_GRAY
)
8135 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
8144 r
= pbm_scan_number (&p
, end
);
8145 g
= pbm_scan_number (&p
, end
);
8146 b
= pbm_scan_number (&p
, end
);
8149 if (r
< 0 || g
< 0 || b
< 0)
8153 XDestroyImage (ximg
);
8155 image_error ("Invalid pixel value in image `%s'",
8160 /* RGB values are now in the range 0..max_color_idx.
8161 Scale this to the range 0..0xffff supported by X. */
8162 r
= (double) r
* 65535 / max_color_idx
;
8163 g
= (double) g
* 65535 / max_color_idx
;
8164 b
= (double) b
* 65535 / max_color_idx
;
8165 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8169 /* Store in IMG->colors the colors allocated for the image, and
8170 free the color table. */
8171 img
->colors
= colors_in_color_table (&img
->ncolors
);
8172 free_color_table ();
8174 /* Put the image into a pixmap. */
8175 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8176 x_destroy_x_image (ximg
);
8180 img
->height
= height
;
8189 /***********************************************************************
8191 ***********************************************************************/
8197 /* Function prototypes. */
8199 static int png_image_p
P_ ((Lisp_Object object
));
8200 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
8202 /* The symbol `png' identifying images of this type. */
8206 /* Indices of image specification fields in png_format, below. */
8208 enum png_keyword_index
8221 /* Vector of image_keyword structures describing the format
8222 of valid user-defined image specifications. */
8224 static struct image_keyword png_format
[PNG_LAST
] =
8226 {":type", IMAGE_SYMBOL_VALUE
, 1},
8227 {":data", IMAGE_STRING_VALUE
, 0},
8228 {":file", IMAGE_STRING_VALUE
, 0},
8229 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8230 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8231 {":relief", IMAGE_INTEGER_VALUE
, 0},
8232 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8233 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8236 /* Structure describing the image type `png'. */
8238 static struct image_type png_type
=
8248 /* Return non-zero if OBJECT is a valid PNG image specification. */
8251 png_image_p (object
)
8254 struct image_keyword fmt
[PNG_LAST
];
8255 bcopy (png_format
, fmt
, sizeof fmt
);
8257 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
)
8258 || (fmt
[PNG_ASCENT
].count
8259 && XFASTINT (fmt
[PNG_ASCENT
].value
) > 100))
8262 /* Must specify either the :data or :file keyword. */
8263 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
8267 /* Error and warning handlers installed when the PNG library
8271 my_png_error (png_ptr
, msg
)
8272 png_struct
*png_ptr
;
8275 xassert (png_ptr
!= NULL
);
8276 image_error ("PNG error: %s", build_string (msg
), Qnil
);
8277 longjmp (png_ptr
->jmpbuf
, 1);
8282 my_png_warning (png_ptr
, msg
)
8283 png_struct
*png_ptr
;
8286 xassert (png_ptr
!= NULL
);
8287 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
8290 /* Memory source for PNG decoding. */
8292 struct png_memory_storage
8294 unsigned char *bytes
; /* The data */
8295 size_t len
; /* How big is it? */
8296 int index
; /* Where are we? */
8300 /* Function set as reader function when reading PNG image from memory.
8301 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8302 bytes from the input to DATA. */
8305 png_read_from_memory (png_ptr
, data
, length
)
8306 png_structp png_ptr
;
8310 struct png_memory_storage
*tbr
8311 = (struct png_memory_storage
*) png_get_io_ptr (png_ptr
);
8313 if (length
> tbr
->len
- tbr
->index
)
8314 png_error (png_ptr
, "Read error");
8316 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
8317 tbr
->index
= tbr
->index
+ length
;
8320 /* Load PNG image IMG for use on frame F. Value is non-zero if
8328 Lisp_Object file
, specified_file
;
8329 Lisp_Object specified_data
;
8331 XImage
*ximg
, *mask_img
= NULL
;
8332 struct gcpro gcpro1
;
8333 png_struct
*png_ptr
= NULL
;
8334 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
8337 png_byte
*pixels
= NULL
;
8338 png_byte
**rows
= NULL
;
8339 png_uint_32 width
, height
;
8340 int bit_depth
, color_type
, interlace_type
;
8342 png_uint_32 row_bytes
;
8345 double screen_gamma
, image_gamma
;
8347 struct png_memory_storage tbr
; /* Data to be read */
8349 /* Find out what file to load. */
8350 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8351 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8355 if (NILP (specified_data
))
8357 file
= x_find_image_file (specified_file
);
8358 if (!STRINGP (file
))
8360 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8365 /* Open the image file. */
8366 fp
= fopen (XSTRING (file
)->data
, "rb");
8369 image_error ("Cannot open image file `%s'", file
, Qnil
);
8375 /* Check PNG signature. */
8376 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
8377 || !png_check_sig (sig
, sizeof sig
))
8379 image_error ("Not a PNG file: `%s'", file
, Qnil
);
8387 /* Read from memory. */
8388 tbr
.bytes
= XSTRING (specified_data
)->data
;
8389 tbr
.len
= STRING_BYTES (XSTRING (specified_data
));
8392 /* Check PNG signature. */
8393 if (tbr
.len
< sizeof sig
8394 || !png_check_sig (tbr
.bytes
, sizeof sig
))
8396 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
8401 /* Need to skip past the signature. */
8402 tbr
.bytes
+= sizeof (sig
);
8405 /* Initialize read and info structs for PNG lib. */
8406 png_ptr
= png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
8407 my_png_error
, my_png_warning
);
8410 if (fp
) fclose (fp
);
8415 info_ptr
= png_create_info_struct (png_ptr
);
8418 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
8419 if (fp
) fclose (fp
);
8424 end_info
= png_create_info_struct (png_ptr
);
8427 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
8428 if (fp
) fclose (fp
);
8433 /* Set error jump-back. We come back here when the PNG library
8434 detects an error. */
8435 if (setjmp (png_ptr
->jmpbuf
))
8439 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8442 if (fp
) fclose (fp
);
8447 /* Read image info. */
8448 if (!NILP (specified_data
))
8449 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
8451 png_init_io (png_ptr
, fp
);
8453 png_set_sig_bytes (png_ptr
, sizeof sig
);
8454 png_read_info (png_ptr
, info_ptr
);
8455 png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
8456 &interlace_type
, NULL
, NULL
);
8458 /* If image contains simply transparency data, we prefer to
8459 construct a clipping mask. */
8460 if (png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
8465 /* This function is easier to write if we only have to handle
8466 one data format: RGB or RGBA with 8 bits per channel. Let's
8467 transform other formats into that format. */
8469 /* Strip more than 8 bits per channel. */
8470 if (bit_depth
== 16)
8471 png_set_strip_16 (png_ptr
);
8473 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8475 png_set_expand (png_ptr
);
8477 /* Convert grayscale images to RGB. */
8478 if (color_type
== PNG_COLOR_TYPE_GRAY
8479 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
8480 png_set_gray_to_rgb (png_ptr
);
8482 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8483 gamma_str
= getenv ("SCREEN_GAMMA");
8484 screen_gamma
= gamma_str
? atof (gamma_str
) : 2.2;
8486 /* Tell the PNG lib to handle gamma correction for us. */
8488 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8489 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
8490 /* There is a special chunk in the image specifying the gamma. */
8491 png_set_sRGB (png_ptr
, info_ptr
, intent
);
8494 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
8495 /* Image contains gamma information. */
8496 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
8498 /* Use a default of 0.5 for the image gamma. */
8499 png_set_gamma (png_ptr
, screen_gamma
, 0.5);
8501 /* Handle alpha channel by combining the image with a background
8502 color. Do this only if a real alpha channel is supplied. For
8503 simple transparency, we prefer a clipping mask. */
8506 png_color_16
*image_background
;
8508 if (png_get_bKGD (png_ptr
, info_ptr
, &image_background
))
8509 /* Image contains a background color with which to
8510 combine the image. */
8511 png_set_background (png_ptr
, image_background
,
8512 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
8515 /* Image does not contain a background color with which
8516 to combine the image data via an alpha channel. Use
8517 the frame's background instead. */
8520 png_color_16 frame_background
;
8523 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
8524 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8525 XQueryColor (FRAME_X_DISPLAY (f
), cmap
, &color
);
8528 bzero (&frame_background
, sizeof frame_background
);
8529 frame_background
.red
= color
.red
;
8530 frame_background
.green
= color
.green
;
8531 frame_background
.blue
= color
.blue
;
8533 png_set_background (png_ptr
, &frame_background
,
8534 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
8538 /* Update info structure. */
8539 png_read_update_info (png_ptr
, info_ptr
);
8541 /* Get number of channels. Valid values are 1 for grayscale images
8542 and images with a palette, 2 for grayscale images with transparency
8543 information (alpha channel), 3 for RGB images, and 4 for RGB
8544 images with alpha channel, i.e. RGBA. If conversions above were
8545 sufficient we should only have 3 or 4 channels here. */
8546 channels
= png_get_channels (png_ptr
, info_ptr
);
8547 xassert (channels
== 3 || channels
== 4);
8549 /* Number of bytes needed for one row of the image. */
8550 row_bytes
= png_get_rowbytes (png_ptr
, info_ptr
);
8552 /* Allocate memory for the image. */
8553 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
8554 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
8555 for (i
= 0; i
< height
; ++i
)
8556 rows
[i
] = pixels
+ i
* row_bytes
;
8558 /* Read the entire image. */
8559 png_read_image (png_ptr
, rows
);
8560 png_read_end (png_ptr
, info_ptr
);
8569 /* Create the X image and pixmap. */
8570 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
8577 /* Create an image and pixmap serving as mask if the PNG image
8578 contains an alpha channel. */
8581 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
8582 &mask_img
, &img
->mask
))
8584 x_destroy_x_image (ximg
);
8585 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
8591 /* Fill the X image and mask from PNG data. */
8592 init_color_table ();
8594 for (y
= 0; y
< height
; ++y
)
8596 png_byte
*p
= rows
[y
];
8598 for (x
= 0; x
< width
; ++x
)
8605 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
8607 /* An alpha channel, aka mask channel, associates variable
8608 transparency with an image. Where other image formats
8609 support binary transparency---fully transparent or fully
8610 opaque---PNG allows up to 254 levels of partial transparency.
8611 The PNG library implements partial transparency by combining
8612 the image with a specified background color.
8614 I'm not sure how to handle this here nicely: because the
8615 background on which the image is displayed may change, for
8616 real alpha channel support, it would be necessary to create
8617 a new image for each possible background.
8619 What I'm doing now is that a mask is created if we have
8620 boolean transparency information. Otherwise I'm using
8621 the frame's background color to combine the image with. */
8626 XPutPixel (mask_img
, x
, y
, *p
> 0);
8632 /* Remember colors allocated for this image. */
8633 img
->colors
= colors_in_color_table (&img
->ncolors
);
8634 free_color_table ();
8637 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
8642 img
->height
= height
;
8644 /* Put the image into the pixmap, then free the X image and its buffer. */
8645 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8646 x_destroy_x_image (ximg
);
8648 /* Same for the mask. */
8651 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
8652 x_destroy_x_image (mask_img
);
8660 #endif /* HAVE_PNG != 0 */
8664 /***********************************************************************
8666 ***********************************************************************/
8670 /* Work around a warning about HAVE_STDLIB_H being redefined in
8672 #ifdef HAVE_STDLIB_H
8673 #define HAVE_STDLIB_H_1
8674 #undef HAVE_STDLIB_H
8675 #endif /* HAVE_STLIB_H */
8677 #include <jpeglib.h>
8681 #ifdef HAVE_STLIB_H_1
8682 #define HAVE_STDLIB_H 1
8685 static int jpeg_image_p
P_ ((Lisp_Object object
));
8686 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
8688 /* The symbol `jpeg' identifying images of this type. */
8692 /* Indices of image specification fields in gs_format, below. */
8694 enum jpeg_keyword_index
8703 JPEG_HEURISTIC_MASK
,
8707 /* Vector of image_keyword structures describing the format
8708 of valid user-defined image specifications. */
8710 static struct image_keyword jpeg_format
[JPEG_LAST
] =
8712 {":type", IMAGE_SYMBOL_VALUE
, 1},
8713 {":data", IMAGE_STRING_VALUE
, 0},
8714 {":file", IMAGE_STRING_VALUE
, 0},
8715 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8716 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
8717 {":relief", IMAGE_INTEGER_VALUE
, 0},
8718 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8719 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
8722 /* Structure describing the image type `jpeg'. */
8724 static struct image_type jpeg_type
=
8734 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8737 jpeg_image_p (object
)
8740 struct image_keyword fmt
[JPEG_LAST
];
8742 bcopy (jpeg_format
, fmt
, sizeof fmt
);
8744 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
)
8745 || (fmt
[JPEG_ASCENT
].count
8746 && XFASTINT (fmt
[JPEG_ASCENT
].value
) > 100))
8749 /* Must specify either the :data or :file keyword. */
8750 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
8754 struct my_jpeg_error_mgr
8756 struct jpeg_error_mgr pub
;
8757 jmp_buf setjmp_buffer
;
8761 my_error_exit (cinfo
)
8764 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
8765 longjmp (mgr
->setjmp_buffer
, 1);
8768 /* Init source method for JPEG data source manager. Called by
8769 jpeg_read_header() before any data is actually read. See
8770 libjpeg.doc from the JPEG lib distribution. */
8773 our_init_source (cinfo
)
8774 j_decompress_ptr cinfo
;
8779 /* Fill input buffer method for JPEG data source manager. Called
8780 whenever more data is needed. We read the whole image in one step,
8781 so this only adds a fake end of input marker at the end. */
8784 our_fill_input_buffer (cinfo
)
8785 j_decompress_ptr cinfo
;
8787 /* Insert a fake EOI marker. */
8788 struct jpeg_source_mgr
*src
= cinfo
->src
;
8789 static JOCTET buffer
[2];
8791 buffer
[0] = (JOCTET
) 0xFF;
8792 buffer
[1] = (JOCTET
) JPEG_EOI
;
8794 src
->next_input_byte
= buffer
;
8795 src
->bytes_in_buffer
= 2;
8800 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8801 is the JPEG data source manager. */
8804 our_skip_input_data (cinfo
, num_bytes
)
8805 j_decompress_ptr cinfo
;
8808 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8812 if (num_bytes
> src
->bytes_in_buffer
)
8813 ERREXIT (cinfo
, JERR_INPUT_EOF
);
8815 src
->bytes_in_buffer
-= num_bytes
;
8816 src
->next_input_byte
+= num_bytes
;
8821 /* Method to terminate data source. Called by
8822 jpeg_finish_decompress() after all data has been processed. */
8825 our_term_source (cinfo
)
8826 j_decompress_ptr cinfo
;
8831 /* Set up the JPEG lib for reading an image from DATA which contains
8832 LEN bytes. CINFO is the decompression info structure created for
8833 reading the image. */
8836 jpeg_memory_src (cinfo
, data
, len
)
8837 j_decompress_ptr cinfo
;
8841 struct jpeg_source_mgr
*src
;
8843 if (cinfo
->src
== NULL
)
8845 /* First time for this JPEG object? */
8846 cinfo
->src
= (struct jpeg_source_mgr
*)
8847 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
8848 sizeof (struct jpeg_source_mgr
));
8849 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8850 src
->next_input_byte
= data
;
8853 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
8854 src
->init_source
= our_init_source
;
8855 src
->fill_input_buffer
= our_fill_input_buffer
;
8856 src
->skip_input_data
= our_skip_input_data
;
8857 src
->resync_to_restart
= jpeg_resync_to_restart
; /* Use default method. */
8858 src
->term_source
= our_term_source
;
8859 src
->bytes_in_buffer
= len
;
8860 src
->next_input_byte
= data
;
8864 /* Load image IMG for use on frame F. Patterned after example.c
8865 from the JPEG lib. */
8872 struct jpeg_decompress_struct cinfo
;
8873 struct my_jpeg_error_mgr mgr
;
8874 Lisp_Object file
, specified_file
;
8875 Lisp_Object specified_data
;
8878 int row_stride
, x
, y
;
8879 XImage
*ximg
= NULL
;
8881 unsigned long *colors
;
8883 struct gcpro gcpro1
;
8885 /* Open the JPEG file. */
8886 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8887 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8891 if (NILP (specified_data
))
8893 file
= x_find_image_file (specified_file
);
8894 if (!STRINGP (file
))
8896 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8901 fp
= fopen (XSTRING (file
)->data
, "r");
8904 image_error ("Cannot open `%s'", file
, Qnil
);
8910 /* Customize libjpeg's error handling to call my_error_exit when an
8911 error is detected. This function will perform a longjmp. */
8912 mgr
.pub
.error_exit
= my_error_exit
;
8913 cinfo
.err
= jpeg_std_error (&mgr
.pub
);
8915 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
8919 /* Called from my_error_exit. Display a JPEG error. */
8920 char buffer
[JMSG_LENGTH_MAX
];
8921 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
8922 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
8923 build_string (buffer
));
8926 /* Close the input file and destroy the JPEG object. */
8929 jpeg_destroy_decompress (&cinfo
);
8933 /* If we already have an XImage, free that. */
8934 x_destroy_x_image (ximg
);
8936 /* Free pixmap and colors. */
8937 x_clear_image (f
, img
);
8944 /* Create the JPEG decompression object. Let it read from fp.
8945 Read the JPEG image header. */
8946 jpeg_create_decompress (&cinfo
);
8948 if (NILP (specified_data
))
8949 jpeg_stdio_src (&cinfo
, fp
);
8951 jpeg_memory_src (&cinfo
, XSTRING (specified_data
)->data
,
8952 STRING_BYTES (XSTRING (specified_data
)));
8954 jpeg_read_header (&cinfo
, TRUE
);
8956 /* Customize decompression so that color quantization will be used.
8957 Start decompression. */
8958 cinfo
.quantize_colors
= TRUE
;
8959 jpeg_start_decompress (&cinfo
);
8960 width
= img
->width
= cinfo
.output_width
;
8961 height
= img
->height
= cinfo
.output_height
;
8965 /* Create X image and pixmap. */
8966 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8969 longjmp (mgr
.setjmp_buffer
, 2);
8972 /* Allocate colors. When color quantization is used,
8973 cinfo.actual_number_of_colors has been set with the number of
8974 colors generated, and cinfo.colormap is a two-dimensional array
8975 of color indices in the range 0..cinfo.actual_number_of_colors.
8976 No more than 255 colors will be generated. */
8980 if (cinfo
.out_color_components
> 2)
8981 ir
= 0, ig
= 1, ib
= 2;
8982 else if (cinfo
.out_color_components
> 1)
8983 ir
= 0, ig
= 1, ib
= 0;
8985 ir
= 0, ig
= 0, ib
= 0;
8987 /* Use the color table mechanism because it handles colors that
8988 cannot be allocated nicely. Such colors will be replaced with
8989 a default color, and we don't have to care about which colors
8990 can be freed safely, and which can't. */
8991 init_color_table ();
8992 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
8995 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
8997 /* Multiply RGB values with 255 because X expects RGB values
8998 in the range 0..0xffff. */
8999 int r
= cinfo
.colormap
[ir
][i
] << 8;
9000 int g
= cinfo
.colormap
[ig
][i
] << 8;
9001 int b
= cinfo
.colormap
[ib
][i
] << 8;
9002 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9005 /* Remember those colors actually allocated. */
9006 img
->colors
= colors_in_color_table (&img
->ncolors
);
9007 free_color_table ();
9011 row_stride
= width
* cinfo
.output_components
;
9012 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
9014 for (y
= 0; y
< height
; ++y
)
9016 jpeg_read_scanlines (&cinfo
, buffer
, 1);
9017 for (x
= 0; x
< cinfo
.output_width
; ++x
)
9018 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
9022 jpeg_finish_decompress (&cinfo
);
9023 jpeg_destroy_decompress (&cinfo
);
9027 /* Put the image into the pixmap. */
9028 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9029 x_destroy_x_image (ximg
);
9035 #endif /* HAVE_JPEG */
9039 /***********************************************************************
9041 ***********************************************************************/
9047 static int tiff_image_p
P_ ((Lisp_Object object
));
9048 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
9050 /* The symbol `tiff' identifying images of this type. */
9054 /* Indices of image specification fields in tiff_format, below. */
9056 enum tiff_keyword_index
9065 TIFF_HEURISTIC_MASK
,
9069 /* Vector of image_keyword structures describing the format
9070 of valid user-defined image specifications. */
9072 static struct image_keyword tiff_format
[TIFF_LAST
] =
9074 {":type", IMAGE_SYMBOL_VALUE
, 1},
9075 {":data", IMAGE_STRING_VALUE
, 0},
9076 {":file", IMAGE_STRING_VALUE
, 0},
9077 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9078 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9079 {":relief", IMAGE_INTEGER_VALUE
, 0},
9080 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9081 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9084 /* Structure describing the image type `tiff'. */
9086 static struct image_type tiff_type
=
9096 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9099 tiff_image_p (object
)
9102 struct image_keyword fmt
[TIFF_LAST
];
9103 bcopy (tiff_format
, fmt
, sizeof fmt
);
9105 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
)
9106 || (fmt
[TIFF_ASCENT
].count
9107 && XFASTINT (fmt
[TIFF_ASCENT
].value
) > 100))
9110 /* Must specify either the :data or :file keyword. */
9111 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
9115 /* Reading from a memory buffer for TIFF images Based on the PNG
9116 memory source, but we have to provide a lot of extra functions.
9119 We really only need to implement read and seek, but I am not
9120 convinced that the TIFF library is smart enough not to destroy
9121 itself if we only hand it the function pointers we need to
9126 unsigned char *bytes
;
9133 tiff_read_from_memory (data
, buf
, size
)
9138 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9140 if (size
> src
->len
- src
->index
)
9142 bcopy (src
->bytes
+ src
->index
, buf
, size
);
9148 tiff_write_from_memory (data
, buf
, size
)
9157 tiff_seek_in_memory (data
, off
, whence
)
9162 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
9167 case SEEK_SET
: /* Go from beginning of source. */
9171 case SEEK_END
: /* Go from end of source. */
9172 idx
= src
->len
+ off
;
9175 case SEEK_CUR
: /* Go from current position. */
9176 idx
= src
->index
+ off
;
9179 default: /* Invalid `whence'. */
9183 if (idx
> src
->len
|| idx
< 0)
9191 tiff_close_memory (data
)
9199 tiff_mmap_memory (data
, pbase
, psize
)
9204 /* It is already _IN_ memory. */
9209 tiff_unmap_memory (data
, base
, size
)
9214 /* We don't need to do this. */
9218 tiff_size_of_memory (data
)
9221 return ((tiff_memory_source
*) data
)->len
;
9224 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9232 Lisp_Object file
, specified_file
;
9233 Lisp_Object specified_data
;
9235 int width
, height
, x
, y
;
9239 struct gcpro gcpro1
;
9240 tiff_memory_source memsrc
;
9242 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9243 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9247 if (NILP (specified_data
))
9249 /* Read from a file */
9250 file
= x_find_image_file (specified_file
);
9251 if (!STRINGP (file
))
9253 image_error ("Cannot find image file `%s'", file
, Qnil
);
9258 /* Try to open the image file. */
9259 tiff
= TIFFOpen (XSTRING (file
)->data
, "r");
9262 image_error ("Cannot open `%s'", file
, Qnil
);
9269 /* Memory source! */
9270 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9271 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9274 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
9275 (TIFFReadWriteProc
) tiff_read_from_memory
,
9276 (TIFFReadWriteProc
) tiff_write_from_memory
,
9277 tiff_seek_in_memory
,
9279 tiff_size_of_memory
,
9285 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
9291 /* Get width and height of the image, and allocate a raster buffer
9292 of width x height 32-bit values. */
9293 TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
9294 TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
9295 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
9297 rc
= TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
9301 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
9309 /* Create the X image and pixmap. */
9310 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9318 /* Initialize the color table. */
9319 init_color_table ();
9321 /* Process the pixel raster. Origin is in the lower-left corner. */
9322 for (y
= 0; y
< height
; ++y
)
9324 uint32
*row
= buf
+ y
* width
;
9326 for (x
= 0; x
< width
; ++x
)
9328 uint32 abgr
= row
[x
];
9329 int r
= TIFFGetR (abgr
) << 8;
9330 int g
= TIFFGetG (abgr
) << 8;
9331 int b
= TIFFGetB (abgr
) << 8;
9332 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
9336 /* Remember the colors allocated for the image. Free the color table. */
9337 img
->colors
= colors_in_color_table (&img
->ncolors
);
9338 free_color_table ();
9340 /* Put the image into the pixmap, then free the X image and its buffer. */
9341 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9342 x_destroy_x_image (ximg
);
9347 img
->height
= height
;
9353 #endif /* HAVE_TIFF != 0 */
9357 /***********************************************************************
9359 ***********************************************************************/
9363 #include <gif_lib.h>
9365 static int gif_image_p
P_ ((Lisp_Object object
));
9366 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
9368 /* The symbol `gif' identifying images of this type. */
9372 /* Indices of image specification fields in gif_format, below. */
9374 enum gif_keyword_index
9388 /* Vector of image_keyword structures describing the format
9389 of valid user-defined image specifications. */
9391 static struct image_keyword gif_format
[GIF_LAST
] =
9393 {":type", IMAGE_SYMBOL_VALUE
, 1},
9394 {":data", IMAGE_STRING_VALUE
, 0},
9395 {":file", IMAGE_STRING_VALUE
, 0},
9396 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9397 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9398 {":relief", IMAGE_INTEGER_VALUE
, 0},
9399 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9400 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9401 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
9404 /* Structure describing the image type `gif'. */
9406 static struct image_type gif_type
=
9415 /* Return non-zero if OBJECT is a valid GIF image specification. */
9418 gif_image_p (object
)
9421 struct image_keyword fmt
[GIF_LAST
];
9422 bcopy (gif_format
, fmt
, sizeof fmt
);
9424 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
)
9425 || (fmt
[GIF_ASCENT
].count
9426 && XFASTINT (fmt
[GIF_ASCENT
].value
) > 100))
9429 /* Must specify either the :data or :file keyword. */
9430 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
9433 /* Reading a GIF image from memory
9434 Based on the PNG memory stuff to a certain extent. */
9438 unsigned char *bytes
;
9444 /* Make the current memory source available to gif_read_from_memory.
9445 It's done this way because not all versions of libungif support
9446 a UserData field in the GifFileType structure. */
9447 static gif_memory_source
*current_gif_memory_src
;
9450 gif_read_from_memory (file
, buf
, len
)
9455 gif_memory_source
*src
= current_gif_memory_src
;
9457 if (len
> src
->len
- src
->index
)
9460 bcopy (src
->bytes
+ src
->index
, buf
, len
);
9466 /* Load GIF image IMG for use on frame F. Value is non-zero if
9474 Lisp_Object file
, specified_file
;
9475 Lisp_Object specified_data
;
9476 int rc
, width
, height
, x
, y
, i
;
9478 ColorMapObject
*gif_color_map
;
9479 unsigned long pixel_colors
[256];
9481 struct gcpro gcpro1
;
9483 int ino
, image_left
, image_top
, image_width
, image_height
;
9484 gif_memory_source memsrc
;
9485 unsigned char *raster
;
9487 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
9488 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
9492 if (NILP (specified_data
))
9494 file
= x_find_image_file (specified_file
);
9495 if (!STRINGP (file
))
9497 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
9502 /* Open the GIF file. */
9503 gif
= DGifOpenFileName (XSTRING (file
)->data
);
9506 image_error ("Cannot open `%s'", file
, Qnil
);
9513 /* Read from memory! */
9514 current_gif_memory_src
= &memsrc
;
9515 memsrc
.bytes
= XSTRING (specified_data
)->data
;
9516 memsrc
.len
= STRING_BYTES (XSTRING (specified_data
));
9519 gif
= DGifOpen(&memsrc
, gif_read_from_memory
);
9522 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
9528 /* Read entire contents. */
9529 rc
= DGifSlurp (gif
);
9530 if (rc
== GIF_ERROR
)
9532 image_error ("Error reading `%s'", img
->spec
, Qnil
);
9533 DGifCloseFile (gif
);
9538 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
9539 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
9540 if (ino
>= gif
->ImageCount
)
9542 image_error ("Invalid image number `%s' in image `%s'",
9544 DGifCloseFile (gif
);
9549 width
= img
->width
= gif
->SWidth
;
9550 height
= img
->height
= gif
->SHeight
;
9554 /* Create the X image and pixmap. */
9555 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
9558 DGifCloseFile (gif
);
9563 /* Allocate colors. */
9564 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
9566 gif_color_map
= gif
->SColorMap
;
9567 init_color_table ();
9568 bzero (pixel_colors
, sizeof pixel_colors
);
9570 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
9572 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
9573 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
9574 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
9575 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
9578 img
->colors
= colors_in_color_table (&img
->ncolors
);
9579 free_color_table ();
9581 /* Clear the part of the screen image that are not covered by
9582 the image from the GIF file. Full animated GIF support
9583 requires more than can be done here (see the gif89 spec,
9584 disposal methods). Let's simply assume that the part
9585 not covered by a sub-image is in the frame's background color. */
9586 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
9587 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
9588 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
9589 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
9591 for (y
= 0; y
< image_top
; ++y
)
9592 for (x
= 0; x
< width
; ++x
)
9593 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9595 for (y
= image_top
+ image_height
; y
< height
; ++y
)
9596 for (x
= 0; x
< width
; ++x
)
9597 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9599 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
9601 for (x
= 0; x
< image_left
; ++x
)
9602 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9603 for (x
= image_left
+ image_width
; x
< width
; ++x
)
9604 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
9607 /* Read the GIF image into the X image. We use a local variable
9608 `raster' here because RasterBits below is a char *, and invites
9609 problems with bytes >= 0x80. */
9610 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
9612 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
9614 static int interlace_start
[] = {0, 4, 2, 1};
9615 static int interlace_increment
[] = {8, 8, 4, 2};
9617 int row
= interlace_start
[0];
9621 for (y
= 0; y
< image_height
; y
++)
9623 if (row
>= image_height
)
9625 row
= interlace_start
[++pass
];
9626 while (row
>= image_height
)
9627 row
= interlace_start
[++pass
];
9630 for (x
= 0; x
< image_width
; x
++)
9632 int i
= raster
[(y
* image_width
) + x
];
9633 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
9637 row
+= interlace_increment
[pass
];
9642 for (y
= 0; y
< image_height
; ++y
)
9643 for (x
= 0; x
< image_width
; ++x
)
9645 int i
= raster
[y
* image_width
+ x
];
9646 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
9650 DGifCloseFile (gif
);
9652 /* Put the image into the pixmap, then free the X image and its buffer. */
9653 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9654 x_destroy_x_image (ximg
);
9661 #endif /* HAVE_GIF != 0 */
9665 /***********************************************************************
9667 ***********************************************************************/
9669 static int gs_image_p
P_ ((Lisp_Object object
));
9670 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9671 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9673 /* The symbol `postscript' identifying images of this type. */
9675 Lisp_Object Qpostscript
;
9677 /* Keyword symbols. */
9679 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9681 /* Indices of image specification fields in gs_format, below. */
9683 enum gs_keyword_index
9699 /* Vector of image_keyword structures describing the format
9700 of valid user-defined image specifications. */
9702 static struct image_keyword gs_format
[GS_LAST
] =
9704 {":type", IMAGE_SYMBOL_VALUE
, 1},
9705 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9706 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9707 {":file", IMAGE_STRING_VALUE
, 1},
9708 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9709 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9710 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
9711 {":margin", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
9712 {":relief", IMAGE_INTEGER_VALUE
, 0},
9713 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9714 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
9717 /* Structure describing the image type `ghostscript'. */
9719 static struct image_type gs_type
=
9729 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9732 gs_clear_image (f
, img
)
9736 /* IMG->data.ptr_val may contain a recorded colormap. */
9737 xfree (img
->data
.ptr_val
);
9738 x_clear_image (f
, img
);
9742 /* Return non-zero if OBJECT is a valid Ghostscript image
9749 struct image_keyword fmt
[GS_LAST
];
9753 bcopy (gs_format
, fmt
, sizeof fmt
);
9755 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
)
9756 || (fmt
[GS_ASCENT
].count
9757 && XFASTINT (fmt
[GS_ASCENT
].value
) > 100))
9760 /* Bounding box must be a list or vector containing 4 integers. */
9761 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9764 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9765 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9770 else if (VECTORP (tem
))
9772 if (XVECTOR (tem
)->size
!= 4)
9774 for (i
= 0; i
< 4; ++i
)
9775 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9785 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9794 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9795 struct gcpro gcpro1
, gcpro2
;
9797 double in_width
, in_height
;
9798 Lisp_Object pixel_colors
= Qnil
;
9800 /* Compute pixel size of pixmap needed from the given size in the
9801 image specification. Sizes in the specification are in pt. 1 pt
9802 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9804 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9805 in_width
= XFASTINT (pt_width
) / 72.0;
9806 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9807 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9808 in_height
= XFASTINT (pt_height
) / 72.0;
9809 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9811 /* Create the pixmap. */
9813 xassert (img
->pixmap
== 0);
9814 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9815 img
->width
, img
->height
,
9816 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9821 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9825 /* Call the loader to fill the pixmap. It returns a process object
9826 if successful. We do not record_unwind_protect here because
9827 other places in redisplay like calling window scroll functions
9828 don't either. Let the Lisp loader use `unwind-protect' instead. */
9829 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9831 sprintf (buffer
, "%lu %lu",
9832 (unsigned long) FRAME_X_WINDOW (f
),
9833 (unsigned long) img
->pixmap
);
9834 window_and_pixmap_id
= build_string (buffer
);
9836 sprintf (buffer
, "%lu %lu",
9837 FRAME_FOREGROUND_PIXEL (f
),
9838 FRAME_BACKGROUND_PIXEL (f
));
9839 pixel_colors
= build_string (buffer
);
9841 XSETFRAME (frame
, f
);
9842 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9844 loader
= intern ("gs-load-image");
9846 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9847 make_number (img
->width
),
9848 make_number (img
->height
),
9849 window_and_pixmap_id
,
9852 return PROCESSP (img
->data
.lisp_val
);
9856 /* Kill the Ghostscript process that was started to fill PIXMAP on
9857 frame F. Called from XTread_socket when receiving an event
9858 telling Emacs that Ghostscript has finished drawing. */
9861 x_kill_gs_process (pixmap
, f
)
9865 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9869 /* Find the image containing PIXMAP. */
9870 for (i
= 0; i
< c
->used
; ++i
)
9871 if (c
->images
[i
]->pixmap
== pixmap
)
9874 /* Kill the GS process. We should have found PIXMAP in the image
9875 cache and its image should contain a process object. */
9876 xassert (i
< c
->used
);
9878 xassert (PROCESSP (img
->data
.lisp_val
));
9879 Fkill_process (img
->data
.lisp_val
, Qnil
);
9880 img
->data
.lisp_val
= Qnil
;
9882 /* On displays with a mutable colormap, figure out the colors
9883 allocated for the image by looking at the pixels of an XImage for
9885 class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
9886 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9892 /* Try to get an XImage for img->pixmep. */
9893 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9894 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9899 /* Initialize the color table. */
9900 init_color_table ();
9902 /* For each pixel of the image, look its color up in the
9903 color table. After having done so, the color table will
9904 contain an entry for each color used by the image. */
9905 for (y
= 0; y
< img
->height
; ++y
)
9906 for (x
= 0; x
< img
->width
; ++x
)
9908 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9909 lookup_pixel_color (f
, pixel
);
9912 /* Record colors in the image. Free color table and XImage. */
9913 img
->colors
= colors_in_color_table (&img
->ncolors
);
9914 free_color_table ();
9915 XDestroyImage (ximg
);
9917 #if 0 /* This doesn't seem to be the case. If we free the colors
9918 here, we get a BadAccess later in x_clear_image when
9919 freeing the colors. */
9920 /* We have allocated colors once, but Ghostscript has also
9921 allocated colors on behalf of us. So, to get the
9922 reference counts right, free them once. */
9925 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
9926 XFreeColors (FRAME_X_DISPLAY (f
), cmap
,
9927 img
->colors
, img
->ncolors
, 0);
9932 image_error ("Cannot get X image of `%s'; colors will not be freed",
9941 /***********************************************************************
9943 ***********************************************************************/
9945 DEFUN ("x-change-window-property", Fx_change_window_property
,
9946 Sx_change_window_property
, 2, 3, 0,
9947 "Change window property PROP to VALUE on the X window of FRAME.\n\
9948 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9949 selected frame. Value is VALUE.")
9950 (prop
, value
, frame
)
9951 Lisp_Object frame
, prop
, value
;
9953 struct frame
*f
= check_x_frame (frame
);
9956 CHECK_STRING (prop
, 1);
9957 CHECK_STRING (value
, 2);
9960 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9961 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9962 prop_atom
, XA_STRING
, 8, PropModeReplace
,
9963 XSTRING (value
)->data
, XSTRING (value
)->size
);
9965 /* Make sure the property is set when we return. */
9966 XFlush (FRAME_X_DISPLAY (f
));
9973 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
9974 Sx_delete_window_property
, 1, 2, 0,
9975 "Remove window property PROP from X window of FRAME.\n\
9976 FRAME nil or omitted means use the selected frame. Value is PROP.")
9978 Lisp_Object prop
, frame
;
9980 struct frame
*f
= check_x_frame (frame
);
9983 CHECK_STRING (prop
, 1);
9985 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
9986 XDeleteProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), prop_atom
);
9988 /* Make sure the property is removed when we return. */
9989 XFlush (FRAME_X_DISPLAY (f
));
9996 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
9998 "Value is the value of window property PROP on FRAME.\n\
9999 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
10000 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10003 Lisp_Object prop
, frame
;
10005 struct frame
*f
= check_x_frame (frame
);
10008 Lisp_Object prop_value
= Qnil
;
10009 char *tmp_data
= NULL
;
10012 unsigned long actual_size
, bytes_remaining
;
10014 CHECK_STRING (prop
, 1);
10016 prop_atom
= XInternAtom (FRAME_X_DISPLAY (f
), XSTRING (prop
)->data
, False
);
10017 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10018 prop_atom
, 0, 0, False
, XA_STRING
,
10019 &actual_type
, &actual_format
, &actual_size
,
10020 &bytes_remaining
, (unsigned char **) &tmp_data
);
10023 int size
= bytes_remaining
;
10028 rc
= XGetWindowProperty (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10029 prop_atom
, 0, bytes_remaining
,
10031 &actual_type
, &actual_format
,
10032 &actual_size
, &bytes_remaining
,
10033 (unsigned char **) &tmp_data
);
10035 prop_value
= make_string (tmp_data
, size
);
10046 /***********************************************************************
10048 ***********************************************************************/
10050 /* The implementation partly follows a patch from
10051 F.Pierresteguy@frcl.bull.fr dated 1994. */
10053 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
10054 the next X event is read and we enter XTread_socket again. Setting
10055 it to 1 inhibits busy-cursor display for direct commands. */
10057 int inhibit_busy_cursor
;
10059 /* Incremented with each call to x-display-busy-cursor.
10060 Decremented in x-undisplay-busy-cursor. */
10062 static int busy_count
;
10065 DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor
,
10066 Sx_show_busy_cursor
, 0, 0, 0,
10067 "Show a busy cursor, if not already shown.\n\
10068 Each call to this function must be matched by a call to\n\
10069 `x-hide-busy-cursor' to make the busy pointer disappear again.")
10073 if (busy_count
== 1)
10075 Lisp_Object rest
, frame
;
10077 FOR_EACH_FRAME (rest
, frame
)
10078 if (FRAME_X_P (XFRAME (frame
)))
10080 struct frame
*f
= XFRAME (frame
);
10083 f
->output_data
.x
->busy_p
= 1;
10085 if (!f
->output_data
.x
->busy_window
)
10087 unsigned long mask
= CWCursor
;
10088 XSetWindowAttributes attrs
;
10090 attrs
.cursor
= f
->output_data
.x
->busy_cursor
;
10092 f
->output_data
.x
->busy_window
10093 = XCreateWindow (FRAME_X_DISPLAY (f
),
10094 FRAME_OUTER_WINDOW (f
),
10095 0, 0, 32000, 32000, 0, 0,
10101 XMapRaised (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10110 DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor
,
10111 Sx_hide_busy_cursor
, 0, 1, 0,
10112 "Hide a busy-cursor.\n\
10113 A busy-cursor will actually be undisplayed when a matching\n\
10114 `x-hide-busy-cursor' is called for each `x-show-busy-cursor'\n\
10115 issued. FORCE non-nil means hide the busy-cursor forcibly,\n\
10116 not counting calls.")
10120 Lisp_Object rest
, frame
;
10122 if (busy_count
== 0)
10125 if (!NILP (force
) && busy_count
!= 0)
10129 if (busy_count
!= 0)
10132 FOR_EACH_FRAME (rest
, frame
)
10134 struct frame
*f
= XFRAME (frame
);
10137 /* Watch out for newly created frames. */
10138 && f
->output_data
.x
->busy_window
)
10142 XUnmapWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->busy_window
);
10143 /* Sync here because XTread_socket looks at the busy_p flag
10144 that is reset to zero below. */
10145 XSync (FRAME_X_DISPLAY (f
), False
);
10147 f
->output_data
.x
->busy_p
= 0;
10156 /***********************************************************************
10158 ***********************************************************************/
10160 static Lisp_Object x_create_tip_frame
P_ ((struct x_display_info
*,
10163 /* The frame of a currently visible tooltip, or null. */
10165 struct frame
*tip_frame
;
10167 /* If non-nil, a timer started that hides the last tooltip when it
10170 Lisp_Object tip_timer
;
10173 /* Create a frame for a tooltip on the display described by DPYINFO.
10174 PARMS is a list of frame parameters. Value is the frame. */
10177 x_create_tip_frame (dpyinfo
, parms
)
10178 struct x_display_info
*dpyinfo
;
10182 Lisp_Object frame
, tem
;
10184 long window_prompting
= 0;
10186 int count
= specpdl_ptr
- specpdl
;
10187 struct gcpro gcpro1
, gcpro2
, gcpro3
;
10192 /* Use this general default value to start with until we know if
10193 this frame has a specified name. */
10194 Vx_resource_name
= Vinvocation_name
;
10196 #ifdef MULTI_KBOARD
10197 kb
= dpyinfo
->kboard
;
10199 kb
= &the_only_kboard
;
10202 /* Get the name of the frame to use for resource lookup. */
10203 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
10204 if (!STRINGP (name
)
10205 && !EQ (name
, Qunbound
)
10207 error ("Invalid frame name--not a string or nil");
10208 Vx_resource_name
= name
;
10211 GCPRO3 (parms
, name
, frame
);
10212 tip_frame
= f
= make_frame (1);
10213 XSETFRAME (frame
, f
);
10214 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
10216 f
->output_method
= output_x_window
;
10217 f
->output_data
.x
= (struct x_output
*) xmalloc (sizeof (struct x_output
));
10218 bzero (f
->output_data
.x
, sizeof (struct x_output
));
10219 f
->output_data
.x
->icon_bitmap
= -1;
10220 f
->output_data
.x
->fontset
= -1;
10221 f
->icon_name
= Qnil
;
10222 FRAME_X_DISPLAY_INFO (f
) = dpyinfo
;
10223 #ifdef MULTI_KBOARD
10224 FRAME_KBOARD (f
) = kb
;
10226 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10227 f
->output_data
.x
->explicit_parent
= 0;
10229 /* Set the name; the functions to which we pass f expect the name to
10231 if (EQ (name
, Qunbound
) || NILP (name
))
10233 f
->name
= build_string (dpyinfo
->x_id_name
);
10234 f
->explicit_name
= 0;
10239 f
->explicit_name
= 1;
10240 /* use the frame's title when getting resources for this frame. */
10241 specbind (Qx_resource_name
, name
);
10244 /* Create fontsets from `global_fontset_alist' before handling fonts. */
10245 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCDR (tem
))
10246 fs_register_fontset (f
, XCAR (tem
));
10248 /* Extract the window parameters from the supplied values
10249 that are needed to determine window geometry. */
10253 font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
10256 /* First, try whatever font the caller has specified. */
10257 if (STRINGP (font
))
10259 tem
= Fquery_fontset (font
, Qnil
);
10261 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
10263 font
= x_new_font (f
, XSTRING (font
)->data
);
10266 /* Try out a font which we hope has bold and italic variations. */
10267 if (!STRINGP (font
))
10268 font
= x_new_font (f
, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10269 if (!STRINGP (font
))
10270 font
= x_new_font (f
, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10271 if (! STRINGP (font
))
10272 font
= x_new_font (f
, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10273 if (! STRINGP (font
))
10274 /* This was formerly the first thing tried, but it finds too many fonts
10275 and takes too long. */
10276 font
= x_new_font (f
, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10277 /* If those didn't work, look for something which will at least work. */
10278 if (! STRINGP (font
))
10279 font
= x_new_font (f
, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10281 if (! STRINGP (font
))
10282 font
= build_string ("fixed");
10284 x_default_parameter (f
, parms
, Qfont
, font
,
10285 "font", "Font", RES_TYPE_STRING
);
10288 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
10289 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
10291 /* This defaults to 2 in order to match xterm. We recognize either
10292 internalBorderWidth or internalBorder (which is what xterm calls
10294 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10298 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
10299 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
10300 if (! EQ (value
, Qunbound
))
10301 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
10305 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
10306 "internalBorderWidth", "internalBorderWidth",
10309 /* Also do the stuff which must be set before the window exists. */
10310 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
10311 "foreground", "Foreground", RES_TYPE_STRING
);
10312 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
10313 "background", "Background", RES_TYPE_STRING
);
10314 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
10315 "pointerColor", "Foreground", RES_TYPE_STRING
);
10316 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
10317 "cursorColor", "Foreground", RES_TYPE_STRING
);
10318 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
10319 "borderColor", "BorderColor", RES_TYPE_STRING
);
10321 /* Init faces before x_default_parameter is called for scroll-bar
10322 parameters because that function calls x_set_scroll_bar_width,
10323 which calls change_frame_size, which calls Fset_window_buffer,
10324 which runs hooks, which call Fvertical_motion. At the end, we
10325 end up in init_iterator with a null face cache, which should not
10327 init_frame_faces (f
);
10329 f
->output_data
.x
->parent_desc
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
10330 window_prompting
= x_figure_window_size (f
, parms
);
10332 if (window_prompting
& XNegative
)
10334 if (window_prompting
& YNegative
)
10335 f
->output_data
.x
->win_gravity
= SouthEastGravity
;
10337 f
->output_data
.x
->win_gravity
= NorthEastGravity
;
10341 if (window_prompting
& YNegative
)
10342 f
->output_data
.x
->win_gravity
= SouthWestGravity
;
10344 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10347 f
->output_data
.x
->size_hint_flags
= window_prompting
;
10349 XSetWindowAttributes attrs
;
10350 unsigned long mask
;
10353 mask
= CWBackPixel
| CWOverrideRedirect
| CWSaveUnder
| CWEventMask
;
10354 /* Window managers looks at the override-redirect flag to
10355 determine whether or net to give windows a decoration (Xlib
10357 attrs
.override_redirect
= True
;
10358 attrs
.save_under
= True
;
10359 attrs
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
10360 /* Arrange for getting MapNotify and UnmapNotify events. */
10361 attrs
.event_mask
= StructureNotifyMask
;
10363 = FRAME_X_WINDOW (f
)
10364 = XCreateWindow (FRAME_X_DISPLAY (f
),
10365 FRAME_X_DISPLAY_INFO (f
)->root_window
,
10366 /* x, y, width, height */
10370 CopyFromParent
, InputOutput
, CopyFromParent
,
10377 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
10378 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10379 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
10380 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
10381 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
10382 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
10384 /* Dimensions, especially f->height, must be done via change_frame_size.
10385 Change will not be effected unless different from the current
10388 height
= f
->height
;
10390 SET_FRAME_WIDTH (f
, 0);
10391 change_frame_size (f
, height
, width
, 1, 0, 0);
10397 /* It is now ok to make the frame official even if we get an error
10398 below. And the frame needs to be on Vframe_list or making it
10399 visible won't work. */
10400 Vframe_list
= Fcons (frame
, Vframe_list
);
10402 /* Now that the frame is official, it counts as a reference to
10404 FRAME_X_DISPLAY_INFO (f
)->reference_count
++;
10406 return unbind_to (count
, frame
);
10410 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 4, 0,
10411 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10412 A tooltip window is a small X window displaying STRING at\n\
10413 the current mouse position.\n\
10414 FRAME nil or omitted means use the selected frame.\n\
10415 PARMS is an optional list of frame parameters which can be\n\
10416 used to change the tooltip's appearance.\n\
10417 Automatically hide the tooltip after TIMEOUT seconds.\n\
10418 TIMEOUT nil means use the default timeout of 5 seconds.")
10419 (string
, frame
, parms
, timeout
)
10420 Lisp_Object string
, frame
, parms
, timeout
;
10424 Window root
, child
;
10425 Lisp_Object buffer
;
10426 struct buffer
*old_buffer
;
10427 struct text_pos pos
;
10428 int i
, width
, height
;
10429 int root_x
, root_y
, win_x
, win_y
;
10431 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
10432 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
10433 int count
= specpdl_ptr
- specpdl
;
10435 specbind (Qinhibit_redisplay
, Qt
);
10437 GCPRO4 (string
, parms
, frame
, timeout
);
10439 CHECK_STRING (string
, 0);
10440 f
= check_x_frame (frame
);
10441 if (NILP (timeout
))
10442 timeout
= make_number (5);
10444 CHECK_NATNUM (timeout
, 2);
10446 /* Hide a previous tip, if any. */
10449 /* Add default values to frame parameters. */
10450 if (NILP (Fassq (Qname
, parms
)))
10451 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
10452 if (NILP (Fassq (Qinternal_border_width
, parms
)))
10453 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
10454 if (NILP (Fassq (Qborder_width
, parms
)))
10455 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
10456 if (NILP (Fassq (Qborder_color
, parms
)))
10457 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
10458 if (NILP (Fassq (Qbackground_color
, parms
)))
10459 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
10462 /* Create a frame for the tooltip, and record it in the global
10463 variable tip_frame. */
10464 frame
= x_create_tip_frame (FRAME_X_DISPLAY_INFO (f
), parms
);
10465 tip_frame
= f
= XFRAME (frame
);
10467 /* Set up the frame's root window. Currently we use a size of 80
10468 columns x 40 lines. If someone wants to show a larger tip, he
10469 will loose. I don't think this is a realistic case. */
10470 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
10471 w
->left
= w
->top
= make_number (0);
10475 w
->pseudo_window_p
= 1;
10477 /* Display the tooltip text in a temporary buffer. */
10478 buffer
= Fget_buffer_create (build_string (" *tip*"));
10479 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
);
10480 old_buffer
= current_buffer
;
10481 set_buffer_internal_1 (XBUFFER (buffer
));
10483 Finsert (make_number (1), &string
);
10484 clear_glyph_matrix (w
->desired_matrix
);
10485 clear_glyph_matrix (w
->current_matrix
);
10486 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
10487 try_window (FRAME_ROOT_WINDOW (f
), pos
);
10489 /* Compute width and height of the tooltip. */
10490 width
= height
= 0;
10491 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
10493 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
10494 struct glyph
*last
;
10497 /* Stop at the first empty row at the end. */
10498 if (!row
->enabled_p
|| !row
->displays_text_p
)
10501 /* Let the row go over the full width of the frame. */
10502 row
->full_width_p
= 1;
10504 /* There's a glyph at the end of rows that is use to place
10505 the cursor there. Don't include the width of this glyph. */
10506 if (row
->used
[TEXT_AREA
])
10508 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
10509 row_width
= row
->pixel_width
- last
->pixel_width
;
10512 row_width
= row
->pixel_width
;
10514 height
+= row
->height
;
10515 width
= max (width
, row_width
);
10518 /* Add the frame's internal border to the width and height the X
10519 window should have. */
10520 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10521 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
10523 /* Move the tooltip window where the mouse pointer is. Resize and
10526 XQueryPointer (FRAME_X_DISPLAY (f
), FRAME_X_DISPLAY_INFO (f
)->root_window
,
10527 &root
, &child
, &root_x
, &root_y
, &win_x
, &win_y
, &pmask
);
10528 XMoveResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10529 root_x
+ 5, root_y
- height
- 5, width
, height
);
10530 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10533 /* Draw into the window. */
10534 w
->must_be_updated_p
= 1;
10535 update_single_window (w
, 1);
10537 /* Restore original current buffer. */
10538 set_buffer_internal_1 (old_buffer
);
10539 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
10541 /* Let the tip disappear after timeout seconds. */
10542 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
10543 intern ("x-hide-tip"));
10546 return unbind_to (count
, Qnil
);
10550 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
10551 "Hide the current tooltip window, if there is any.\n\
10552 Value is t is tooltip was open, nil otherwise.")
10555 int count
= specpdl_ptr
- specpdl
;
10558 specbind (Qinhibit_redisplay
, Qt
);
10560 if (!NILP (tip_timer
))
10562 call1 (intern ("cancel-timer"), tip_timer
);
10570 XSETFRAME (frame
, tip_frame
);
10571 Fdelete_frame (frame
, Qt
);
10576 return unbind_to (count
, deleted_p
? Qt
: Qnil
);
10581 /***********************************************************************
10582 File selection dialog
10583 ***********************************************************************/
10587 /* Callback for "OK" and "Cancel" on file selection dialog. */
10590 file_dialog_cb (widget
, client_data
, call_data
)
10592 XtPointer call_data
, client_data
;
10594 int *result
= (int *) client_data
;
10595 XmAnyCallbackStruct
*cb
= (XmAnyCallbackStruct
*) call_data
;
10596 *result
= cb
->reason
;
10600 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 4, 0,
10601 "Read file name, prompting with PROMPT in directory DIR.\n\
10602 Use a file selection dialog.\n\
10603 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10604 specified. Don't let the user enter a file name in the file\n\
10605 selection dialog's entry field, if MUSTMATCH is non-nil.")
10606 (prompt
, dir
, default_filename
, mustmatch
)
10607 Lisp_Object prompt
, dir
, default_filename
, mustmatch
;
10610 struct frame
*f
= SELECTED_FRAME ();
10611 Lisp_Object file
= Qnil
;
10612 Widget dialog
, text
, list
, help
;
10615 extern XtAppContext Xt_app_con
;
10617 XmString dir_xmstring
, pattern_xmstring
;
10618 int popup_activated_flag
;
10619 int count
= specpdl_ptr
- specpdl
;
10620 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
10622 GCPRO5 (prompt
, dir
, default_filename
, mustmatch
, file
);
10623 CHECK_STRING (prompt
, 0);
10624 CHECK_STRING (dir
, 1);
10626 /* Prevent redisplay. */
10627 specbind (Qinhibit_redisplay
, Qt
);
10631 /* Create the dialog with PROMPT as title, using DIR as initial
10632 directory and using "*" as pattern. */
10633 dir
= Fexpand_file_name (dir
, Qnil
);
10634 dir_xmstring
= XmStringCreateLocalized (XSTRING (dir
)->data
);
10635 pattern_xmstring
= XmStringCreateLocalized ("*");
10637 XtSetArg (al
[ac
], XmNtitle
, XSTRING (prompt
)->data
); ++ac
;
10638 XtSetArg (al
[ac
], XmNdirectory
, dir_xmstring
); ++ac
;
10639 XtSetArg (al
[ac
], XmNpattern
, pattern_xmstring
); ++ac
;
10640 XtSetArg (al
[ac
], XmNresizePolicy
, XmRESIZE_GROW
); ++ac
;
10641 XtSetArg (al
[ac
], XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
); ++ac
;
10642 dialog
= XmCreateFileSelectionDialog (f
->output_data
.x
->widget
,
10644 XmStringFree (dir_xmstring
);
10645 XmStringFree (pattern_xmstring
);
10647 /* Add callbacks for OK and Cancel. */
10648 XtAddCallback (dialog
, XmNokCallback
, file_dialog_cb
,
10649 (XtPointer
) &result
);
10650 XtAddCallback (dialog
, XmNcancelCallback
, file_dialog_cb
,
10651 (XtPointer
) &result
);
10653 /* Disable the help button since we can't display help. */
10654 help
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_HELP_BUTTON
);
10655 XtSetSensitive (help
, False
);
10657 /* Mark OK button as default. */
10658 XtVaSetValues (XmFileSelectionBoxGetChild (dialog
, XmDIALOG_OK_BUTTON
),
10659 XmNshowAsDefault
, True
, NULL
);
10661 /* If MUSTMATCH is non-nil, disable the file entry field of the
10662 dialog, so that the user must select a file from the files list
10663 box. We can't remove it because we wouldn't have a way to get at
10664 the result file name, then. */
10665 text
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_TEXT
);
10666 if (!NILP (mustmatch
))
10669 label
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_SELECTION_LABEL
);
10670 XtSetSensitive (text
, False
);
10671 XtSetSensitive (label
, False
);
10674 /* Manage the dialog, so that list boxes get filled. */
10675 XtManageChild (dialog
);
10677 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10678 must include the path for this to work. */
10679 list
= XmFileSelectionBoxGetChild (dialog
, XmDIALOG_LIST
);
10680 if (STRINGP (default_filename
))
10682 XmString default_xmstring
;
10686 = XmStringCreateLocalized (XSTRING (default_filename
)->data
);
10688 if (!XmListItemExists (list
, default_xmstring
))
10690 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10691 XmListAddItem (list
, default_xmstring
, 0);
10695 item_pos
= XmListItemPos (list
, default_xmstring
);
10696 XmStringFree (default_xmstring
);
10698 /* Select the item and scroll it into view. */
10699 XmListSelectPos (list
, item_pos
, True
);
10700 XmListSetPos (list
, item_pos
);
10703 /* Process all events until the user presses Cancel or OK. */
10704 for (result
= 0; result
== 0;)
10707 Widget widget
, parent
;
10709 XtAppNextEvent (Xt_app_con
, &event
);
10711 /* See if the receiver of the event is one of the widgets of
10712 the file selection dialog. If so, dispatch it. If not,
10714 widget
= XtWindowToWidget (event
.xany
.display
, event
.xany
.window
);
10716 while (parent
&& parent
!= dialog
)
10717 parent
= XtParent (parent
);
10719 if (parent
== dialog
10720 || (event
.type
== Expose
10721 && !process_expose_from_menu (event
)))
10722 XtDispatchEvent (&event
);
10725 /* Get the result. */
10726 if (result
== XmCR_OK
)
10731 XtVaGetValues (dialog
, XmNtextString
, &text
, 0);
10732 XmStringGetLtoR (text
, XmFONTLIST_DEFAULT_TAG
, &data
);
10733 XmStringFree (text
);
10734 file
= build_string (data
);
10741 XtUnmanageChild (dialog
);
10742 XtDestroyWidget (dialog
);
10746 /* Make "Cancel" equivalent to C-g. */
10748 Fsignal (Qquit
, Qnil
);
10750 return unbind_to (count
, file
);
10753 #endif /* USE_MOTIF */
10756 /***********************************************************************
10758 ***********************************************************************/
10762 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
10763 "Value is non-nil if SPEC is a valid image specification.")
10767 return valid_image_p (spec
) ? Qt
: Qnil
;
10771 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
10777 if (valid_image_p (spec
))
10778 id
= lookup_image (SELECTED_FRAME (), spec
);
10780 debug_print (spec
);
10781 return make_number (id
);
10784 #endif /* GLYPH_DEBUG != 0 */
10788 /***********************************************************************
10790 ***********************************************************************/
10795 /* This is zero if not using X windows. */
10798 /* The section below is built by the lisp expression at the top of the file,
10799 just above where these variables are declared. */
10800 /*&&& init symbols here &&&*/
10801 Qauto_raise
= intern ("auto-raise");
10802 staticpro (&Qauto_raise
);
10803 Qauto_lower
= intern ("auto-lower");
10804 staticpro (&Qauto_lower
);
10805 Qbar
= intern ("bar");
10807 Qborder_color
= intern ("border-color");
10808 staticpro (&Qborder_color
);
10809 Qborder_width
= intern ("border-width");
10810 staticpro (&Qborder_width
);
10811 Qbox
= intern ("box");
10813 Qcursor_color
= intern ("cursor-color");
10814 staticpro (&Qcursor_color
);
10815 Qcursor_type
= intern ("cursor-type");
10816 staticpro (&Qcursor_type
);
10817 Qgeometry
= intern ("geometry");
10818 staticpro (&Qgeometry
);
10819 Qicon_left
= intern ("icon-left");
10820 staticpro (&Qicon_left
);
10821 Qicon_top
= intern ("icon-top");
10822 staticpro (&Qicon_top
);
10823 Qicon_type
= intern ("icon-type");
10824 staticpro (&Qicon_type
);
10825 Qicon_name
= intern ("icon-name");
10826 staticpro (&Qicon_name
);
10827 Qinternal_border_width
= intern ("internal-border-width");
10828 staticpro (&Qinternal_border_width
);
10829 Qleft
= intern ("left");
10830 staticpro (&Qleft
);
10831 Qright
= intern ("right");
10832 staticpro (&Qright
);
10833 Qmouse_color
= intern ("mouse-color");
10834 staticpro (&Qmouse_color
);
10835 Qnone
= intern ("none");
10836 staticpro (&Qnone
);
10837 Qparent_id
= intern ("parent-id");
10838 staticpro (&Qparent_id
);
10839 Qscroll_bar_width
= intern ("scroll-bar-width");
10840 staticpro (&Qscroll_bar_width
);
10841 Qsuppress_icon
= intern ("suppress-icon");
10842 staticpro (&Qsuppress_icon
);
10843 Qundefined_color
= intern ("undefined-color");
10844 staticpro (&Qundefined_color
);
10845 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
10846 staticpro (&Qvertical_scroll_bars
);
10847 Qvisibility
= intern ("visibility");
10848 staticpro (&Qvisibility
);
10849 Qwindow_id
= intern ("window-id");
10850 staticpro (&Qwindow_id
);
10851 Qouter_window_id
= intern ("outer-window-id");
10852 staticpro (&Qouter_window_id
);
10853 Qx_frame_parameter
= intern ("x-frame-parameter");
10854 staticpro (&Qx_frame_parameter
);
10855 Qx_resource_name
= intern ("x-resource-name");
10856 staticpro (&Qx_resource_name
);
10857 Quser_position
= intern ("user-position");
10858 staticpro (&Quser_position
);
10859 Quser_size
= intern ("user-size");
10860 staticpro (&Quser_size
);
10861 Qscroll_bar_foreground
= intern ("scroll-bar-foreground");
10862 staticpro (&Qscroll_bar_foreground
);
10863 Qscroll_bar_background
= intern ("scroll-bar-background");
10864 staticpro (&Qscroll_bar_background
);
10865 Qscreen_gamma
= intern ("screen-gamma");
10866 staticpro (&Qscreen_gamma
);
10867 /* This is the end of symbol initialization. */
10869 /* Text property `display' should be nonsticky by default. */
10870 Vtext_property_default_nonsticky
10871 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
10874 Qlaplace
= intern ("laplace");
10875 staticpro (&Qlaplace
);
10877 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
10878 staticpro (&Qface_set_after_frame_default
);
10880 Fput (Qundefined_color
, Qerror_conditions
,
10881 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
10882 Fput (Qundefined_color
, Qerror_message
,
10883 build_string ("Undefined color"));
10885 init_x_parm_symbols ();
10887 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
10888 "List of directories to search for bitmap files for X.");
10889 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
10891 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
10892 "The shape of the pointer when over text.\n\
10893 Changing the value does not affect existing frames\n\
10894 unless you set the mouse color.");
10895 Vx_pointer_shape
= Qnil
;
10897 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
10898 "The name Emacs uses to look up X resources.\n\
10899 `x-get-resource' uses this as the first component of the instance name\n\
10900 when requesting resource values.\n\
10901 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
10902 was invoked, or to the value specified with the `-name' or `-rn'\n\
10903 switches, if present.\n\
10905 It may be useful to bind this variable locally around a call\n\
10906 to `x-get-resource'. See also the variable `x-resource-class'.");
10907 Vx_resource_name
= Qnil
;
10909 DEFVAR_LISP ("x-resource-class", &Vx_resource_class
,
10910 "The class Emacs uses to look up X resources.\n\
10911 `x-get-resource' uses this as the first component of the instance class\n\
10912 when requesting resource values.\n\
10913 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
10915 Setting this variable permanently is not a reasonable thing to do,\n\
10916 but binding this variable locally around a call to `x-get-resource'\n\
10917 is a reasonable practice. See also the variable `x-resource-name'.");
10918 Vx_resource_class
= build_string (EMACS_CLASS
);
10920 #if 0 /* This doesn't really do anything. */
10921 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape
,
10922 "The shape of the pointer when not over text.\n\
10923 This variable takes effect when you create a new frame\n\
10924 or when you set the mouse color.");
10926 Vx_nontext_pointer_shape
= Qnil
;
10928 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape
,
10929 "The shape of the pointer when Emacs is busy.\n\
10930 This variable takes effect when you create a new frame\n\
10931 or when you set the mouse color.");
10932 Vx_busy_pointer_shape
= Qnil
;
10934 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p
,
10935 "Non-zero means Emacs displays a busy cursor on window systems.");
10936 display_busy_cursor_p
= 1;
10938 #if 0 /* This doesn't really do anything. */
10939 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape
,
10940 "The shape of the pointer when over the mode line.\n\
10941 This variable takes effect when you create a new frame\n\
10942 or when you set the mouse color.");
10944 Vx_mode_pointer_shape
= Qnil
;
10946 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10947 &Vx_sensitive_text_pointer_shape
,
10948 "The shape of the pointer when over mouse-sensitive text.\n\
10949 This variable takes effect when you create a new frame\n\
10950 or when you set the mouse color.");
10951 Vx_sensitive_text_pointer_shape
= Qnil
;
10953 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
10954 "A string indicating the foreground color of the cursor box.");
10955 Vx_cursor_fore_pixel
= Qnil
;
10957 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
10958 "Non-nil if no X window manager is in use.\n\
10959 Emacs doesn't try to figure this out; this is always nil\n\
10960 unless you set it to something else.");
10961 /* We don't have any way to find this out, so set it to nil
10962 and maybe the user would like to set it to t. */
10963 Vx_no_window_manager
= Qnil
;
10965 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10966 &Vx_pixel_size_width_font_regexp
,
10967 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
10969 Since Emacs gets width of a font matching with this regexp from\n\
10970 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
10971 such a font. This is especially effective for such large fonts as\n\
10972 Chinese, Japanese, and Korean.");
10973 Vx_pixel_size_width_font_regexp
= Qnil
;
10975 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
10976 "Time after which cached images are removed from the cache.\n\
10977 When an image has not been displayed this many seconds, remove it\n\
10978 from the image cache. Value must be an integer or nil with nil\n\
10979 meaning don't clear the cache.");
10980 Vimage_cache_eviction_delay
= make_number (30 * 60);
10982 DEFVAR_LISP ("image-types", &Vimage_types
,
10983 "List of supported image types.\n\
10984 Each element of the list is a symbol for a supported image type.");
10985 Vimage_types
= Qnil
;
10987 #ifdef USE_X_TOOLKIT
10988 Fprovide (intern ("x-toolkit"));
10991 Fprovide (intern ("motif"));
10994 defsubr (&Sx_get_resource
);
10996 /* X window properties. */
10997 defsubr (&Sx_change_window_property
);
10998 defsubr (&Sx_delete_window_property
);
10999 defsubr (&Sx_window_property
);
11002 defsubr (&Sx_draw_rectangle
);
11003 defsubr (&Sx_erase_rectangle
);
11004 defsubr (&Sx_contour_region
);
11005 defsubr (&Sx_uncontour_region
);
11007 defsubr (&Sxw_display_color_p
);
11008 defsubr (&Sx_display_grayscale_p
);
11009 defsubr (&Sxw_color_defined_p
);
11010 defsubr (&Sxw_color_values
);
11011 defsubr (&Sx_server_max_request_size
);
11012 defsubr (&Sx_server_vendor
);
11013 defsubr (&Sx_server_version
);
11014 defsubr (&Sx_display_pixel_width
);
11015 defsubr (&Sx_display_pixel_height
);
11016 defsubr (&Sx_display_mm_width
);
11017 defsubr (&Sx_display_mm_height
);
11018 defsubr (&Sx_display_screens
);
11019 defsubr (&Sx_display_planes
);
11020 defsubr (&Sx_display_color_cells
);
11021 defsubr (&Sx_display_visual_class
);
11022 defsubr (&Sx_display_backing_store
);
11023 defsubr (&Sx_display_save_under
);
11025 defsubr (&Sx_rebind_key
);
11026 defsubr (&Sx_rebind_keys
);
11027 defsubr (&Sx_track_pointer
);
11028 defsubr (&Sx_grab_pointer
);
11029 defsubr (&Sx_ungrab_pointer
);
11031 defsubr (&Sx_parse_geometry
);
11032 defsubr (&Sx_create_frame
);
11034 defsubr (&Sx_horizontal_line
);
11036 defsubr (&Sx_open_connection
);
11037 defsubr (&Sx_close_connection
);
11038 defsubr (&Sx_display_list
);
11039 defsubr (&Sx_synchronize
);
11041 /* Setting callback functions for fontset handler. */
11042 get_font_info_func
= x_get_font_info
;
11044 #if 0 /* This function pointer doesn't seem to be used anywhere.
11045 And the pointer assigned has the wrong type, anyway. */
11046 list_fonts_func
= x_list_fonts
;
11049 load_font_func
= x_load_font
;
11050 find_ccl_program_func
= x_find_ccl_program
;
11051 query_font_func
= x_query_font
;
11052 set_frame_fontset_func
= x_set_font
;
11053 check_window_system_func
= check_x
;
11056 Qxbm
= intern ("xbm");
11058 QCtype
= intern (":type");
11059 staticpro (&QCtype
);
11060 QCalgorithm
= intern (":algorithm");
11061 staticpro (&QCalgorithm
);
11062 QCheuristic_mask
= intern (":heuristic-mask");
11063 staticpro (&QCheuristic_mask
);
11064 QCcolor_symbols
= intern (":color-symbols");
11065 staticpro (&QCcolor_symbols
);
11066 QCdata
= intern (":data");
11067 staticpro (&QCdata
);
11068 QCascent
= intern (":ascent");
11069 staticpro (&QCascent
);
11070 QCmargin
= intern (":margin");
11071 staticpro (&QCmargin
);
11072 QCrelief
= intern (":relief");
11073 staticpro (&QCrelief
);
11074 Qpostscript
= intern ("postscript");
11075 staticpro (&Qpostscript
);
11076 QCloader
= intern (":loader");
11077 staticpro (&QCloader
);
11078 QCbounding_box
= intern (":bounding-box");
11079 staticpro (&QCbounding_box
);
11080 QCpt_width
= intern (":pt-width");
11081 staticpro (&QCpt_width
);
11082 QCpt_height
= intern (":pt-height");
11083 staticpro (&QCpt_height
);
11084 QCindex
= intern (":index");
11085 staticpro (&QCindex
);
11086 Qpbm
= intern ("pbm");
11090 Qxpm
= intern ("xpm");
11095 Qjpeg
= intern ("jpeg");
11096 staticpro (&Qjpeg
);
11100 Qtiff
= intern ("tiff");
11101 staticpro (&Qtiff
);
11105 Qgif
= intern ("gif");
11110 Qpng
= intern ("png");
11114 defsubr (&Sclear_image_cache
);
11117 defsubr (&Simagep
);
11118 defsubr (&Slookup_image
);
11122 defsubr (&Sx_show_busy_cursor
);
11123 defsubr (&Sx_hide_busy_cursor
);
11125 inhibit_busy_cursor
= 0;
11127 defsubr (&Sx_show_tip
);
11128 defsubr (&Sx_hide_tip
);
11129 staticpro (&tip_timer
);
11133 defsubr (&Sx_file_dialog
);
11141 image_types
= NULL
;
11142 Vimage_types
= Qnil
;
11144 define_image_type (&xbm_type
);
11145 define_image_type (&gs_type
);
11146 define_image_type (&pbm_type
);
11149 define_image_type (&xpm_type
);
11153 define_image_type (&jpeg_type
);
11157 define_image_type (&tiff_type
);
11161 define_image_type (&gif_type
);
11165 define_image_type (&png_type
);
11169 #endif /* HAVE_X_WINDOWS */