Docstring fixes.
[emacs.git] / src / xfns.c
blob370ce8825d7bf150221ec9db22dfcd1f1d62ed65
1 /* Functions for the X window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 /* This makes the fields of a Display accessible, in Xlib header files. */
29 #define XLIB_ILLEGAL_ACCESS
31 #include "lisp.h"
32 #include "xterm.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include <epaths.h>
41 #include "charset.h"
42 #include "coding.h"
43 #include "fontset.h"
44 #include "systime.h"
45 #include "termhooks.h"
46 #include "atimer.h"
48 #ifdef HAVE_X_WINDOWS
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
54 #ifndef VMS
55 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
56 #include "bitmaps/gray.xbm"
57 #else
58 #include <X11/bitmaps/gray>
59 #endif
60 #else
61 #include "[.bitmaps]gray.xbm"
62 #endif
64 #ifdef USE_X_TOOLKIT
65 #include <X11/Shell.h>
67 #ifndef USE_MOTIF
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* USE_MOTIF */
72 #ifdef USG
73 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
74 #include <X11/Xos.h>
75 #define USG
76 #else
77 #include <X11/Xos.h>
78 #endif
80 #include "widget.h"
82 #include "../lwlib/lwlib.h"
84 #ifdef USE_MOTIF
85 #include <Xm/Xm.h>
86 #include <Xm/DialogS.h>
87 #include <Xm/FileSB.h>
88 #endif
90 /* Do the EDITRES protocol if running X11R5
91 Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
93 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
94 #define HACK_EDITRES
95 extern void _XEditResCheckMessages ();
96 #endif /* R5 + Athena */
98 /* Unique id counter for widgets created by the Lucid Widget Library. */
100 extern LWLIB_ID widget_id_tick;
102 #ifdef USE_LUCID
103 /* This is part of a kludge--see lwlib/xlwmenu.c. */
104 extern XFontStruct *xlwmenu_default_font;
105 #endif
107 extern void free_frame_menubar ();
108 extern double atof ();
110 #endif /* USE_X_TOOLKIT */
112 #define min(a,b) ((a) < (b) ? (a) : (b))
113 #define max(a,b) ((a) > (b) ? (a) : (b))
115 #ifdef HAVE_X11R4
116 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
117 #else
118 #define MAXREQUEST(dpy) ((dpy)->max_request_size)
119 #endif
121 /* The gray bitmap `bitmaps/gray'. This is done because xterm.c uses
122 it, and including `bitmaps/gray' more than once is a problem when
123 config.h defines `static' as an empty replacement string. */
125 int gray_bitmap_width = gray_width;
126 int gray_bitmap_height = gray_height;
127 unsigned char *gray_bitmap_bits = gray_bits;
129 /* The name we're using in resource queries. Most often "emacs". */
131 Lisp_Object Vx_resource_name;
133 /* The application class we're using in resource queries.
134 Normally "Emacs". */
136 Lisp_Object Vx_resource_class;
138 /* Non-zero means we're allowed to display a busy cursor. */
140 int display_busy_cursor_p;
142 /* The background and shape of the mouse pointer, and shape when not
143 over text or in the modeline. */
145 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
146 Lisp_Object Vx_busy_pointer_shape;
148 /* The shape when over mouse-sensitive text. */
150 Lisp_Object Vx_sensitive_text_pointer_shape;
152 /* Color of chars displayed in cursor box. */
154 Lisp_Object Vx_cursor_fore_pixel;
156 /* Nonzero if using X. */
158 static int x_in_use;
160 /* Non nil if no window manager is in use. */
162 Lisp_Object Vx_no_window_manager;
164 /* Search path for bitmap files. */
166 Lisp_Object Vx_bitmap_file_path;
168 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
170 Lisp_Object Vx_pixel_size_width_font_regexp;
172 /* Evaluate this expression to rebuild the section of syms_of_xfns
173 that initializes and staticpros the symbols declared below. Note
174 that Emacs 18 has a bug that keeps C-x C-e from being able to
175 evaluate this expression.
177 (progn
178 ;; Accumulate a list of the symbols we want to initialize from the
179 ;; declarations at the top of the file.
180 (goto-char (point-min))
181 (search-forward "/\*&&& symbols declared here &&&*\/\n")
182 (let (symbol-list)
183 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
184 (setq symbol-list
185 (cons (buffer-substring (match-beginning 1) (match-end 1))
186 symbol-list))
187 (forward-line 1))
188 (setq symbol-list (nreverse symbol-list))
189 ;; Delete the section of syms_of_... where we initialize the symbols.
190 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
191 (let ((start (point)))
192 (while (looking-at "^ Q")
193 (forward-line 2))
194 (kill-region start (point)))
195 ;; Write a new symbol initialization section.
196 (while symbol-list
197 (insert (format " %s = intern (\"" (car symbol-list)))
198 (let ((start (point)))
199 (insert (substring (car symbol-list) 1))
200 (subst-char-in-region start (point) ?_ ?-))
201 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
202 (setq symbol-list (cdr symbol-list)))))
206 /*&&& symbols declared here &&&*/
207 Lisp_Object Qauto_raise;
208 Lisp_Object Qauto_lower;
209 Lisp_Object Qbar;
210 Lisp_Object Qborder_color;
211 Lisp_Object Qborder_width;
212 Lisp_Object Qbox;
213 Lisp_Object Qcursor_color;
214 Lisp_Object Qcursor_type;
215 Lisp_Object Qgeometry;
216 Lisp_Object Qicon_left;
217 Lisp_Object Qicon_top;
218 Lisp_Object Qicon_type;
219 Lisp_Object Qicon_name;
220 Lisp_Object Qinternal_border_width;
221 Lisp_Object Qleft;
222 Lisp_Object Qright;
223 Lisp_Object Qmouse_color;
224 Lisp_Object Qnone;
225 Lisp_Object Qouter_window_id;
226 Lisp_Object Qparent_id;
227 Lisp_Object Qscroll_bar_width;
228 Lisp_Object Qsuppress_icon;
229 extern Lisp_Object Qtop;
230 Lisp_Object Qundefined_color;
231 Lisp_Object Qvertical_scroll_bars;
232 Lisp_Object Qvisibility;
233 Lisp_Object Qwindow_id;
234 Lisp_Object Qx_frame_parameter;
235 Lisp_Object Qx_resource_name;
236 Lisp_Object Quser_position;
237 Lisp_Object Quser_size;
238 extern Lisp_Object Qdisplay;
239 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
240 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
241 Lisp_Object Qcompound_text;
243 /* The below are defined in frame.c. */
245 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
246 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
247 extern Lisp_Object Qtool_bar_lines;
249 extern Lisp_Object Vwindow_system_version;
251 Lisp_Object Qface_set_after_frame_default;
254 /* Error if we are not connected to X. */
256 void
257 check_x ()
259 if (! x_in_use)
260 error ("X windows are not in use or not initialized");
263 /* Nonzero if we can use mouse menus.
264 You should not call this unless HAVE_MENUS is defined. */
267 have_menus_p ()
269 return x_in_use;
272 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
273 and checking validity for X. */
275 FRAME_PTR
276 check_x_frame (frame)
277 Lisp_Object frame;
279 FRAME_PTR f;
281 if (NILP (frame))
282 frame = selected_frame;
283 CHECK_LIVE_FRAME (frame, 0);
284 f = XFRAME (frame);
285 if (! FRAME_X_P (f))
286 error ("Non-X frame used");
287 return f;
290 /* Let the user specify an X display with a frame.
291 nil stands for the selected frame--or, if that is not an X frame,
292 the first X display on the list. */
294 static struct x_display_info *
295 check_x_display_info (frame)
296 Lisp_Object frame;
298 struct x_display_info *dpyinfo = NULL;
300 if (NILP (frame))
302 struct frame *sf = XFRAME (selected_frame);
304 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
305 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
306 else if (x_display_list != 0)
307 dpyinfo = x_display_list;
308 else
309 error ("X windows are not in use or not initialized");
311 else if (STRINGP (frame))
312 dpyinfo = x_display_info_for_name (frame);
313 else
315 FRAME_PTR f;
317 CHECK_LIVE_FRAME (frame, 0);
318 f = XFRAME (frame);
319 if (! FRAME_X_P (f))
320 error ("Non-X frame used");
321 dpyinfo = FRAME_X_DISPLAY_INFO (f);
324 return dpyinfo;
328 /* Return the Emacs frame-object corresponding to an X window.
329 It could be the frame's main window or an icon window. */
331 /* This function can be called during GC, so use GC_xxx type test macros. */
333 struct frame *
334 x_window_to_frame (dpyinfo, wdesc)
335 struct x_display_info *dpyinfo;
336 int wdesc;
338 Lisp_Object tail, frame;
339 struct frame *f;
341 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
343 frame = XCAR (tail);
344 if (!GC_FRAMEP (frame))
345 continue;
346 f = XFRAME (frame);
347 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
348 continue;
349 if (f->output_data.x->busy_window == wdesc)
350 return f;
351 #ifdef USE_X_TOOLKIT
352 if ((f->output_data.x->edit_widget
353 && XtWindow (f->output_data.x->edit_widget) == wdesc)
354 /* A tooltip frame? */
355 || (!f->output_data.x->edit_widget
356 && FRAME_X_WINDOW (f) == wdesc)
357 || f->output_data.x->icon_desc == wdesc)
358 return f;
359 #else /* not USE_X_TOOLKIT */
360 if (FRAME_X_WINDOW (f) == wdesc
361 || f->output_data.x->icon_desc == wdesc)
362 return f;
363 #endif /* not USE_X_TOOLKIT */
365 return 0;
368 #ifdef USE_X_TOOLKIT
369 /* Like x_window_to_frame but also compares the window with the widget's
370 windows. */
372 struct frame *
373 x_any_window_to_frame (dpyinfo, wdesc)
374 struct x_display_info *dpyinfo;
375 int wdesc;
377 Lisp_Object tail, frame;
378 struct frame *f, *found;
379 struct x_output *x;
381 found = NULL;
382 for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
384 frame = XCAR (tail);
385 if (!GC_FRAMEP (frame))
386 continue;
388 f = XFRAME (frame);
389 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
391 /* This frame matches if the window is any of its widgets. */
392 x = f->output_data.x;
393 if (x->busy_window == wdesc)
394 found = f;
395 else if (x->widget)
397 if (wdesc == XtWindow (x->widget)
398 || wdesc == XtWindow (x->column_widget)
399 || wdesc == XtWindow (x->edit_widget))
400 found = f;
401 /* Match if the window is this frame's menubar. */
402 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
403 found = f;
405 else if (FRAME_X_WINDOW (f) == wdesc)
406 /* A tooltip frame. */
407 found = f;
411 return found;
414 /* Likewise, but exclude the menu bar widget. */
416 struct frame *
417 x_non_menubar_window_to_frame (dpyinfo, wdesc)
418 struct x_display_info *dpyinfo;
419 int wdesc;
421 Lisp_Object tail, frame;
422 struct frame *f;
423 struct x_output *x;
425 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
427 frame = XCAR (tail);
428 if (!GC_FRAMEP (frame))
429 continue;
430 f = XFRAME (frame);
431 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
432 continue;
433 x = f->output_data.x;
434 /* This frame matches if the window is any of its widgets. */
435 if (x->busy_window == wdesc)
436 return f;
437 else if (x->widget)
439 if (wdesc == XtWindow (x->widget)
440 || wdesc == XtWindow (x->column_widget)
441 || wdesc == XtWindow (x->edit_widget))
442 return f;
444 else if (FRAME_X_WINDOW (f) == wdesc)
445 /* A tooltip frame. */
446 return f;
448 return 0;
451 /* Likewise, but consider only the menu bar widget. */
453 struct frame *
454 x_menubar_window_to_frame (dpyinfo, wdesc)
455 struct x_display_info *dpyinfo;
456 int wdesc;
458 Lisp_Object tail, frame;
459 struct frame *f;
460 struct x_output *x;
462 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
464 frame = XCAR (tail);
465 if (!GC_FRAMEP (frame))
466 continue;
467 f = XFRAME (frame);
468 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
469 continue;
470 x = f->output_data.x;
471 /* Match if the window is this frame's menubar. */
472 if (x->menubar_widget
473 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
474 return f;
476 return 0;
479 /* Return the frame whose principal (outermost) window is WDESC.
480 If WDESC is some other (smaller) window, we return 0. */
482 struct frame *
483 x_top_window_to_frame (dpyinfo, wdesc)
484 struct x_display_info *dpyinfo;
485 int wdesc;
487 Lisp_Object tail, frame;
488 struct frame *f;
489 struct x_output *x;
491 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
493 frame = XCAR (tail);
494 if (!GC_FRAMEP (frame))
495 continue;
496 f = XFRAME (frame);
497 if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
498 continue;
499 x = f->output_data.x;
501 if (x->widget)
503 /* This frame matches if the window is its topmost widget. */
504 if (wdesc == XtWindow (x->widget))
505 return f;
506 #if 0 /* I don't know why it did this,
507 but it seems logically wrong,
508 and it causes trouble for MapNotify events. */
509 /* Match if the window is this frame's menubar. */
510 if (x->menubar_widget
511 && wdesc == XtWindow (x->menubar_widget))
512 return f;
513 #endif
515 else if (FRAME_X_WINDOW (f) == wdesc)
516 /* Tooltip frame. */
517 return f;
519 return 0;
521 #endif /* USE_X_TOOLKIT */
525 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
526 id, which is just an int that this section returns. Bitmaps are
527 reference counted so they can be shared among frames.
529 Bitmap indices are guaranteed to be > 0, so a negative number can
530 be used to indicate no bitmap.
532 If you use x_create_bitmap_from_data, then you must keep track of
533 the bitmaps yourself. That is, creating a bitmap from the same
534 data more than once will not be caught. */
537 /* Functions to access the contents of a bitmap, given an id. */
540 x_bitmap_height (f, id)
541 FRAME_PTR f;
542 int id;
544 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
548 x_bitmap_width (f, id)
549 FRAME_PTR f;
550 int id;
552 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
556 x_bitmap_pixmap (f, id)
557 FRAME_PTR f;
558 int id;
560 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
564 /* Allocate a new bitmap record. Returns index of new record. */
566 static int
567 x_allocate_bitmap_record (f)
568 FRAME_PTR f;
570 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
571 int i;
573 if (dpyinfo->bitmaps == NULL)
575 dpyinfo->bitmaps_size = 10;
576 dpyinfo->bitmaps
577 = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
578 dpyinfo->bitmaps_last = 1;
579 return 1;
582 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
583 return ++dpyinfo->bitmaps_last;
585 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
586 if (dpyinfo->bitmaps[i].refcount == 0)
587 return i + 1;
589 dpyinfo->bitmaps_size *= 2;
590 dpyinfo->bitmaps
591 = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
592 dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
593 return ++dpyinfo->bitmaps_last;
596 /* Add one reference to the reference count of the bitmap with id ID. */
598 void
599 x_reference_bitmap (f, id)
600 FRAME_PTR f;
601 int id;
603 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
606 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
609 x_create_bitmap_from_data (f, bits, width, height)
610 struct frame *f;
611 char *bits;
612 unsigned int width, height;
614 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
615 Pixmap bitmap;
616 int id;
618 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
619 bits, width, height);
621 if (! bitmap)
622 return -1;
624 id = x_allocate_bitmap_record (f);
625 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
626 dpyinfo->bitmaps[id - 1].file = NULL;
627 dpyinfo->bitmaps[id - 1].refcount = 1;
628 dpyinfo->bitmaps[id - 1].depth = 1;
629 dpyinfo->bitmaps[id - 1].height = height;
630 dpyinfo->bitmaps[id - 1].width = width;
632 return id;
635 /* Create bitmap from file FILE for frame F. */
638 x_create_bitmap_from_file (f, file)
639 struct frame *f;
640 Lisp_Object file;
642 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
643 unsigned int width, height;
644 Pixmap bitmap;
645 int xhot, yhot, result, id;
646 Lisp_Object found;
647 int fd;
648 char *filename;
650 /* Look for an existing bitmap with the same name. */
651 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
653 if (dpyinfo->bitmaps[id].refcount
654 && dpyinfo->bitmaps[id].file
655 && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
657 ++dpyinfo->bitmaps[id].refcount;
658 return id + 1;
662 /* Search bitmap-file-path for the file, if appropriate. */
663 fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
664 if (fd < 0)
665 return -1;
666 /* XReadBitmapFile won't handle magic file names. */
667 if (fd == 0)
668 return -1;
669 emacs_close (fd);
671 filename = (char *) XSTRING (found)->data;
673 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
674 filename, &width, &height, &bitmap, &xhot, &yhot);
675 if (result != BitmapSuccess)
676 return -1;
678 id = x_allocate_bitmap_record (f);
679 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
680 dpyinfo->bitmaps[id - 1].refcount = 1;
681 dpyinfo->bitmaps[id - 1].file
682 = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
683 dpyinfo->bitmaps[id - 1].depth = 1;
684 dpyinfo->bitmaps[id - 1].height = height;
685 dpyinfo->bitmaps[id - 1].width = width;
686 strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
688 return id;
691 /* Remove reference to bitmap with id number ID. */
693 void
694 x_destroy_bitmap (f, id)
695 FRAME_PTR f;
696 int id;
698 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
700 if (id > 0)
702 --dpyinfo->bitmaps[id - 1].refcount;
703 if (dpyinfo->bitmaps[id - 1].refcount == 0)
705 BLOCK_INPUT;
706 XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
707 if (dpyinfo->bitmaps[id - 1].file)
709 xfree (dpyinfo->bitmaps[id - 1].file);
710 dpyinfo->bitmaps[id - 1].file = NULL;
712 UNBLOCK_INPUT;
717 /* Free all the bitmaps for the display specified by DPYINFO. */
719 static void
720 x_destroy_all_bitmaps (dpyinfo)
721 struct x_display_info *dpyinfo;
723 int i;
724 for (i = 0; i < dpyinfo->bitmaps_last; i++)
725 if (dpyinfo->bitmaps[i].refcount > 0)
727 XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
728 if (dpyinfo->bitmaps[i].file)
729 xfree (dpyinfo->bitmaps[i].file);
731 dpyinfo->bitmaps_last = 0;
734 /* Connect the frame-parameter names for X frames
735 to the ways of passing the parameter values to the window system.
737 The name of a parameter, as a Lisp symbol,
738 has an `x-frame-parameter' property which is an integer in Lisp
739 that is an index in this table. */
741 struct x_frame_parm_table
743 char *name;
744 void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
747 static void x_change_window_heights P_ ((Lisp_Object, int));
748 static void x_disable_image P_ ((struct frame *, struct image *));
749 static void x_create_im P_ ((struct frame *));
750 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
751 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
752 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
753 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
754 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
755 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
756 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
757 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
758 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
759 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
760 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
761 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
762 Lisp_Object));
763 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
764 void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
765 void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
766 void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
767 Lisp_Object));
768 void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
769 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
770 void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
771 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
772 void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
773 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
774 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
775 Lisp_Object));
776 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
777 Lisp_Object));
778 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
779 Lisp_Object,
780 Lisp_Object,
781 char *, char *,
782 int));
783 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
784 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
785 Lisp_Object));
786 static void init_color_table P_ ((void));
787 static void free_color_table P_ ((void));
788 static unsigned long *colors_in_color_table P_ ((int *n));
789 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
790 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
794 static struct x_frame_parm_table x_frame_parms[] =
796 "auto-raise", x_set_autoraise,
797 "auto-lower", x_set_autolower,
798 "background-color", x_set_background_color,
799 "border-color", x_set_border_color,
800 "border-width", x_set_border_width,
801 "cursor-color", x_set_cursor_color,
802 "cursor-type", x_set_cursor_type,
803 "font", x_set_font,
804 "foreground-color", x_set_foreground_color,
805 "icon-name", x_set_icon_name,
806 "icon-type", x_set_icon_type,
807 "internal-border-width", x_set_internal_border_width,
808 "menu-bar-lines", x_set_menu_bar_lines,
809 "mouse-color", x_set_mouse_color,
810 "name", x_explicitly_set_name,
811 "scroll-bar-width", x_set_scroll_bar_width,
812 "title", x_set_title,
813 "unsplittable", x_set_unsplittable,
814 "vertical-scroll-bars", x_set_vertical_scroll_bars,
815 "visibility", x_set_visibility,
816 "tool-bar-lines", x_set_tool_bar_lines,
817 "scroll-bar-foreground", x_set_scroll_bar_foreground,
818 "scroll-bar-background", x_set_scroll_bar_background,
819 "screen-gamma", x_set_screen_gamma,
820 "line-spacing", x_set_line_spacing
823 /* Attach the `x-frame-parameter' properties to
824 the Lisp symbol names of parameters relevant to X. */
826 void
827 init_x_parm_symbols ()
829 int i;
831 for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
832 Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
833 make_number (i));
836 /* Change the parameters of frame F as specified by ALIST.
837 If a parameter is not specially recognized, do nothing special;
838 otherwise call the `x_set_...' function for that parameter.
839 Except for certain geometry properties, always call store_frame_param
840 to store the new value in the parameter alist. */
842 void
843 x_set_frame_parameters (f, alist)
844 FRAME_PTR f;
845 Lisp_Object alist;
847 Lisp_Object tail;
849 /* If both of these parameters are present, it's more efficient to
850 set them both at once. So we wait until we've looked at the
851 entire list before we set them. */
852 int width, height;
854 /* Same here. */
855 Lisp_Object left, top;
857 /* Same with these. */
858 Lisp_Object icon_left, icon_top;
860 /* Record in these vectors all the parms specified. */
861 Lisp_Object *parms;
862 Lisp_Object *values;
863 int i, p;
864 int left_no_change = 0, top_no_change = 0;
865 int icon_left_no_change = 0, icon_top_no_change = 0;
867 struct gcpro gcpro1, gcpro2;
869 i = 0;
870 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
871 i++;
873 parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
874 values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
876 /* Extract parm names and values into those vectors. */
878 i = 0;
879 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
881 Lisp_Object elt;
883 elt = Fcar (tail);
884 parms[i] = Fcar (elt);
885 values[i] = Fcdr (elt);
886 i++;
888 /* TAIL and ALIST are not used again below here. */
889 alist = tail = Qnil;
891 GCPRO2 (*parms, *values);
892 gcpro1.nvars = i;
893 gcpro2.nvars = i;
895 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
896 because their values appear in VALUES and strings are not valid. */
897 top = left = Qunbound;
898 icon_left = icon_top = Qunbound;
900 /* Provide default values for HEIGHT and WIDTH. */
901 if (FRAME_NEW_WIDTH (f))
902 width = FRAME_NEW_WIDTH (f);
903 else
904 width = FRAME_WIDTH (f);
906 if (FRAME_NEW_HEIGHT (f))
907 height = FRAME_NEW_HEIGHT (f);
908 else
909 height = FRAME_HEIGHT (f);
911 /* Process foreground_color and background_color before anything else.
912 They are independent of other properties, but other properties (e.g.,
913 cursor_color) are dependent upon them. */
914 for (p = 0; p < i; p++)
916 Lisp_Object prop, val;
918 prop = parms[p];
919 val = values[p];
920 if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
922 register Lisp_Object param_index, old_value;
924 param_index = Fget (prop, Qx_frame_parameter);
925 old_value = get_frame_param (f, prop);
926 store_frame_param (f, prop, val);
927 if (NATNUMP (param_index)
928 && (XFASTINT (param_index)
929 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
930 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
934 /* Now process them in reverse of specified order. */
935 for (i--; i >= 0; i--)
937 Lisp_Object prop, val;
939 prop = parms[i];
940 val = values[i];
942 if (EQ (prop, Qwidth) && NUMBERP (val))
943 width = XFASTINT (val);
944 else if (EQ (prop, Qheight) && NUMBERP (val))
945 height = XFASTINT (val);
946 else if (EQ (prop, Qtop))
947 top = val;
948 else if (EQ (prop, Qleft))
949 left = val;
950 else if (EQ (prop, Qicon_top))
951 icon_top = val;
952 else if (EQ (prop, Qicon_left))
953 icon_left = val;
954 else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
955 /* Processed above. */
956 continue;
957 else
959 register Lisp_Object param_index, old_value;
961 param_index = Fget (prop, Qx_frame_parameter);
962 old_value = get_frame_param (f, prop);
963 store_frame_param (f, prop, val);
964 if (NATNUMP (param_index)
965 && (XFASTINT (param_index)
966 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
967 (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
971 /* Don't die if just one of these was set. */
972 if (EQ (left, Qunbound))
974 left_no_change = 1;
975 if (f->output_data.x->left_pos < 0)
976 left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
977 else
978 XSETINT (left, f->output_data.x->left_pos);
980 if (EQ (top, Qunbound))
982 top_no_change = 1;
983 if (f->output_data.x->top_pos < 0)
984 top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
985 else
986 XSETINT (top, f->output_data.x->top_pos);
989 /* If one of the icon positions was not set, preserve or default it. */
990 if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
992 icon_left_no_change = 1;
993 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
994 if (NILP (icon_left))
995 XSETINT (icon_left, 0);
997 if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
999 icon_top_no_change = 1;
1000 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
1001 if (NILP (icon_top))
1002 XSETINT (icon_top, 0);
1005 /* Don't set these parameters unless they've been explicitly
1006 specified. The window might be mapped or resized while we're in
1007 this function, and we don't want to override that unless the lisp
1008 code has asked for it.
1010 Don't set these parameters unless they actually differ from the
1011 window's current parameters; the window may not actually exist
1012 yet. */
1014 Lisp_Object frame;
1016 check_frame_size (f, &height, &width);
1018 XSETFRAME (frame, f);
1020 if (width != FRAME_WIDTH (f)
1021 || height != FRAME_HEIGHT (f)
1022 || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
1023 Fset_frame_size (frame, make_number (width), make_number (height));
1025 if ((!NILP (left) || !NILP (top))
1026 && ! (left_no_change && top_no_change)
1027 && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
1028 && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
1030 int leftpos = 0;
1031 int toppos = 0;
1033 /* Record the signs. */
1034 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
1035 if (EQ (left, Qminus))
1036 f->output_data.x->size_hint_flags |= XNegative;
1037 else if (INTEGERP (left))
1039 leftpos = XINT (left);
1040 if (leftpos < 0)
1041 f->output_data.x->size_hint_flags |= XNegative;
1043 else if (CONSP (left) && EQ (XCAR (left), Qminus)
1044 && CONSP (XCDR (left))
1045 && INTEGERP (XCAR (XCDR (left))))
1047 leftpos = - XINT (XCAR (XCDR (left)));
1048 f->output_data.x->size_hint_flags |= XNegative;
1050 else if (CONSP (left) && EQ (XCAR (left), Qplus)
1051 && CONSP (XCDR (left))
1052 && INTEGERP (XCAR (XCDR (left))))
1054 leftpos = XINT (XCAR (XCDR (left)));
1057 if (EQ (top, Qminus))
1058 f->output_data.x->size_hint_flags |= YNegative;
1059 else if (INTEGERP (top))
1061 toppos = XINT (top);
1062 if (toppos < 0)
1063 f->output_data.x->size_hint_flags |= YNegative;
1065 else if (CONSP (top) && EQ (XCAR (top), Qminus)
1066 && CONSP (XCDR (top))
1067 && INTEGERP (XCAR (XCDR (top))))
1069 toppos = - XINT (XCAR (XCDR (top)));
1070 f->output_data.x->size_hint_flags |= YNegative;
1072 else if (CONSP (top) && EQ (XCAR (top), Qplus)
1073 && CONSP (XCDR (top))
1074 && INTEGERP (XCAR (XCDR (top))))
1076 toppos = XINT (XCAR (XCDR (top)));
1080 /* Store the numeric value of the position. */
1081 f->output_data.x->top_pos = toppos;
1082 f->output_data.x->left_pos = leftpos;
1084 f->output_data.x->win_gravity = NorthWestGravity;
1086 /* Actually set that position, and convert to absolute. */
1087 x_set_offset (f, leftpos, toppos, -1);
1090 if ((!NILP (icon_left) || !NILP (icon_top))
1091 && ! (icon_left_no_change && icon_top_no_change))
1092 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
1095 UNGCPRO;
1098 /* Store the screen positions of frame F into XPTR and YPTR.
1099 These are the positions of the containing window manager window,
1100 not Emacs's own window. */
1102 void
1103 x_real_positions (f, xptr, yptr)
1104 FRAME_PTR f;
1105 int *xptr, *yptr;
1107 int win_x, win_y;
1108 Window child;
1110 /* This is pretty gross, but seems to be the easiest way out of
1111 the problem that arises when restarting window-managers. */
1113 #ifdef USE_X_TOOLKIT
1114 Window outer = (f->output_data.x->widget
1115 ? XtWindow (f->output_data.x->widget)
1116 : FRAME_X_WINDOW (f));
1117 #else
1118 Window outer = f->output_data.x->window_desc;
1119 #endif
1120 Window tmp_root_window;
1121 Window *tmp_children;
1122 unsigned int tmp_nchildren;
1124 while (1)
1126 int count = x_catch_errors (FRAME_X_DISPLAY (f));
1127 Window outer_window;
1129 XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
1130 &f->output_data.x->parent_desc,
1131 &tmp_children, &tmp_nchildren);
1132 XFree ((char *) tmp_children);
1134 win_x = win_y = 0;
1136 /* Find the position of the outside upper-left corner of
1137 the inner window, with respect to the outer window. */
1138 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
1139 outer_window = f->output_data.x->parent_desc;
1140 else
1141 outer_window = outer;
1143 XTranslateCoordinates (FRAME_X_DISPLAY (f),
1145 /* From-window, to-window. */
1146 outer_window,
1147 FRAME_X_DISPLAY_INFO (f)->root_window,
1149 /* From-position, to-position. */
1150 0, 0, &win_x, &win_y,
1152 /* Child of win. */
1153 &child);
1155 /* It is possible for the window returned by the XQueryNotify
1156 to become invalid by the time we call XTranslateCoordinates.
1157 That can happen when you restart some window managers.
1158 If so, we get an error in XTranslateCoordinates.
1159 Detect that and try the whole thing over. */
1160 if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
1162 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1163 break;
1166 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1169 *xptr = win_x;
1170 *yptr = win_y;
1173 /* Insert a description of internally-recorded parameters of frame X
1174 into the parameter alist *ALISTPTR that is to be given to the user.
1175 Only parameters that are specific to the X window system
1176 and whose values are not correctly recorded in the frame's
1177 param_alist need to be considered here. */
1179 void
1180 x_report_frame_params (f, alistptr)
1181 struct frame *f;
1182 Lisp_Object *alistptr;
1184 char buf[16];
1185 Lisp_Object tem;
1187 /* Represent negative positions (off the top or left screen edge)
1188 in a way that Fmodify_frame_parameters will understand correctly. */
1189 XSETINT (tem, f->output_data.x->left_pos);
1190 if (f->output_data.x->left_pos >= 0)
1191 store_in_alist (alistptr, Qleft, tem);
1192 else
1193 store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
1195 XSETINT (tem, f->output_data.x->top_pos);
1196 if (f->output_data.x->top_pos >= 0)
1197 store_in_alist (alistptr, Qtop, tem);
1198 else
1199 store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
1201 store_in_alist (alistptr, Qborder_width,
1202 make_number (f->output_data.x->border_width));
1203 store_in_alist (alistptr, Qinternal_border_width,
1204 make_number (f->output_data.x->internal_border_width));
1205 sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
1206 store_in_alist (alistptr, Qwindow_id,
1207 build_string (buf));
1208 #ifdef USE_X_TOOLKIT
1209 /* Tooltip frame may not have this widget. */
1210 if (f->output_data.x->widget)
1211 #endif
1212 sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
1213 store_in_alist (alistptr, Qouter_window_id,
1214 build_string (buf));
1215 store_in_alist (alistptr, Qicon_name, f->icon_name);
1216 FRAME_SAMPLE_VISIBILITY (f);
1217 store_in_alist (alistptr, Qvisibility,
1218 (FRAME_VISIBLE_P (f) ? Qt
1219 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
1220 store_in_alist (alistptr, Qdisplay,
1221 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
1223 if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
1224 tem = Qnil;
1225 else
1226 XSETFASTINT (tem, f->output_data.x->parent_desc);
1227 store_in_alist (alistptr, Qparent_id, tem);
1232 /* Gamma-correct COLOR on frame F. */
1234 void
1235 gamma_correct (f, color)
1236 struct frame *f;
1237 XColor *color;
1239 if (f->gamma)
1241 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
1242 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
1243 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
1248 /* Decide if color named COLOR_NAME is valid for use on frame F. If
1249 so, return the RGB values in COLOR. If ALLOC_P is non-zero,
1250 allocate the color. Value is zero if COLOR_NAME is invalid, or
1251 no color could be allocated. */
1254 x_defined_color (f, color_name, color, alloc_p)
1255 struct frame *f;
1256 char *color_name;
1257 XColor *color;
1258 int alloc_p;
1260 int success_p;
1261 Display *dpy = FRAME_X_DISPLAY (f);
1262 Colormap cmap = FRAME_X_COLORMAP (f);
1264 BLOCK_INPUT;
1265 success_p = XParseColor (dpy, cmap, color_name, color);
1266 if (success_p && alloc_p)
1267 success_p = x_alloc_nearest_color (f, cmap, color);
1268 UNBLOCK_INPUT;
1270 return success_p;
1274 /* Return the pixel color value for color COLOR_NAME on frame F. If F
1275 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
1276 Signal an error if color can't be allocated. */
1279 x_decode_color (f, color_name, mono_color)
1280 FRAME_PTR f;
1281 Lisp_Object color_name;
1282 int mono_color;
1284 XColor cdef;
1286 CHECK_STRING (color_name, 0);
1288 #if 0 /* Don't do this. It's wrong when we're not using the default
1289 colormap, it makes freeing difficult, and it's probably not
1290 an important optimization. */
1291 if (strcmp (XSTRING (color_name)->data, "black") == 0)
1292 return BLACK_PIX_DEFAULT (f);
1293 else if (strcmp (XSTRING (color_name)->data, "white") == 0)
1294 return WHITE_PIX_DEFAULT (f);
1295 #endif
1297 /* Return MONO_COLOR for monochrome frames. */
1298 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
1299 return mono_color;
1301 /* x_defined_color is responsible for coping with failures
1302 by looking for a near-miss. */
1303 if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
1304 return cdef.pixel;
1306 Fsignal (Qerror, Fcons (build_string ("Undefined color"),
1307 Fcons (color_name, Qnil)));
1308 return 0;
1313 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
1314 the previous value of that parameter, NEW_VALUE is the new value. */
1316 static void
1317 x_set_line_spacing (f, new_value, old_value)
1318 struct frame *f;
1319 Lisp_Object new_value, old_value;
1321 if (NILP (new_value))
1322 f->extra_line_spacing = 0;
1323 else if (NATNUMP (new_value))
1324 f->extra_line_spacing = XFASTINT (new_value);
1325 else
1326 Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
1327 Fcons (new_value, Qnil)));
1328 if (FRAME_VISIBLE_P (f))
1329 redraw_frame (f);
1333 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
1334 the previous value of that parameter, NEW_VALUE is the new value. */
1336 static void
1337 x_set_screen_gamma (f, new_value, old_value)
1338 struct frame *f;
1339 Lisp_Object new_value, old_value;
1341 if (NILP (new_value))
1342 f->gamma = 0;
1343 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
1344 /* The value 0.4545 is the normal viewing gamma. */
1345 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
1346 else
1347 Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
1348 Fcons (new_value, Qnil)));
1350 clear_face_cache (0);
1354 /* Functions called only from `x_set_frame_param'
1355 to set individual parameters.
1357 If FRAME_X_WINDOW (f) is 0,
1358 the frame is being created and its X-window does not exist yet.
1359 In that case, just record the parameter's new value
1360 in the standard place; do not attempt to change the window. */
1362 void
1363 x_set_foreground_color (f, arg, oldval)
1364 struct frame *f;
1365 Lisp_Object arg, oldval;
1367 unsigned long pixel
1368 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1370 unload_color (f, f->output_data.x->foreground_pixel);
1371 f->output_data.x->foreground_pixel = pixel;
1373 if (FRAME_X_WINDOW (f) != 0)
1375 BLOCK_INPUT;
1376 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1377 f->output_data.x->foreground_pixel);
1378 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1379 f->output_data.x->foreground_pixel);
1380 UNBLOCK_INPUT;
1381 update_face_from_frame_parameter (f, Qforeground_color, arg);
1382 if (FRAME_VISIBLE_P (f))
1383 redraw_frame (f);
1387 void
1388 x_set_background_color (f, arg, oldval)
1389 struct frame *f;
1390 Lisp_Object arg, oldval;
1392 unsigned long pixel
1393 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1395 unload_color (f, f->output_data.x->background_pixel);
1396 f->output_data.x->background_pixel = pixel;
1398 if (FRAME_X_WINDOW (f) != 0)
1400 BLOCK_INPUT;
1401 /* The main frame area. */
1402 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1403 f->output_data.x->background_pixel);
1404 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
1405 f->output_data.x->background_pixel);
1406 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1407 f->output_data.x->background_pixel);
1408 XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1409 f->output_data.x->background_pixel);
1411 Lisp_Object bar;
1412 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
1413 bar = XSCROLL_BAR (bar)->next)
1414 XSetWindowBackground (FRAME_X_DISPLAY (f),
1415 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
1416 f->output_data.x->background_pixel);
1418 UNBLOCK_INPUT;
1420 update_face_from_frame_parameter (f, Qbackground_color, arg);
1422 if (FRAME_VISIBLE_P (f))
1423 redraw_frame (f);
1427 void
1428 x_set_mouse_color (f, arg, oldval)
1429 struct frame *f;
1430 Lisp_Object arg, oldval;
1432 Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
1433 Cursor busy_cursor;
1434 int count;
1435 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1436 unsigned long mask_color = f->output_data.x->background_pixel;
1438 /* Don't let pointers be invisible. */
1439 if (mask_color == pixel
1440 && mask_color == f->output_data.x->background_pixel)
1441 pixel = f->output_data.x->foreground_pixel;
1443 unload_color (f, f->output_data.x->mouse_pixel);
1444 f->output_data.x->mouse_pixel = pixel;
1446 BLOCK_INPUT;
1448 /* It's not okay to crash if the user selects a screwy cursor. */
1449 count = x_catch_errors (FRAME_X_DISPLAY (f));
1451 if (!EQ (Qnil, Vx_pointer_shape))
1453 CHECK_NUMBER (Vx_pointer_shape, 0);
1454 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
1456 else
1457 cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1458 x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
1460 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1462 CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
1463 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1464 XINT (Vx_nontext_pointer_shape));
1466 else
1467 nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
1468 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1470 if (!EQ (Qnil, Vx_busy_pointer_shape))
1472 CHECK_NUMBER (Vx_busy_pointer_shape, 0);
1473 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1474 XINT (Vx_busy_pointer_shape));
1476 else
1477 busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
1478 x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
1480 x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
1481 if (!EQ (Qnil, Vx_mode_pointer_shape))
1483 CHECK_NUMBER (Vx_mode_pointer_shape, 0);
1484 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
1485 XINT (Vx_mode_pointer_shape));
1487 else
1488 mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
1489 x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
1491 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1493 CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
1494 cross_cursor
1495 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1496 XINT (Vx_sensitive_text_pointer_shape));
1498 else
1499 cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
1501 /* Check and report errors with the above calls. */
1502 x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
1503 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
1506 XColor fore_color, back_color;
1508 fore_color.pixel = f->output_data.x->mouse_pixel;
1509 back_color.pixel = mask_color;
1510 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1511 &fore_color);
1512 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
1513 &back_color);
1514 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1515 &fore_color, &back_color);
1516 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1517 &fore_color, &back_color);
1518 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1519 &fore_color, &back_color);
1520 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1521 &fore_color, &back_color);
1522 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1523 &fore_color, &back_color);
1526 if (FRAME_X_WINDOW (f) != 0)
1527 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1529 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1530 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1531 f->output_data.x->text_cursor = cursor;
1533 if (nontext_cursor != f->output_data.x->nontext_cursor
1534 && f->output_data.x->nontext_cursor != 0)
1535 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1536 f->output_data.x->nontext_cursor = nontext_cursor;
1538 if (busy_cursor != f->output_data.x->busy_cursor
1539 && f->output_data.x->busy_cursor != 0)
1540 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1541 f->output_data.x->busy_cursor = busy_cursor;
1543 if (mode_cursor != f->output_data.x->modeline_cursor
1544 && f->output_data.x->modeline_cursor != 0)
1545 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1546 f->output_data.x->modeline_cursor = mode_cursor;
1548 if (cross_cursor != f->output_data.x->cross_cursor
1549 && f->output_data.x->cross_cursor != 0)
1550 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1551 f->output_data.x->cross_cursor = cross_cursor;
1553 XFlush (FRAME_X_DISPLAY (f));
1554 UNBLOCK_INPUT;
1556 update_face_from_frame_parameter (f, Qmouse_color, arg);
1559 void
1560 x_set_cursor_color (f, arg, oldval)
1561 struct frame *f;
1562 Lisp_Object arg, oldval;
1564 unsigned long fore_pixel, pixel;
1565 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1567 if (!NILP (Vx_cursor_fore_pixel))
1569 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1570 WHITE_PIX_DEFAULT (f));
1571 fore_pixel_allocated_p = 1;
1573 else
1574 fore_pixel = f->output_data.x->background_pixel;
1576 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1577 pixel_allocated_p = 1;
1579 /* Make sure that the cursor color differs from the background color. */
1580 if (pixel == f->output_data.x->background_pixel)
1582 if (pixel_allocated_p)
1584 x_free_colors (f, &pixel, 1);
1585 pixel_allocated_p = 0;
1588 pixel = f->output_data.x->mouse_pixel;
1589 if (pixel == fore_pixel)
1591 if (fore_pixel_allocated_p)
1593 x_free_colors (f, &fore_pixel, 1);
1594 fore_pixel_allocated_p = 0;
1596 fore_pixel = f->output_data.x->background_pixel;
1600 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1601 if (!fore_pixel_allocated_p)
1602 fore_pixel = x_copy_color (f, fore_pixel);
1603 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1605 unload_color (f, f->output_data.x->cursor_pixel);
1606 if (!pixel_allocated_p)
1607 pixel = x_copy_color (f, pixel);
1608 f->output_data.x->cursor_pixel = pixel;
1610 if (FRAME_X_WINDOW (f) != 0)
1612 BLOCK_INPUT;
1613 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1614 f->output_data.x->cursor_pixel);
1615 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1616 fore_pixel);
1617 UNBLOCK_INPUT;
1619 if (FRAME_VISIBLE_P (f))
1621 x_update_cursor (f, 0);
1622 x_update_cursor (f, 1);
1626 update_face_from_frame_parameter (f, Qcursor_color, arg);
1629 /* Set the border-color of frame F to value described by ARG.
1630 ARG can be a string naming a color.
1631 The border-color is used for the border that is drawn by the X server.
1632 Note that this does not fully take effect if done before
1633 F has an x-window; it must be redone when the window is created.
1635 Note: this is done in two routines because of the way X10 works.
1637 Note: under X11, this is normally the province of the window manager,
1638 and so emacs' border colors may be overridden. */
1640 void
1641 x_set_border_color (f, arg, oldval)
1642 struct frame *f;
1643 Lisp_Object arg, oldval;
1645 int pix;
1647 CHECK_STRING (arg, 0);
1648 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1649 x_set_border_pixel (f, pix);
1650 update_face_from_frame_parameter (f, Qborder_color, arg);
1653 /* Set the border-color of frame F to pixel value PIX.
1654 Note that this does not fully take effect if done before
1655 F has an x-window. */
1657 void
1658 x_set_border_pixel (f, pix)
1659 struct frame *f;
1660 int pix;
1662 unload_color (f, f->output_data.x->border_pixel);
1663 f->output_data.x->border_pixel = pix;
1665 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1667 BLOCK_INPUT;
1668 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1669 (unsigned long)pix);
1670 UNBLOCK_INPUT;
1672 if (FRAME_VISIBLE_P (f))
1673 redraw_frame (f);
1678 /* Value is the internal representation of the specified cursor type
1679 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1680 of the bar cursor. */
1682 enum text_cursor_kinds
1683 x_specified_cursor_type (arg, width)
1684 Lisp_Object arg;
1685 int *width;
1687 enum text_cursor_kinds type;
1689 if (EQ (arg, Qbar))
1691 type = BAR_CURSOR;
1692 *width = 2;
1694 else if (CONSP (arg)
1695 && EQ (XCAR (arg), Qbar)
1696 && INTEGERP (XCDR (arg))
1697 && XINT (XCDR (arg)) >= 0)
1699 type = BAR_CURSOR;
1700 *width = XINT (XCDR (arg));
1702 else if (NILP (arg))
1703 type = NO_CURSOR;
1704 else
1705 /* Treat anything unknown as "box cursor".
1706 It was bad to signal an error; people have trouble fixing
1707 .Xdefaults with Emacs, when it has something bad in it. */
1708 type = FILLED_BOX_CURSOR;
1710 return type;
1713 void
1714 x_set_cursor_type (f, arg, oldval)
1715 FRAME_PTR f;
1716 Lisp_Object arg, oldval;
1718 int width;
1720 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1721 f->output_data.x->cursor_width = width;
1723 /* Make sure the cursor gets redrawn. This is overkill, but how
1724 often do people change cursor types? */
1725 update_mode_lines++;
1728 void
1729 x_set_icon_type (f, arg, oldval)
1730 struct frame *f;
1731 Lisp_Object arg, oldval;
1733 int result;
1735 if (STRINGP (arg))
1737 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1738 return;
1740 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1741 return;
1743 BLOCK_INPUT;
1744 if (NILP (arg))
1745 result = x_text_icon (f,
1746 (char *) XSTRING ((!NILP (f->icon_name)
1747 ? f->icon_name
1748 : f->name))->data);
1749 else
1750 result = x_bitmap_icon (f, arg);
1752 if (result)
1754 UNBLOCK_INPUT;
1755 error ("No icon window available");
1758 XFlush (FRAME_X_DISPLAY (f));
1759 UNBLOCK_INPUT;
1762 /* Return non-nil if frame F wants a bitmap icon. */
1764 Lisp_Object
1765 x_icon_type (f)
1766 FRAME_PTR f;
1768 Lisp_Object tem;
1770 tem = assq_no_quit (Qicon_type, f->param_alist);
1771 if (CONSP (tem))
1772 return XCDR (tem);
1773 else
1774 return Qnil;
1777 void
1778 x_set_icon_name (f, arg, oldval)
1779 struct frame *f;
1780 Lisp_Object arg, oldval;
1782 int result;
1784 if (STRINGP (arg))
1786 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1787 return;
1789 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1790 return;
1792 f->icon_name = arg;
1794 if (f->output_data.x->icon_bitmap != 0)
1795 return;
1797 BLOCK_INPUT;
1799 result = x_text_icon (f,
1800 (char *) XSTRING ((!NILP (f->icon_name)
1801 ? f->icon_name
1802 : !NILP (f->title)
1803 ? f->title
1804 : f->name))->data);
1806 if (result)
1808 UNBLOCK_INPUT;
1809 error ("No icon window available");
1812 XFlush (FRAME_X_DISPLAY (f));
1813 UNBLOCK_INPUT;
1816 void
1817 x_set_font (f, arg, oldval)
1818 struct frame *f;
1819 Lisp_Object arg, oldval;
1821 Lisp_Object result;
1822 Lisp_Object fontset_name;
1823 Lisp_Object frame;
1825 CHECK_STRING (arg, 1);
1827 fontset_name = Fquery_fontset (arg, Qnil);
1829 BLOCK_INPUT;
1830 result = (STRINGP (fontset_name)
1831 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1832 : x_new_font (f, XSTRING (arg)->data));
1833 UNBLOCK_INPUT;
1835 if (EQ (result, Qnil))
1836 error ("Font `%s' is not defined", XSTRING (arg)->data);
1837 else if (EQ (result, Qt))
1838 error ("The characters of the given font have varying widths");
1839 else if (STRINGP (result))
1841 store_frame_param (f, Qfont, result);
1842 recompute_basic_faces (f);
1844 else
1845 abort ();
1847 do_pending_window_change (0);
1849 /* Don't call `face-set-after-frame-default' when faces haven't been
1850 initialized yet. This is the case when called from
1851 Fx_create_frame. In that case, the X widget or window doesn't
1852 exist either, and we can end up in x_report_frame_params with a
1853 null widget which gives a segfault. */
1854 if (FRAME_FACE_CACHE (f))
1856 XSETFRAME (frame, f);
1857 call1 (Qface_set_after_frame_default, frame);
1861 void
1862 x_set_border_width (f, arg, oldval)
1863 struct frame *f;
1864 Lisp_Object arg, oldval;
1866 CHECK_NUMBER (arg, 0);
1868 if (XINT (arg) == f->output_data.x->border_width)
1869 return;
1871 if (FRAME_X_WINDOW (f) != 0)
1872 error ("Cannot change the border width of a window");
1874 f->output_data.x->border_width = XINT (arg);
1877 void
1878 x_set_internal_border_width (f, arg, oldval)
1879 struct frame *f;
1880 Lisp_Object arg, oldval;
1882 int old = f->output_data.x->internal_border_width;
1884 CHECK_NUMBER (arg, 0);
1885 f->output_data.x->internal_border_width = XINT (arg);
1886 if (f->output_data.x->internal_border_width < 0)
1887 f->output_data.x->internal_border_width = 0;
1889 #ifdef USE_X_TOOLKIT
1890 if (f->output_data.x->edit_widget)
1891 widget_store_internal_border (f->output_data.x->edit_widget);
1892 #endif
1894 if (f->output_data.x->internal_border_width == old)
1895 return;
1897 if (FRAME_X_WINDOW (f) != 0)
1899 x_set_window_size (f, 0, f->width, f->height);
1900 SET_FRAME_GARBAGED (f);
1901 do_pending_window_change (0);
1905 void
1906 x_set_visibility (f, value, oldval)
1907 struct frame *f;
1908 Lisp_Object value, oldval;
1910 Lisp_Object frame;
1911 XSETFRAME (frame, f);
1913 if (NILP (value))
1914 Fmake_frame_invisible (frame, Qt);
1915 else if (EQ (value, Qicon))
1916 Ficonify_frame (frame);
1917 else
1918 Fmake_frame_visible (frame);
1922 /* Change window heights in windows rooted in WINDOW by N lines. */
1924 static void
1925 x_change_window_heights (window, n)
1926 Lisp_Object window;
1927 int n;
1929 struct window *w = XWINDOW (window);
1931 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1932 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1934 if (INTEGERP (w->orig_top))
1935 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1936 if (INTEGERP (w->orig_height))
1937 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1939 /* Handle just the top child in a vertical split. */
1940 if (!NILP (w->vchild))
1941 x_change_window_heights (w->vchild, n);
1943 /* Adjust all children in a horizontal split. */
1944 for (window = w->hchild; !NILP (window); window = w->next)
1946 w = XWINDOW (window);
1947 x_change_window_heights (window, n);
1951 void
1952 x_set_menu_bar_lines (f, value, oldval)
1953 struct frame *f;
1954 Lisp_Object value, oldval;
1956 int nlines;
1957 #ifndef USE_X_TOOLKIT
1958 int olines = FRAME_MENU_BAR_LINES (f);
1959 #endif
1961 /* Right now, menu bars don't work properly in minibuf-only frames;
1962 most of the commands try to apply themselves to the minibuffer
1963 frame itself, and get an error because you can't switch buffers
1964 in or split the minibuffer window. */
1965 if (FRAME_MINIBUF_ONLY_P (f))
1966 return;
1968 if (INTEGERP (value))
1969 nlines = XINT (value);
1970 else
1971 nlines = 0;
1973 /* Make sure we redisplay all windows in this frame. */
1974 windows_or_buffers_changed++;
1976 #ifdef USE_X_TOOLKIT
1977 FRAME_MENU_BAR_LINES (f) = 0;
1978 if (nlines)
1980 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1981 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1982 /* Make sure next redisplay shows the menu bar. */
1983 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1985 else
1987 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1988 free_frame_menubar (f);
1989 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1990 if (FRAME_X_P (f))
1991 f->output_data.x->menubar_widget = 0;
1993 #else /* not USE_X_TOOLKIT */
1994 FRAME_MENU_BAR_LINES (f) = nlines;
1995 x_change_window_heights (f->root_window, nlines - olines);
1996 #endif /* not USE_X_TOOLKIT */
1997 adjust_glyphs (f);
2001 /* Set the number of lines used for the tool bar of frame F to VALUE.
2002 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2003 is the old number of tool bar lines. This function changes the
2004 height of all windows on frame F to match the new tool bar height.
2005 The frame's height doesn't change. */
2007 void
2008 x_set_tool_bar_lines (f, value, oldval)
2009 struct frame *f;
2010 Lisp_Object value, oldval;
2012 int delta, nlines, root_height;
2013 Lisp_Object root_window;
2015 /* Use VALUE only if an integer >= 0. */
2016 if (INTEGERP (value) && XINT (value) >= 0)
2017 nlines = XFASTINT (value);
2018 else
2019 nlines = 0;
2021 /* Make sure we redisplay all windows in this frame. */
2022 ++windows_or_buffers_changed;
2024 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2026 /* Don't resize the tool-bar to more than we have room for. */
2027 root_window = FRAME_ROOT_WINDOW (f);
2028 root_height = XINT (XWINDOW (root_window)->height);
2029 if (root_height - delta < 1)
2031 delta = root_height - 1;
2032 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2035 FRAME_TOOL_BAR_LINES (f) = nlines;
2036 x_change_window_heights (root_window, delta);
2037 adjust_glyphs (f);
2039 /* We also have to make sure that the internal border at the top of
2040 the frame, below the menu bar or tool bar, is redrawn when the
2041 tool bar disappears. This is so because the internal border is
2042 below the tool bar if one is displayed, but is below the menu bar
2043 if there isn't a tool bar. The tool bar draws into the area
2044 below the menu bar. */
2045 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2047 updating_frame = f;
2048 clear_frame ();
2049 updating_frame = NULL;
2054 /* Set the foreground color for scroll bars on frame F to VALUE.
2055 VALUE should be a string, a color name. If it isn't a string or
2056 isn't a valid color name, do nothing. OLDVAL is the old value of
2057 the frame parameter. */
2059 void
2060 x_set_scroll_bar_foreground (f, value, oldval)
2061 struct frame *f;
2062 Lisp_Object value, oldval;
2064 unsigned long pixel;
2066 if (STRINGP (value))
2067 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2068 else
2069 pixel = -1;
2071 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2072 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2074 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2075 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2077 /* Remove all scroll bars because they have wrong colors. */
2078 if (condemn_scroll_bars_hook)
2079 (*condemn_scroll_bars_hook) (f);
2080 if (judge_scroll_bars_hook)
2081 (*judge_scroll_bars_hook) (f);
2083 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2084 redraw_frame (f);
2089 /* Set the background color for scroll bars on frame F to VALUE VALUE
2090 should be a string, a color name. If it isn't a string or isn't a
2091 valid color name, do nothing. OLDVAL is the old value of the frame
2092 parameter. */
2094 void
2095 x_set_scroll_bar_background (f, value, oldval)
2096 struct frame *f;
2097 Lisp_Object value, oldval;
2099 unsigned long pixel;
2101 if (STRINGP (value))
2102 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2103 else
2104 pixel = -1;
2106 if (f->output_data.x->scroll_bar_background_pixel != -1)
2107 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2109 f->output_data.x->scroll_bar_background_pixel = pixel;
2110 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2112 /* Remove all scroll bars because they have wrong colors. */
2113 if (condemn_scroll_bars_hook)
2114 (*condemn_scroll_bars_hook) (f);
2115 if (judge_scroll_bars_hook)
2116 (*judge_scroll_bars_hook) (f);
2118 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2119 redraw_frame (f);
2124 /* Encode Lisp string STRING as a text in a format appropriate for
2125 XICCC (X Inter Client Communication Conventions).
2127 If STRING contains only ASCII characters, do no conversion and
2128 return the string data of STRING. Otherwise, encode the text by
2129 CODING_SYSTEM, and return a newly allocated memory area which
2130 should be freed by `xfree' by a caller.
2132 Store the byte length of resulting text in *TEXT_BYTES.
2134 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2135 which means that the `encoding' of the result can be `STRING'.
2136 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2137 the result should be `COMPOUND_TEXT'. */
2139 unsigned char *
2140 x_encode_text (string, coding_system, text_bytes, stringp)
2141 Lisp_Object string, coding_system;
2142 int *text_bytes, *stringp;
2144 unsigned char *str = XSTRING (string)->data;
2145 int chars = XSTRING (string)->size;
2146 int bytes = STRING_BYTES (XSTRING (string));
2147 int charset_info;
2148 int bufsize;
2149 unsigned char *buf;
2150 struct coding_system coding;
2152 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2153 if (charset_info == 0)
2155 /* No multibyte character in OBJ. We need not encode it. */
2156 *text_bytes = bytes;
2157 *stringp = 1;
2158 return str;
2161 setup_coding_system (coding_system, &coding);
2162 coding.src_multibyte = 1;
2163 coding.dst_multibyte = 0;
2164 coding.mode |= CODING_MODE_LAST_BLOCK;
2165 if (coding.type == coding_type_iso2022)
2166 coding.flags |= CODING_FLAG_ISO_SAFE;
2167 bufsize = encoding_buffer_size (&coding, bytes);
2168 buf = (unsigned char *) xmalloc (bufsize);
2169 encode_coding (&coding, str, buf, bytes, bufsize);
2170 *text_bytes = coding.produced;
2171 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2172 return buf;
2176 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2177 x_id_name.
2179 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2180 name; if NAME is a string, set F's name to NAME and set
2181 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2183 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2184 suggesting a new name, which lisp code should override; if
2185 F->explicit_name is set, ignore the new name; otherwise, set it. */
2187 void
2188 x_set_name (f, name, explicit)
2189 struct frame *f;
2190 Lisp_Object name;
2191 int explicit;
2193 /* Make sure that requests from lisp code override requests from
2194 Emacs redisplay code. */
2195 if (explicit)
2197 /* If we're switching from explicit to implicit, we had better
2198 update the mode lines and thereby update the title. */
2199 if (f->explicit_name && NILP (name))
2200 update_mode_lines = 1;
2202 f->explicit_name = ! NILP (name);
2204 else if (f->explicit_name)
2205 return;
2207 /* If NAME is nil, set the name to the x_id_name. */
2208 if (NILP (name))
2210 /* Check for no change needed in this very common case
2211 before we do any consing. */
2212 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2213 XSTRING (f->name)->data))
2214 return;
2215 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2217 else
2218 CHECK_STRING (name, 0);
2220 /* Don't change the name if it's already NAME. */
2221 if (! NILP (Fstring_equal (name, f->name)))
2222 return;
2224 f->name = name;
2226 /* For setting the frame title, the title parameter should override
2227 the name parameter. */
2228 if (! NILP (f->title))
2229 name = f->title;
2231 if (FRAME_X_WINDOW (f))
2233 BLOCK_INPUT;
2234 #ifdef HAVE_X11R4
2236 XTextProperty text, icon;
2237 int bytes, stringp;
2238 Lisp_Object coding_system;
2240 coding_system = Vlocale_coding_system;
2241 if (NILP (coding_system))
2242 coding_system = Qcompound_text;
2243 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2244 text.encoding = (stringp ? XA_STRING
2245 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2246 text.format = 8;
2247 text.nitems = bytes;
2249 if (NILP (f->icon_name))
2251 icon = text;
2253 else
2255 icon.value = x_encode_text (f->icon_name, coding_system,
2256 &bytes, &stringp);
2257 icon.encoding = (stringp ? XA_STRING
2258 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2259 icon.format = 8;
2260 icon.nitems = bytes;
2262 #ifdef USE_X_TOOLKIT
2263 XSetWMName (FRAME_X_DISPLAY (f),
2264 XtWindow (f->output_data.x->widget), &text);
2265 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2266 &icon);
2267 #else /* not USE_X_TOOLKIT */
2268 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2269 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2270 #endif /* not USE_X_TOOLKIT */
2271 if (!NILP (f->icon_name)
2272 && icon.value != XSTRING (f->icon_name)->data)
2273 xfree (icon.value);
2274 if (text.value != XSTRING (name)->data)
2275 xfree (text.value);
2277 #else /* not HAVE_X11R4 */
2278 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2279 XSTRING (name)->data);
2280 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2281 XSTRING (name)->data);
2282 #endif /* not HAVE_X11R4 */
2283 UNBLOCK_INPUT;
2287 /* This function should be called when the user's lisp code has
2288 specified a name for the frame; the name will override any set by the
2289 redisplay code. */
2290 void
2291 x_explicitly_set_name (f, arg, oldval)
2292 FRAME_PTR f;
2293 Lisp_Object arg, oldval;
2295 x_set_name (f, arg, 1);
2298 /* This function should be called by Emacs redisplay code to set the
2299 name; names set this way will never override names set by the user's
2300 lisp code. */
2301 void
2302 x_implicitly_set_name (f, arg, oldval)
2303 FRAME_PTR f;
2304 Lisp_Object arg, oldval;
2306 x_set_name (f, arg, 0);
2309 /* Change the title of frame F to NAME.
2310 If NAME is nil, use the frame name as the title.
2312 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2313 name; if NAME is a string, set F's name to NAME and set
2314 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2316 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2317 suggesting a new name, which lisp code should override; if
2318 F->explicit_name is set, ignore the new name; otherwise, set it. */
2320 void
2321 x_set_title (f, name, old_name)
2322 struct frame *f;
2323 Lisp_Object name, old_name;
2325 /* Don't change the title if it's already NAME. */
2326 if (EQ (name, f->title))
2327 return;
2329 update_mode_lines = 1;
2331 f->title = name;
2333 if (NILP (name))
2334 name = f->name;
2335 else
2336 CHECK_STRING (name, 0);
2338 if (FRAME_X_WINDOW (f))
2340 BLOCK_INPUT;
2341 #ifdef HAVE_X11R4
2343 XTextProperty text, icon;
2344 int bytes, stringp;
2345 Lisp_Object coding_system;
2347 coding_system = Vlocale_coding_system;
2348 if (NILP (coding_system))
2349 coding_system = Qcompound_text;
2350 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2351 text.encoding = (stringp ? XA_STRING
2352 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2353 text.format = 8;
2354 text.nitems = bytes;
2356 if (NILP (f->icon_name))
2358 icon = text;
2360 else
2362 icon.value = x_encode_text (f->icon_name, coding_system,
2363 &bytes, &stringp);
2364 icon.encoding = (stringp ? XA_STRING
2365 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2366 icon.format = 8;
2367 icon.nitems = bytes;
2369 #ifdef USE_X_TOOLKIT
2370 XSetWMName (FRAME_X_DISPLAY (f),
2371 XtWindow (f->output_data.x->widget), &text);
2372 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2373 &icon);
2374 #else /* not USE_X_TOOLKIT */
2375 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2376 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2377 #endif /* not USE_X_TOOLKIT */
2378 if (!NILP (f->icon_name)
2379 && icon.value != XSTRING (f->icon_name)->data)
2380 xfree (icon.value);
2381 if (text.value != XSTRING (name)->data)
2382 xfree (text.value);
2384 #else /* not HAVE_X11R4 */
2385 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2386 XSTRING (name)->data);
2387 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2388 XSTRING (name)->data);
2389 #endif /* not HAVE_X11R4 */
2390 UNBLOCK_INPUT;
2394 void
2395 x_set_autoraise (f, arg, oldval)
2396 struct frame *f;
2397 Lisp_Object arg, oldval;
2399 f->auto_raise = !EQ (Qnil, arg);
2402 void
2403 x_set_autolower (f, arg, oldval)
2404 struct frame *f;
2405 Lisp_Object arg, oldval;
2407 f->auto_lower = !EQ (Qnil, arg);
2410 void
2411 x_set_unsplittable (f, arg, oldval)
2412 struct frame *f;
2413 Lisp_Object arg, oldval;
2415 f->no_split = !NILP (arg);
2418 void
2419 x_set_vertical_scroll_bars (f, arg, oldval)
2420 struct frame *f;
2421 Lisp_Object arg, oldval;
2423 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2424 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2425 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2426 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2428 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2429 = (NILP (arg)
2430 ? vertical_scroll_bar_none
2431 : EQ (Qright, arg)
2432 ? vertical_scroll_bar_right
2433 : vertical_scroll_bar_left);
2435 /* We set this parameter before creating the X window for the
2436 frame, so we can get the geometry right from the start.
2437 However, if the window hasn't been created yet, we shouldn't
2438 call x_set_window_size. */
2439 if (FRAME_X_WINDOW (f))
2440 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2441 do_pending_window_change (0);
2445 void
2446 x_set_scroll_bar_width (f, arg, oldval)
2447 struct frame *f;
2448 Lisp_Object arg, oldval;
2450 int wid = FONT_WIDTH (f->output_data.x->font);
2452 if (NILP (arg))
2454 #ifdef USE_TOOLKIT_SCROLL_BARS
2455 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2456 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2457 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2458 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2459 #else
2460 /* Make the actual width at least 14 pixels and a multiple of a
2461 character width. */
2462 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2464 /* Use all of that space (aside from required margins) for the
2465 scroll bar. */
2466 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2467 #endif
2469 if (FRAME_X_WINDOW (f))
2470 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2471 do_pending_window_change (0);
2473 else if (INTEGERP (arg) && XINT (arg) > 0
2474 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2476 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2477 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2479 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2480 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2481 if (FRAME_X_WINDOW (f))
2482 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2485 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2486 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2487 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2492 /* Subroutines of creating an X frame. */
2494 /* Make sure that Vx_resource_name is set to a reasonable value.
2495 Fix it up, or set it to `emacs' if it is too hopeless. */
2497 static void
2498 validate_x_resource_name ()
2500 int len = 0;
2501 /* Number of valid characters in the resource name. */
2502 int good_count = 0;
2503 /* Number of invalid characters in the resource name. */
2504 int bad_count = 0;
2505 Lisp_Object new;
2506 int i;
2508 if (!STRINGP (Vx_resource_class))
2509 Vx_resource_class = build_string (EMACS_CLASS);
2511 if (STRINGP (Vx_resource_name))
2513 unsigned char *p = XSTRING (Vx_resource_name)->data;
2514 int i;
2516 len = STRING_BYTES (XSTRING (Vx_resource_name));
2518 /* Only letters, digits, - and _ are valid in resource names.
2519 Count the valid characters and count the invalid ones. */
2520 for (i = 0; i < len; i++)
2522 int c = p[i];
2523 if (! ((c >= 'a' && c <= 'z')
2524 || (c >= 'A' && c <= 'Z')
2525 || (c >= '0' && c <= '9')
2526 || c == '-' || c == '_'))
2527 bad_count++;
2528 else
2529 good_count++;
2532 else
2533 /* Not a string => completely invalid. */
2534 bad_count = 5, good_count = 0;
2536 /* If name is valid already, return. */
2537 if (bad_count == 0)
2538 return;
2540 /* If name is entirely invalid, or nearly so, use `emacs'. */
2541 if (good_count == 0
2542 || (good_count == 1 && bad_count > 0))
2544 Vx_resource_name = build_string ("emacs");
2545 return;
2548 /* Name is partly valid. Copy it and replace the invalid characters
2549 with underscores. */
2551 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2553 for (i = 0; i < len; i++)
2555 int c = XSTRING (new)->data[i];
2556 if (! ((c >= 'a' && c <= 'z')
2557 || (c >= 'A' && c <= 'Z')
2558 || (c >= '0' && c <= '9')
2559 || c == '-' || c == '_'))
2560 XSTRING (new)->data[i] = '_';
2565 extern char *x_get_string_resource ();
2567 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2568 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2569 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2570 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2571 the name specified by the `-name' or `-rn' command-line arguments.\n\
2573 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2574 class, respectively. You must specify both of them or neither.\n\
2575 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2576 and the class is `Emacs.CLASS.SUBCLASS'.")
2577 (attribute, class, component, subclass)
2578 Lisp_Object attribute, class, component, subclass;
2580 register char *value;
2581 char *name_key;
2582 char *class_key;
2584 check_x ();
2586 CHECK_STRING (attribute, 0);
2587 CHECK_STRING (class, 0);
2589 if (!NILP (component))
2590 CHECK_STRING (component, 1);
2591 if (!NILP (subclass))
2592 CHECK_STRING (subclass, 2);
2593 if (NILP (component) != NILP (subclass))
2594 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2596 validate_x_resource_name ();
2598 /* Allocate space for the components, the dots which separate them,
2599 and the final '\0'. Make them big enough for the worst case. */
2600 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2601 + (STRINGP (component)
2602 ? STRING_BYTES (XSTRING (component)) : 0)
2603 + STRING_BYTES (XSTRING (attribute))
2604 + 3);
2606 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2607 + STRING_BYTES (XSTRING (class))
2608 + (STRINGP (subclass)
2609 ? STRING_BYTES (XSTRING (subclass)) : 0)
2610 + 3);
2612 /* Start with emacs.FRAMENAME for the name (the specific one)
2613 and with `Emacs' for the class key (the general one). */
2614 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2615 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2617 strcat (class_key, ".");
2618 strcat (class_key, XSTRING (class)->data);
2620 if (!NILP (component))
2622 strcat (class_key, ".");
2623 strcat (class_key, XSTRING (subclass)->data);
2625 strcat (name_key, ".");
2626 strcat (name_key, XSTRING (component)->data);
2629 strcat (name_key, ".");
2630 strcat (name_key, XSTRING (attribute)->data);
2632 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2633 name_key, class_key);
2635 if (value != (char *) 0)
2636 return build_string (value);
2637 else
2638 return Qnil;
2641 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2643 Lisp_Object
2644 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2645 struct x_display_info *dpyinfo;
2646 Lisp_Object attribute, class, component, subclass;
2648 register char *value;
2649 char *name_key;
2650 char *class_key;
2652 CHECK_STRING (attribute, 0);
2653 CHECK_STRING (class, 0);
2655 if (!NILP (component))
2656 CHECK_STRING (component, 1);
2657 if (!NILP (subclass))
2658 CHECK_STRING (subclass, 2);
2659 if (NILP (component) != NILP (subclass))
2660 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2662 validate_x_resource_name ();
2664 /* Allocate space for the components, the dots which separate them,
2665 and the final '\0'. Make them big enough for the worst case. */
2666 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2667 + (STRINGP (component)
2668 ? STRING_BYTES (XSTRING (component)) : 0)
2669 + STRING_BYTES (XSTRING (attribute))
2670 + 3);
2672 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2673 + STRING_BYTES (XSTRING (class))
2674 + (STRINGP (subclass)
2675 ? STRING_BYTES (XSTRING (subclass)) : 0)
2676 + 3);
2678 /* Start with emacs.FRAMENAME for the name (the specific one)
2679 and with `Emacs' for the class key (the general one). */
2680 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2681 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2683 strcat (class_key, ".");
2684 strcat (class_key, XSTRING (class)->data);
2686 if (!NILP (component))
2688 strcat (class_key, ".");
2689 strcat (class_key, XSTRING (subclass)->data);
2691 strcat (name_key, ".");
2692 strcat (name_key, XSTRING (component)->data);
2695 strcat (name_key, ".");
2696 strcat (name_key, XSTRING (attribute)->data);
2698 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2700 if (value != (char *) 0)
2701 return build_string (value);
2702 else
2703 return Qnil;
2706 /* Used when C code wants a resource value. */
2708 char *
2709 x_get_resource_string (attribute, class)
2710 char *attribute, *class;
2712 char *name_key;
2713 char *class_key;
2714 struct frame *sf = SELECTED_FRAME ();
2716 /* Allocate space for the components, the dots which separate them,
2717 and the final '\0'. */
2718 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2719 + strlen (attribute) + 2);
2720 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2721 + strlen (class) + 2);
2723 sprintf (name_key, "%s.%s",
2724 XSTRING (Vinvocation_name)->data,
2725 attribute);
2726 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2728 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2729 name_key, class_key);
2732 /* Types we might convert a resource string into. */
2733 enum resource_types
2735 RES_TYPE_NUMBER,
2736 RES_TYPE_FLOAT,
2737 RES_TYPE_BOOLEAN,
2738 RES_TYPE_STRING,
2739 RES_TYPE_SYMBOL
2742 /* Return the value of parameter PARAM.
2744 First search ALIST, then Vdefault_frame_alist, then the X defaults
2745 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2747 Convert the resource to the type specified by desired_type.
2749 If no default is specified, return Qunbound. If you call
2750 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2751 and don't let it get stored in any Lisp-visible variables! */
2753 static Lisp_Object
2754 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2755 struct x_display_info *dpyinfo;
2756 Lisp_Object alist, param;
2757 char *attribute;
2758 char *class;
2759 enum resource_types type;
2761 register Lisp_Object tem;
2763 tem = Fassq (param, alist);
2764 if (EQ (tem, Qnil))
2765 tem = Fassq (param, Vdefault_frame_alist);
2766 if (EQ (tem, Qnil))
2769 if (attribute)
2771 tem = display_x_get_resource (dpyinfo,
2772 build_string (attribute),
2773 build_string (class),
2774 Qnil, Qnil);
2776 if (NILP (tem))
2777 return Qunbound;
2779 switch (type)
2781 case RES_TYPE_NUMBER:
2782 return make_number (atoi (XSTRING (tem)->data));
2784 case RES_TYPE_FLOAT:
2785 return make_float (atof (XSTRING (tem)->data));
2787 case RES_TYPE_BOOLEAN:
2788 tem = Fdowncase (tem);
2789 if (!strcmp (XSTRING (tem)->data, "on")
2790 || !strcmp (XSTRING (tem)->data, "true"))
2791 return Qt;
2792 else
2793 return Qnil;
2795 case RES_TYPE_STRING:
2796 return tem;
2798 case RES_TYPE_SYMBOL:
2799 /* As a special case, we map the values `true' and `on'
2800 to Qt, and `false' and `off' to Qnil. */
2802 Lisp_Object lower;
2803 lower = Fdowncase (tem);
2804 if (!strcmp (XSTRING (lower)->data, "on")
2805 || !strcmp (XSTRING (lower)->data, "true"))
2806 return Qt;
2807 else if (!strcmp (XSTRING (lower)->data, "off")
2808 || !strcmp (XSTRING (lower)->data, "false"))
2809 return Qnil;
2810 else
2811 return Fintern (tem, Qnil);
2814 default:
2815 abort ();
2818 else
2819 return Qunbound;
2821 return Fcdr (tem);
2824 /* Like x_get_arg, but also record the value in f->param_alist. */
2826 static Lisp_Object
2827 x_get_and_record_arg (f, alist, param, attribute, class, type)
2828 struct frame *f;
2829 Lisp_Object alist, param;
2830 char *attribute;
2831 char *class;
2832 enum resource_types type;
2834 Lisp_Object value;
2836 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2837 attribute, class, type);
2838 if (! NILP (value))
2839 store_frame_param (f, param, value);
2841 return value;
2844 /* Record in frame F the specified or default value according to ALIST
2845 of the parameter named PROP (a Lisp symbol).
2846 If no value is specified for PROP, look for an X default for XPROP
2847 on the frame named NAME.
2848 If that is not found either, use the value DEFLT. */
2850 static Lisp_Object
2851 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2852 struct frame *f;
2853 Lisp_Object alist;
2854 Lisp_Object prop;
2855 Lisp_Object deflt;
2856 char *xprop;
2857 char *xclass;
2858 enum resource_types type;
2860 Lisp_Object tem;
2862 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2863 if (EQ (tem, Qunbound))
2864 tem = deflt;
2865 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2866 return tem;
2870 /* Record in frame F the specified or default value according to ALIST
2871 of the parameter named PROP (a Lisp symbol). If no value is
2872 specified for PROP, look for an X default for XPROP on the frame
2873 named NAME. If that is not found either, use the value DEFLT. */
2875 static Lisp_Object
2876 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2877 foreground_p)
2878 struct frame *f;
2879 Lisp_Object alist;
2880 Lisp_Object prop;
2881 char *xprop;
2882 char *xclass;
2883 int foreground_p;
2885 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2886 Lisp_Object tem;
2888 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2889 if (EQ (tem, Qunbound))
2891 #ifdef USE_TOOLKIT_SCROLL_BARS
2893 /* See if an X resource for the scroll bar color has been
2894 specified. */
2895 tem = display_x_get_resource (dpyinfo,
2896 build_string (foreground_p
2897 ? "foreground"
2898 : "background"),
2899 build_string (""),
2900 build_string ("verticalScrollBar"),
2901 build_string (""));
2902 if (!STRINGP (tem))
2904 /* If nothing has been specified, scroll bars will use a
2905 toolkit-dependent default. Because these defaults are
2906 difficult to get at without actually creating a scroll
2907 bar, use nil to indicate that no color has been
2908 specified. */
2909 tem = Qnil;
2912 #else /* not USE_TOOLKIT_SCROLL_BARS */
2914 tem = Qnil;
2916 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2919 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2920 return tem;
2925 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2926 "Parse an X-style geometry string STRING.\n\
2927 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2928 The properties returned may include `top', `left', `height', and `width'.\n\
2929 The value of `left' or `top' may be an integer,\n\
2930 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2931 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2932 (string)
2933 Lisp_Object string;
2935 int geometry, x, y;
2936 unsigned int width, height;
2937 Lisp_Object result;
2939 CHECK_STRING (string, 0);
2941 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2942 &x, &y, &width, &height);
2944 #if 0
2945 if (!!(geometry & XValue) != !!(geometry & YValue))
2946 error ("Must specify both x and y position, or neither");
2947 #endif
2949 result = Qnil;
2950 if (geometry & XValue)
2952 Lisp_Object element;
2954 if (x >= 0 && (geometry & XNegative))
2955 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2956 else if (x < 0 && ! (geometry & XNegative))
2957 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2958 else
2959 element = Fcons (Qleft, make_number (x));
2960 result = Fcons (element, result);
2963 if (geometry & YValue)
2965 Lisp_Object element;
2967 if (y >= 0 && (geometry & YNegative))
2968 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2969 else if (y < 0 && ! (geometry & YNegative))
2970 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2971 else
2972 element = Fcons (Qtop, make_number (y));
2973 result = Fcons (element, result);
2976 if (geometry & WidthValue)
2977 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2978 if (geometry & HeightValue)
2979 result = Fcons (Fcons (Qheight, make_number (height)), result);
2981 return result;
2984 /* Calculate the desired size and position of this window,
2985 and return the flags saying which aspects were specified.
2987 This function does not make the coordinates positive. */
2989 #define DEFAULT_ROWS 40
2990 #define DEFAULT_COLS 80
2992 static int
2993 x_figure_window_size (f, parms)
2994 struct frame *f;
2995 Lisp_Object parms;
2997 register Lisp_Object tem0, tem1, tem2;
2998 long window_prompting = 0;
2999 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3001 /* Default values if we fall through.
3002 Actually, if that happens we should get
3003 window manager prompting. */
3004 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3005 f->height = DEFAULT_ROWS;
3006 /* Window managers expect that if program-specified
3007 positions are not (0,0), they're intentional, not defaults. */
3008 f->output_data.x->top_pos = 0;
3009 f->output_data.x->left_pos = 0;
3011 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3012 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3013 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3014 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3016 if (!EQ (tem0, Qunbound))
3018 CHECK_NUMBER (tem0, 0);
3019 f->height = XINT (tem0);
3021 if (!EQ (tem1, Qunbound))
3023 CHECK_NUMBER (tem1, 0);
3024 SET_FRAME_WIDTH (f, XINT (tem1));
3026 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3027 window_prompting |= USSize;
3028 else
3029 window_prompting |= PSize;
3032 f->output_data.x->vertical_scroll_bar_extra
3033 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3035 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3036 f->output_data.x->flags_areas_extra
3037 = FRAME_FLAGS_AREA_WIDTH (f);
3038 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3039 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3041 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3042 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3043 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3044 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3046 if (EQ (tem0, Qminus))
3048 f->output_data.x->top_pos = 0;
3049 window_prompting |= YNegative;
3051 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3052 && CONSP (XCDR (tem0))
3053 && INTEGERP (XCAR (XCDR (tem0))))
3055 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3056 window_prompting |= YNegative;
3058 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3059 && CONSP (XCDR (tem0))
3060 && INTEGERP (XCAR (XCDR (tem0))))
3062 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3064 else if (EQ (tem0, Qunbound))
3065 f->output_data.x->top_pos = 0;
3066 else
3068 CHECK_NUMBER (tem0, 0);
3069 f->output_data.x->top_pos = XINT (tem0);
3070 if (f->output_data.x->top_pos < 0)
3071 window_prompting |= YNegative;
3074 if (EQ (tem1, Qminus))
3076 f->output_data.x->left_pos = 0;
3077 window_prompting |= XNegative;
3079 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3080 && CONSP (XCDR (tem1))
3081 && INTEGERP (XCAR (XCDR (tem1))))
3083 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3084 window_prompting |= XNegative;
3086 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3087 && CONSP (XCDR (tem1))
3088 && INTEGERP (XCAR (XCDR (tem1))))
3090 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3092 else if (EQ (tem1, Qunbound))
3093 f->output_data.x->left_pos = 0;
3094 else
3096 CHECK_NUMBER (tem1, 0);
3097 f->output_data.x->left_pos = XINT (tem1);
3098 if (f->output_data.x->left_pos < 0)
3099 window_prompting |= XNegative;
3102 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3103 window_prompting |= USPosition;
3104 else
3105 window_prompting |= PPosition;
3108 return window_prompting;
3111 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3113 Status
3114 XSetWMProtocols (dpy, w, protocols, count)
3115 Display *dpy;
3116 Window w;
3117 Atom *protocols;
3118 int count;
3120 Atom prop;
3121 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3122 if (prop == None) return False;
3123 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3124 (unsigned char *) protocols, count);
3125 return True;
3127 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3129 #ifdef USE_X_TOOLKIT
3131 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3132 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3133 already be present because of the toolkit (Motif adds some of them,
3134 for example, but Xt doesn't). */
3136 static void
3137 hack_wm_protocols (f, widget)
3138 FRAME_PTR f;
3139 Widget widget;
3141 Display *dpy = XtDisplay (widget);
3142 Window w = XtWindow (widget);
3143 int need_delete = 1;
3144 int need_focus = 1;
3145 int need_save = 1;
3147 BLOCK_INPUT;
3149 Atom type, *atoms = 0;
3150 int format = 0;
3151 unsigned long nitems = 0;
3152 unsigned long bytes_after;
3154 if ((XGetWindowProperty (dpy, w,
3155 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3156 (long)0, (long)100, False, XA_ATOM,
3157 &type, &format, &nitems, &bytes_after,
3158 (unsigned char **) &atoms)
3159 == Success)
3160 && format == 32 && type == XA_ATOM)
3161 while (nitems > 0)
3163 nitems--;
3164 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3165 need_delete = 0;
3166 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3167 need_focus = 0;
3168 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3169 need_save = 0;
3171 if (atoms) XFree ((char *) atoms);
3174 Atom props [10];
3175 int count = 0;
3176 if (need_delete)
3177 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3178 if (need_focus)
3179 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3180 if (need_save)
3181 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3182 if (count)
3183 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3184 XA_ATOM, 32, PropModeAppend,
3185 (unsigned char *) props, count);
3187 UNBLOCK_INPUT;
3189 #endif
3193 /* Support routines for XIC (X Input Context). */
3195 #ifdef HAVE_X_I18N
3197 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3198 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3201 /* Supported XIM styles, ordered by preferenc. */
3203 static XIMStyle supported_xim_styles[] =
3205 XIMPreeditPosition | XIMStatusArea,
3206 XIMPreeditPosition | XIMStatusNothing,
3207 XIMPreeditPosition | XIMStatusNone,
3208 XIMPreeditNothing | XIMStatusArea,
3209 XIMPreeditNothing | XIMStatusNothing,
3210 XIMPreeditNothing | XIMStatusNone,
3211 XIMPreeditNone | XIMStatusArea,
3212 XIMPreeditNone | XIMStatusNothing,
3213 XIMPreeditNone | XIMStatusNone,
3218 /* Create an X fontset on frame F with base font name
3219 BASE_FONTNAME.. */
3221 static XFontSet
3222 xic_create_xfontset (f, base_fontname)
3223 struct frame *f;
3224 char *base_fontname;
3226 XFontSet xfs;
3227 char **missing_list;
3228 int missing_count;
3229 char *def_string;
3231 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3232 base_fontname, &missing_list,
3233 &missing_count, &def_string);
3234 if (missing_list)
3235 XFreeStringList (missing_list);
3237 /* No need to free def_string. */
3238 return xfs;
3242 /* Value is the best input style, given user preferences USER (already
3243 checked to be supported by Emacs), and styles supported by the
3244 input method XIM. */
3246 static XIMStyle
3247 best_xim_style (user, xim)
3248 XIMStyles *user;
3249 XIMStyles *xim;
3251 int i, j;
3253 for (i = 0; i < user->count_styles; ++i)
3254 for (j = 0; j < xim->count_styles; ++j)
3255 if (user->supported_styles[i] == xim->supported_styles[j])
3256 return user->supported_styles[i];
3258 /* Return the default style. */
3259 return XIMPreeditNothing | XIMStatusNothing;
3262 /* Create XIC for frame F. */
3264 void
3265 create_frame_xic (f)
3266 struct frame *f;
3268 XIM xim;
3269 XIC xic = NULL;
3270 XFontSet xfs = NULL;
3271 static XIMStyle xic_style;
3273 if (FRAME_XIC (f))
3274 return;
3276 xim = FRAME_X_XIM (f);
3277 if (xim)
3279 XRectangle s_area;
3280 XPoint spot;
3281 XVaNestedList preedit_attr;
3282 XVaNestedList status_attr;
3283 char *base_fontname;
3284 int fontset;
3286 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3287 spot.x = 0; spot.y = 1;
3288 /* Create X fontset. */
3289 fontset = FRAME_FONTSET (f);
3290 if (fontset < 0)
3291 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3292 else
3294 /* Determine the base fontname from the ASCII font name of
3295 FONTSET. */
3296 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3297 char *p = ascii_font;
3298 int i;
3300 for (i = 0; *p; p++)
3301 if (*p == '-') i++;
3302 if (i != 14)
3303 /* As the font name doesn't conform to XLFD, we can't
3304 modify it to get a suitable base fontname for the
3305 frame. */
3306 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3307 else
3309 int len = strlen (ascii_font) + 1;
3310 char *p1 = NULL;
3312 for (i = 0, p = ascii_font; i < 8; p++)
3314 if (*p == '-')
3316 i++;
3317 if (i == 3)
3318 p1 = p + 1;
3321 base_fontname = (char *) alloca (len);
3322 bzero (base_fontname, len);
3323 strcpy (base_fontname, "-*-*-");
3324 bcopy (p1, base_fontname + 5, p - p1);
3325 strcat (base_fontname, "*-*-*-*-*-*-*");
3328 xfs = xic_create_xfontset (f, base_fontname);
3330 /* Determine XIC style. */
3331 if (xic_style == 0)
3333 XIMStyles supported_list;
3334 supported_list.count_styles = (sizeof supported_xim_styles
3335 / sizeof supported_xim_styles[0]);
3336 supported_list.supported_styles = supported_xim_styles;
3337 xic_style = best_xim_style (&supported_list,
3338 FRAME_X_XIM_STYLES (f));
3341 preedit_attr = XVaCreateNestedList (0,
3342 XNFontSet, xfs,
3343 XNForeground,
3344 FRAME_FOREGROUND_PIXEL (f),
3345 XNBackground,
3346 FRAME_BACKGROUND_PIXEL (f),
3347 (xic_style & XIMPreeditPosition
3348 ? XNSpotLocation
3349 : NULL),
3350 &spot,
3351 NULL);
3352 status_attr = XVaCreateNestedList (0,
3353 XNArea,
3354 &s_area,
3355 XNFontSet,
3356 xfs,
3357 XNForeground,
3358 FRAME_FOREGROUND_PIXEL (f),
3359 XNBackground,
3360 FRAME_BACKGROUND_PIXEL (f),
3361 NULL);
3363 xic = XCreateIC (xim,
3364 XNInputStyle, xic_style,
3365 XNClientWindow, FRAME_X_WINDOW(f),
3366 XNFocusWindow, FRAME_X_WINDOW(f),
3367 XNStatusAttributes, status_attr,
3368 XNPreeditAttributes, preedit_attr,
3369 NULL);
3370 XFree (preedit_attr);
3371 XFree (status_attr);
3374 FRAME_XIC (f) = xic;
3375 FRAME_XIC_STYLE (f) = xic_style;
3376 FRAME_XIC_FONTSET (f) = xfs;
3380 /* Destroy XIC and free XIC fontset of frame F, if any. */
3382 void
3383 free_frame_xic (f)
3384 struct frame *f;
3386 if (FRAME_XIC (f) == NULL)
3387 return;
3389 XDestroyIC (FRAME_XIC (f));
3390 if (FRAME_XIC_FONTSET (f))
3391 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3393 FRAME_XIC (f) = NULL;
3394 FRAME_XIC_FONTSET (f) = NULL;
3398 /* Place preedit area for XIC of window W's frame to specified
3399 pixel position X/Y. X and Y are relative to window W. */
3401 void
3402 xic_set_preeditarea (w, x, y)
3403 struct window *w;
3404 int x, y;
3406 struct frame *f = XFRAME (w->frame);
3407 XVaNestedList attr;
3408 XPoint spot;
3410 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3411 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3412 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3413 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3414 XFree (attr);
3418 /* Place status area for XIC in bottom right corner of frame F.. */
3420 void
3421 xic_set_statusarea (f)
3422 struct frame *f;
3424 XIC xic = FRAME_XIC (f);
3425 XVaNestedList attr;
3426 XRectangle area;
3427 XRectangle *needed;
3429 /* Negotiate geometry of status area. If input method has existing
3430 status area, use its current size. */
3431 area.x = area.y = area.width = area.height = 0;
3432 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3433 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3434 XFree (attr);
3436 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3437 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3438 XFree (attr);
3440 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3442 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3443 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3444 XFree (attr);
3447 area.width = needed->width;
3448 area.height = needed->height;
3449 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3450 area.y = (PIXEL_HEIGHT (f) - area.height
3451 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3452 XFree (needed);
3454 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3455 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3456 XFree (attr);
3460 /* Set X fontset for XIC of frame F, using base font name
3461 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3463 void
3464 xic_set_xfontset (f, base_fontname)
3465 struct frame *f;
3466 char *base_fontname;
3468 XVaNestedList attr;
3469 XFontSet xfs;
3471 xfs = xic_create_xfontset (f, base_fontname);
3473 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3474 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3475 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3476 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3477 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3478 XFree (attr);
3480 if (FRAME_XIC_FONTSET (f))
3481 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3482 FRAME_XIC_FONTSET (f) = xfs;
3485 #endif /* HAVE_X_I18N */
3489 #ifdef USE_X_TOOLKIT
3491 /* Create and set up the X widget for frame F. */
3493 static void
3494 x_window (f, window_prompting, minibuffer_only)
3495 struct frame *f;
3496 long window_prompting;
3497 int minibuffer_only;
3499 XClassHint class_hints;
3500 XSetWindowAttributes attributes;
3501 unsigned long attribute_mask;
3502 Widget shell_widget;
3503 Widget pane_widget;
3504 Widget frame_widget;
3505 Arg al [25];
3506 int ac;
3508 BLOCK_INPUT;
3510 /* Use the resource name as the top-level widget name
3511 for looking up resources. Make a non-Lisp copy
3512 for the window manager, so GC relocation won't bother it.
3514 Elsewhere we specify the window name for the window manager. */
3517 char *str = (char *) XSTRING (Vx_resource_name)->data;
3518 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3519 strcpy (f->namebuf, str);
3522 ac = 0;
3523 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3524 XtSetArg (al[ac], XtNinput, 1); ac++;
3525 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3526 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3527 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3528 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3529 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3530 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3531 applicationShellWidgetClass,
3532 FRAME_X_DISPLAY (f), al, ac);
3534 f->output_data.x->widget = shell_widget;
3535 /* maybe_set_screen_title_format (shell_widget); */
3537 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3538 (widget_value *) NULL,
3539 shell_widget, False,
3540 (lw_callback) NULL,
3541 (lw_callback) NULL,
3542 (lw_callback) NULL,
3543 (lw_callback) NULL);
3545 ac = 0;
3546 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3547 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3548 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3549 XtSetValues (pane_widget, al, ac);
3550 f->output_data.x->column_widget = pane_widget;
3552 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3553 the emacs screen when changing menubar. This reduces flickering. */
3555 ac = 0;
3556 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3557 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3558 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3559 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3560 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3561 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3562 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3563 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3564 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3565 al, ac);
3567 f->output_data.x->edit_widget = frame_widget;
3569 XtManageChild (frame_widget);
3571 /* Do some needed geometry management. */
3573 int len;
3574 char *tem, shell_position[32];
3575 Arg al[2];
3576 int ac = 0;
3577 int extra_borders = 0;
3578 int menubar_size
3579 = (f->output_data.x->menubar_widget
3580 ? (f->output_data.x->menubar_widget->core.height
3581 + f->output_data.x->menubar_widget->core.border_width)
3582 : 0);
3584 #if 0 /* Experimentally, we now get the right results
3585 for -geometry -0-0 without this. 24 Aug 96, rms. */
3586 if (FRAME_EXTERNAL_MENU_BAR (f))
3588 Dimension ibw = 0;
3589 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3590 menubar_size += ibw;
3592 #endif
3594 f->output_data.x->menubar_height = menubar_size;
3596 #ifndef USE_LUCID
3597 /* Motif seems to need this amount added to the sizes
3598 specified for the shell widget. The Athena/Lucid widgets don't.
3599 Both conclusions reached experimentally. -- rms. */
3600 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3601 &extra_borders, NULL);
3602 extra_borders *= 2;
3603 #endif
3605 /* Convert our geometry parameters into a geometry string
3606 and specify it.
3607 Note that we do not specify here whether the position
3608 is a user-specified or program-specified one.
3609 We pass that information later, in x_wm_set_size_hints. */
3611 int left = f->output_data.x->left_pos;
3612 int xneg = window_prompting & XNegative;
3613 int top = f->output_data.x->top_pos;
3614 int yneg = window_prompting & YNegative;
3615 if (xneg)
3616 left = -left;
3617 if (yneg)
3618 top = -top;
3620 if (window_prompting & USPosition)
3621 sprintf (shell_position, "=%dx%d%c%d%c%d",
3622 PIXEL_WIDTH (f) + extra_borders,
3623 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3624 (xneg ? '-' : '+'), left,
3625 (yneg ? '-' : '+'), top);
3626 else
3627 sprintf (shell_position, "=%dx%d",
3628 PIXEL_WIDTH (f) + extra_borders,
3629 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3632 len = strlen (shell_position) + 1;
3633 /* We don't free this because we don't know whether
3634 it is safe to free it while the frame exists.
3635 It isn't worth the trouble of arranging to free it
3636 when the frame is deleted. */
3637 tem = (char *) xmalloc (len);
3638 strncpy (tem, shell_position, len);
3639 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3640 XtSetValues (shell_widget, al, ac);
3643 XtManageChild (pane_widget);
3644 XtRealizeWidget (shell_widget);
3646 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3648 validate_x_resource_name ();
3650 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3651 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3652 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3654 #ifdef HAVE_X_I18N
3655 FRAME_XIC (f) = NULL;
3656 #ifdef USE_XIM
3657 create_frame_xic (f);
3658 #endif
3659 #endif
3661 f->output_data.x->wm_hints.input = True;
3662 f->output_data.x->wm_hints.flags |= InputHint;
3663 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3664 &f->output_data.x->wm_hints);
3666 hack_wm_protocols (f, shell_widget);
3668 #ifdef HACK_EDITRES
3669 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3670 #endif
3672 /* Do a stupid property change to force the server to generate a
3673 PropertyNotify event so that the event_stream server timestamp will
3674 be initialized to something relevant to the time we created the window.
3676 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3677 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3678 XA_ATOM, 32, PropModeAppend,
3679 (unsigned char*) NULL, 0);
3681 /* Make all the standard events reach the Emacs frame. */
3682 attributes.event_mask = STANDARD_EVENT_SET;
3684 #ifdef HAVE_X_I18N
3685 if (FRAME_XIC (f))
3687 /* XIM server might require some X events. */
3688 unsigned long fevent = NoEventMask;
3689 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3690 attributes.event_mask |= fevent;
3692 #endif /* HAVE_X_I18N */
3694 attribute_mask = CWEventMask;
3695 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3696 attribute_mask, &attributes);
3698 XtMapWidget (frame_widget);
3700 /* x_set_name normally ignores requests to set the name if the
3701 requested name is the same as the current name. This is the one
3702 place where that assumption isn't correct; f->name is set, but
3703 the X server hasn't been told. */
3705 Lisp_Object name;
3706 int explicit = f->explicit_name;
3708 f->explicit_name = 0;
3709 name = f->name;
3710 f->name = Qnil;
3711 x_set_name (f, name, explicit);
3714 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3715 f->output_data.x->text_cursor);
3717 UNBLOCK_INPUT;
3719 /* This is a no-op, except under Motif. Make sure main areas are
3720 set to something reasonable, in case we get an error later. */
3721 lw_set_main_areas (pane_widget, 0, frame_widget);
3724 #else /* not USE_X_TOOLKIT */
3726 /* Create and set up the X window for frame F. */
3728 void
3729 x_window (f)
3730 struct frame *f;
3733 XClassHint class_hints;
3734 XSetWindowAttributes attributes;
3735 unsigned long attribute_mask;
3737 attributes.background_pixel = f->output_data.x->background_pixel;
3738 attributes.border_pixel = f->output_data.x->border_pixel;
3739 attributes.bit_gravity = StaticGravity;
3740 attributes.backing_store = NotUseful;
3741 attributes.save_under = True;
3742 attributes.event_mask = STANDARD_EVENT_SET;
3743 attributes.colormap = FRAME_X_COLORMAP (f);
3744 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3745 | CWColormap);
3747 BLOCK_INPUT;
3748 FRAME_X_WINDOW (f)
3749 = XCreateWindow (FRAME_X_DISPLAY (f),
3750 f->output_data.x->parent_desc,
3751 f->output_data.x->left_pos,
3752 f->output_data.x->top_pos,
3753 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3754 f->output_data.x->border_width,
3755 CopyFromParent, /* depth */
3756 InputOutput, /* class */
3757 FRAME_X_VISUAL (f),
3758 attribute_mask, &attributes);
3760 #ifdef HAVE_X_I18N
3761 #ifdef USE_XIM
3762 create_frame_xic (f);
3763 if (FRAME_XIC (f))
3765 /* XIM server might require some X events. */
3766 unsigned long fevent = NoEventMask;
3767 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3768 attributes.event_mask |= fevent;
3769 attribute_mask = CWEventMask;
3770 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3771 attribute_mask, &attributes);
3773 #endif
3774 #endif /* HAVE_X_I18N */
3776 validate_x_resource_name ();
3778 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3779 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3780 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3782 /* The menubar is part of the ordinary display;
3783 it does not count in addition to the height of the window. */
3784 f->output_data.x->menubar_height = 0;
3786 /* This indicates that we use the "Passive Input" input model.
3787 Unless we do this, we don't get the Focus{In,Out} events that we
3788 need to draw the cursor correctly. Accursed bureaucrats.
3789 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3791 f->output_data.x->wm_hints.input = True;
3792 f->output_data.x->wm_hints.flags |= InputHint;
3793 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3794 &f->output_data.x->wm_hints);
3795 f->output_data.x->wm_hints.icon_pixmap = None;
3797 /* Request "save yourself" and "delete window" commands from wm. */
3799 Atom protocols[2];
3800 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3801 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3802 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3805 /* x_set_name normally ignores requests to set the name if the
3806 requested name is the same as the current name. This is the one
3807 place where that assumption isn't correct; f->name is set, but
3808 the X server hasn't been told. */
3810 Lisp_Object name;
3811 int explicit = f->explicit_name;
3813 f->explicit_name = 0;
3814 name = f->name;
3815 f->name = Qnil;
3816 x_set_name (f, name, explicit);
3819 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3820 f->output_data.x->text_cursor);
3822 UNBLOCK_INPUT;
3824 if (FRAME_X_WINDOW (f) == 0)
3825 error ("Unable to create window");
3828 #endif /* not USE_X_TOOLKIT */
3830 /* Handle the icon stuff for this window. Perhaps later we might
3831 want an x_set_icon_position which can be called interactively as
3832 well. */
3834 static void
3835 x_icon (f, parms)
3836 struct frame *f;
3837 Lisp_Object parms;
3839 Lisp_Object icon_x, icon_y;
3840 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3842 /* Set the position of the icon. Note that twm groups all
3843 icons in an icon window. */
3844 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3845 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3846 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3848 CHECK_NUMBER (icon_x, 0);
3849 CHECK_NUMBER (icon_y, 0);
3851 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3852 error ("Both left and top icon corners of icon must be specified");
3854 BLOCK_INPUT;
3856 if (! EQ (icon_x, Qunbound))
3857 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3859 /* Start up iconic or window? */
3860 x_wm_set_window_state
3861 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3862 Qicon)
3863 ? IconicState
3864 : NormalState));
3866 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3867 ? f->icon_name
3868 : f->name))->data);
3870 UNBLOCK_INPUT;
3873 /* Make the GCs needed for this window, setting the
3874 background, border and mouse colors; also create the
3875 mouse cursor and the gray border tile. */
3877 static char cursor_bits[] =
3879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3885 static void
3886 x_make_gc (f)
3887 struct frame *f;
3889 XGCValues gc_values;
3891 BLOCK_INPUT;
3893 /* Create the GCs of this frame.
3894 Note that many default values are used. */
3896 /* Normal video */
3897 gc_values.font = f->output_data.x->font->fid;
3898 gc_values.foreground = f->output_data.x->foreground_pixel;
3899 gc_values.background = f->output_data.x->background_pixel;
3900 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3901 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3902 FRAME_X_WINDOW (f),
3903 GCLineWidth | GCFont
3904 | GCForeground | GCBackground,
3905 &gc_values);
3907 /* Reverse video style. */
3908 gc_values.foreground = f->output_data.x->background_pixel;
3909 gc_values.background = f->output_data.x->foreground_pixel;
3910 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3911 FRAME_X_WINDOW (f),
3912 GCFont | GCForeground | GCBackground
3913 | GCLineWidth,
3914 &gc_values);
3916 /* Cursor has cursor-color background, background-color foreground. */
3917 gc_values.foreground = f->output_data.x->background_pixel;
3918 gc_values.background = f->output_data.x->cursor_pixel;
3919 gc_values.fill_style = FillOpaqueStippled;
3920 gc_values.stipple
3921 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3922 FRAME_X_DISPLAY_INFO (f)->root_window,
3923 cursor_bits, 16, 16);
3924 f->output_data.x->cursor_gc
3925 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3926 (GCFont | GCForeground | GCBackground
3927 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3928 &gc_values);
3930 /* Reliefs. */
3931 f->output_data.x->white_relief.gc = 0;
3932 f->output_data.x->black_relief.gc = 0;
3934 /* Create the gray border tile used when the pointer is not in
3935 the frame. Since this depends on the frame's pixel values,
3936 this must be done on a per-frame basis. */
3937 f->output_data.x->border_tile
3938 = (XCreatePixmapFromBitmapData
3939 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3940 gray_bits, gray_width, gray_height,
3941 f->output_data.x->foreground_pixel,
3942 f->output_data.x->background_pixel,
3943 DefaultDepth (FRAME_X_DISPLAY (f),
3944 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3946 UNBLOCK_INPUT;
3949 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3950 1, 1, 0,
3951 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3952 Returns an Emacs frame object.\n\
3953 ALIST is an alist of frame parameters.\n\
3954 If the parameters specify that the frame should not have a minibuffer,\n\
3955 and do not specify a specific minibuffer window to use,\n\
3956 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3957 be shared by the new frame.\n\
3959 This function is an internal primitive--use `make-frame' instead.")
3960 (parms)
3961 Lisp_Object parms;
3963 struct frame *f;
3964 Lisp_Object frame, tem;
3965 Lisp_Object name;
3966 int minibuffer_only = 0;
3967 long window_prompting = 0;
3968 int width, height;
3969 int count = specpdl_ptr - specpdl;
3970 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3971 Lisp_Object display;
3972 struct x_display_info *dpyinfo = NULL;
3973 Lisp_Object parent;
3974 struct kboard *kb;
3976 check_x ();
3978 /* Use this general default value to start with
3979 until we know if this frame has a specified name. */
3980 Vx_resource_name = Vinvocation_name;
3982 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3983 if (EQ (display, Qunbound))
3984 display = Qnil;
3985 dpyinfo = check_x_display_info (display);
3986 #ifdef MULTI_KBOARD
3987 kb = dpyinfo->kboard;
3988 #else
3989 kb = &the_only_kboard;
3990 #endif
3992 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3993 if (!STRINGP (name)
3994 && ! EQ (name, Qunbound)
3995 && ! NILP (name))
3996 error ("Invalid frame name--not a string or nil");
3998 if (STRINGP (name))
3999 Vx_resource_name = name;
4001 /* See if parent window is specified. */
4002 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4003 if (EQ (parent, Qunbound))
4004 parent = Qnil;
4005 if (! NILP (parent))
4006 CHECK_NUMBER (parent, 0);
4008 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4009 /* No need to protect DISPLAY because that's not used after passing
4010 it to make_frame_without_minibuffer. */
4011 frame = Qnil;
4012 GCPRO4 (parms, parent, name, frame);
4013 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4014 RES_TYPE_SYMBOL);
4015 if (EQ (tem, Qnone) || NILP (tem))
4016 f = make_frame_without_minibuffer (Qnil, kb, display);
4017 else if (EQ (tem, Qonly))
4019 f = make_minibuffer_frame ();
4020 minibuffer_only = 1;
4022 else if (WINDOWP (tem))
4023 f = make_frame_without_minibuffer (tem, kb, display);
4024 else
4025 f = make_frame (1);
4027 XSETFRAME (frame, f);
4029 /* Note that X Windows does support scroll bars. */
4030 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4032 f->output_method = output_x_window;
4033 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4034 bzero (f->output_data.x, sizeof (struct x_output));
4035 f->output_data.x->icon_bitmap = -1;
4036 f->output_data.x->fontset = -1;
4037 f->output_data.x->scroll_bar_foreground_pixel = -1;
4038 f->output_data.x->scroll_bar_background_pixel = -1;
4040 f->icon_name
4041 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4042 RES_TYPE_STRING);
4043 if (! STRINGP (f->icon_name))
4044 f->icon_name = Qnil;
4046 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4047 #ifdef MULTI_KBOARD
4048 FRAME_KBOARD (f) = kb;
4049 #endif
4051 /* These colors will be set anyway later, but it's important
4052 to get the color reference counts right, so initialize them! */
4054 Lisp_Object black;
4055 struct gcpro gcpro1;
4057 black = build_string ("black");
4058 GCPRO1 (black);
4059 f->output_data.x->foreground_pixel
4060 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4061 f->output_data.x->background_pixel
4062 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4063 f->output_data.x->cursor_pixel
4064 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4065 f->output_data.x->cursor_foreground_pixel
4066 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4067 f->output_data.x->border_pixel
4068 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4069 f->output_data.x->mouse_pixel
4070 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4071 UNGCPRO;
4074 /* Specify the parent under which to make this X window. */
4076 if (!NILP (parent))
4078 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4079 f->output_data.x->explicit_parent = 1;
4081 else
4083 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4084 f->output_data.x->explicit_parent = 0;
4087 /* Set the name; the functions to which we pass f expect the name to
4088 be set. */
4089 if (EQ (name, Qunbound) || NILP (name))
4091 f->name = build_string (dpyinfo->x_id_name);
4092 f->explicit_name = 0;
4094 else
4096 f->name = name;
4097 f->explicit_name = 1;
4098 /* use the frame's title when getting resources for this frame. */
4099 specbind (Qx_resource_name, name);
4102 /* Extract the window parameters from the supplied values
4103 that are needed to determine window geometry. */
4105 Lisp_Object font;
4107 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4109 BLOCK_INPUT;
4110 /* First, try whatever font the caller has specified. */
4111 if (STRINGP (font))
4113 tem = Fquery_fontset (font, Qnil);
4114 if (STRINGP (tem))
4115 font = x_new_fontset (f, XSTRING (tem)->data);
4116 else
4117 font = x_new_font (f, XSTRING (font)->data);
4120 /* Try out a font which we hope has bold and italic variations. */
4121 if (!STRINGP (font))
4122 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4123 if (!STRINGP (font))
4124 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4125 if (! STRINGP (font))
4126 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4127 if (! STRINGP (font))
4128 /* This was formerly the first thing tried, but it finds too many fonts
4129 and takes too long. */
4130 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4131 /* If those didn't work, look for something which will at least work. */
4132 if (! STRINGP (font))
4133 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4134 UNBLOCK_INPUT;
4135 if (! STRINGP (font))
4136 font = build_string ("fixed");
4138 x_default_parameter (f, parms, Qfont, font,
4139 "font", "Font", RES_TYPE_STRING);
4142 #ifdef USE_LUCID
4143 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4144 whereby it fails to get any font. */
4145 xlwmenu_default_font = f->output_data.x->font;
4146 #endif
4148 x_default_parameter (f, parms, Qborder_width, make_number (2),
4149 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4151 /* This defaults to 2 in order to match xterm. We recognize either
4152 internalBorderWidth or internalBorder (which is what xterm calls
4153 it). */
4154 if (NILP (Fassq (Qinternal_border_width, parms)))
4156 Lisp_Object value;
4158 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4159 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4160 if (! EQ (value, Qunbound))
4161 parms = Fcons (Fcons (Qinternal_border_width, value),
4162 parms);
4164 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4165 "internalBorderWidth", "internalBorderWidth",
4166 RES_TYPE_NUMBER);
4167 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4168 "verticalScrollBars", "ScrollBars",
4169 RES_TYPE_SYMBOL);
4171 /* Also do the stuff which must be set before the window exists. */
4172 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4173 "foreground", "Foreground", RES_TYPE_STRING);
4174 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4175 "background", "Background", RES_TYPE_STRING);
4176 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4177 "pointerColor", "Foreground", RES_TYPE_STRING);
4178 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4179 "cursorColor", "Foreground", RES_TYPE_STRING);
4180 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4181 "borderColor", "BorderColor", RES_TYPE_STRING);
4182 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4183 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4184 x_default_parameter (f, parms, Qline_spacing, Qnil,
4185 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4187 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4188 "scrollBarForeground",
4189 "ScrollBarForeground", 1);
4190 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4191 "scrollBarBackground",
4192 "ScrollBarBackground", 0);
4194 /* Init faces before x_default_parameter is called for scroll-bar
4195 parameters because that function calls x_set_scroll_bar_width,
4196 which calls change_frame_size, which calls Fset_window_buffer,
4197 which runs hooks, which call Fvertical_motion. At the end, we
4198 end up in init_iterator with a null face cache, which should not
4199 happen. */
4200 init_frame_faces (f);
4202 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4203 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4204 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4205 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4206 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4207 "bufferPredicate", "BufferPredicate",
4208 RES_TYPE_SYMBOL);
4209 x_default_parameter (f, parms, Qtitle, Qnil,
4210 "title", "Title", RES_TYPE_STRING);
4212 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4213 window_prompting = x_figure_window_size (f, parms);
4215 if (window_prompting & XNegative)
4217 if (window_prompting & YNegative)
4218 f->output_data.x->win_gravity = SouthEastGravity;
4219 else
4220 f->output_data.x->win_gravity = NorthEastGravity;
4222 else
4224 if (window_prompting & YNegative)
4225 f->output_data.x->win_gravity = SouthWestGravity;
4226 else
4227 f->output_data.x->win_gravity = NorthWestGravity;
4230 f->output_data.x->size_hint_flags = window_prompting;
4232 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4233 f->no_split = minibuffer_only || EQ (tem, Qt);
4235 /* Create the X widget or window. Add the tool-bar height to the
4236 initial frame height so that the user gets a text display area of
4237 the size he specified with -g or via .Xdefaults. Later changes
4238 of the tool-bar height don't change the frame size. This is done
4239 so that users can create tall Emacs frames without having to
4240 guess how tall the tool-bar will get. */
4241 f->height += FRAME_TOOL_BAR_LINES (f);
4243 #ifdef USE_X_TOOLKIT
4244 x_window (f, window_prompting, minibuffer_only);
4245 #else
4246 x_window (f);
4247 #endif
4249 x_icon (f, parms);
4250 x_make_gc (f);
4252 /* Now consider the frame official. */
4253 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4254 Vframe_list = Fcons (frame, Vframe_list);
4256 /* We need to do this after creating the X window, so that the
4257 icon-creation functions can say whose icon they're describing. */
4258 x_default_parameter (f, parms, Qicon_type, Qnil,
4259 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4261 x_default_parameter (f, parms, Qauto_raise, Qnil,
4262 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4263 x_default_parameter (f, parms, Qauto_lower, Qnil,
4264 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4265 x_default_parameter (f, parms, Qcursor_type, Qbox,
4266 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4267 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4268 "scrollBarWidth", "ScrollBarWidth",
4269 RES_TYPE_NUMBER);
4271 /* Dimensions, especially f->height, must be done via change_frame_size.
4272 Change will not be effected unless different from the current
4273 f->height. */
4274 width = f->width;
4275 height = f->height;
4276 f->height = 0;
4277 SET_FRAME_WIDTH (f, 0);
4278 change_frame_size (f, height, width, 1, 0, 0);
4280 /* Set up faces after all frame parameters are known. */
4281 call1 (Qface_set_after_frame_default, frame);
4283 #ifdef USE_X_TOOLKIT
4284 /* Create the menu bar. */
4285 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4287 /* If this signals an error, we haven't set size hints for the
4288 frame and we didn't make it visible. */
4289 initialize_frame_menubar (f);
4291 /* This is a no-op, except under Motif where it arranges the
4292 main window for the widgets on it. */
4293 lw_set_main_areas (f->output_data.x->column_widget,
4294 f->output_data.x->menubar_widget,
4295 f->output_data.x->edit_widget);
4297 #endif /* USE_X_TOOLKIT */
4299 /* Tell the server what size and position, etc, we want, and how
4300 badly we want them. This should be done after we have the menu
4301 bar so that its size can be taken into account. */
4302 BLOCK_INPUT;
4303 x_wm_set_size_hint (f, window_prompting, 0);
4304 UNBLOCK_INPUT;
4306 /* Make the window appear on the frame and enable display, unless
4307 the caller says not to. However, with explicit parent, Emacs
4308 cannot control visibility, so don't try. */
4309 if (! f->output_data.x->explicit_parent)
4311 Lisp_Object visibility;
4313 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4314 RES_TYPE_SYMBOL);
4315 if (EQ (visibility, Qunbound))
4316 visibility = Qt;
4318 if (EQ (visibility, Qicon))
4319 x_iconify_frame (f);
4320 else if (! NILP (visibility))
4321 x_make_frame_visible (f);
4322 else
4323 /* Must have been Qnil. */
4327 UNGCPRO;
4328 return unbind_to (count, frame);
4331 /* FRAME is used only to get a handle on the X display. We don't pass the
4332 display info directly because we're called from frame.c, which doesn't
4333 know about that structure. */
4335 Lisp_Object
4336 x_get_focus_frame (frame)
4337 struct frame *frame;
4339 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4340 Lisp_Object xfocus;
4341 if (! dpyinfo->x_focus_frame)
4342 return Qnil;
4344 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4345 return xfocus;
4349 /* In certain situations, when the window manager follows a
4350 click-to-focus policy, there seems to be no way around calling
4351 XSetInputFocus to give another frame the input focus .
4353 In an ideal world, XSetInputFocus should generally be avoided so
4354 that applications don't interfere with the window manager's focus
4355 policy. But I think it's okay to use when it's clearly done
4356 following a user-command. */
4358 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4359 "Set the input focus to FRAME.\n\
4360 FRAME nil means use the selected frame.")
4361 (frame)
4362 Lisp_Object frame;
4364 struct frame *f = check_x_frame (frame);
4365 Display *dpy = FRAME_X_DISPLAY (f);
4366 int count;
4368 BLOCK_INPUT;
4369 count = x_catch_errors (dpy);
4370 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4371 RevertToParent, CurrentTime);
4372 x_uncatch_errors (dpy, count);
4373 UNBLOCK_INPUT;
4375 return Qnil;
4379 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4380 "Internal function called by `color-defined-p', which see.")
4381 (color, frame)
4382 Lisp_Object color, frame;
4384 XColor foo;
4385 FRAME_PTR f = check_x_frame (frame);
4387 CHECK_STRING (color, 1);
4389 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4390 return Qt;
4391 else
4392 return Qnil;
4395 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4396 "Internal function called by `color-values', which see.")
4397 (color, frame)
4398 Lisp_Object color, frame;
4400 XColor foo;
4401 FRAME_PTR f = check_x_frame (frame);
4403 CHECK_STRING (color, 1);
4405 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4407 Lisp_Object rgb[3];
4409 rgb[0] = make_number (foo.red);
4410 rgb[1] = make_number (foo.green);
4411 rgb[2] = make_number (foo.blue);
4412 return Flist (3, rgb);
4414 else
4415 return Qnil;
4418 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4419 "Internal function called by `display-color-p', which see.")
4420 (display)
4421 Lisp_Object display;
4423 struct x_display_info *dpyinfo = check_x_display_info (display);
4425 if (dpyinfo->n_planes <= 2)
4426 return Qnil;
4428 switch (dpyinfo->visual->class)
4430 case StaticColor:
4431 case PseudoColor:
4432 case TrueColor:
4433 case DirectColor:
4434 return Qt;
4436 default:
4437 return Qnil;
4441 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4442 0, 1, 0,
4443 "Return t if the X display supports shades of gray.\n\
4444 Note that color displays do support shades of gray.\n\
4445 The optional argument DISPLAY specifies which display to ask about.\n\
4446 DISPLAY should be either a frame or a display name (a string).\n\
4447 If omitted or nil, that stands for the selected frame's display.")
4448 (display)
4449 Lisp_Object display;
4451 struct x_display_info *dpyinfo = check_x_display_info (display);
4453 if (dpyinfo->n_planes <= 1)
4454 return Qnil;
4456 switch (dpyinfo->visual->class)
4458 case StaticColor:
4459 case PseudoColor:
4460 case TrueColor:
4461 case DirectColor:
4462 case StaticGray:
4463 case GrayScale:
4464 return Qt;
4466 default:
4467 return Qnil;
4471 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4472 0, 1, 0,
4473 "Returns the width in pixels of the X display DISPLAY.\n\
4474 The optional argument DISPLAY specifies which display to ask about.\n\
4475 DISPLAY should be either a frame or a display name (a string).\n\
4476 If omitted or nil, that stands for the selected frame's display.")
4477 (display)
4478 Lisp_Object display;
4480 struct x_display_info *dpyinfo = check_x_display_info (display);
4482 return make_number (dpyinfo->width);
4485 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4486 Sx_display_pixel_height, 0, 1, 0,
4487 "Returns the height in pixels of the X display DISPLAY.\n\
4488 The optional argument DISPLAY specifies which display to ask about.\n\
4489 DISPLAY should be either a frame or a display name (a string).\n\
4490 If omitted or nil, that stands for the selected frame's display.")
4491 (display)
4492 Lisp_Object display;
4494 struct x_display_info *dpyinfo = check_x_display_info (display);
4496 return make_number (dpyinfo->height);
4499 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4500 0, 1, 0,
4501 "Returns the number of bitplanes of the X display DISPLAY.\n\
4502 The optional argument DISPLAY specifies which display to ask about.\n\
4503 DISPLAY should be either a frame or a display name (a string).\n\
4504 If omitted or nil, that stands for the selected frame's display.")
4505 (display)
4506 Lisp_Object display;
4508 struct x_display_info *dpyinfo = check_x_display_info (display);
4510 return make_number (dpyinfo->n_planes);
4513 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4514 0, 1, 0,
4515 "Returns the number of color cells of the X display DISPLAY.\n\
4516 The optional argument DISPLAY specifies which display to ask about.\n\
4517 DISPLAY should be either a frame or a display name (a string).\n\
4518 If omitted or nil, that stands for the selected frame's display.")
4519 (display)
4520 Lisp_Object display;
4522 struct x_display_info *dpyinfo = check_x_display_info (display);
4524 return make_number (DisplayCells (dpyinfo->display,
4525 XScreenNumberOfScreen (dpyinfo->screen)));
4528 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4529 Sx_server_max_request_size,
4530 0, 1, 0,
4531 "Returns the maximum request size of the X server of display DISPLAY.\n\
4532 The optional argument DISPLAY specifies which display to ask about.\n\
4533 DISPLAY should be either a frame or a display name (a string).\n\
4534 If omitted or nil, that stands for the selected frame's display.")
4535 (display)
4536 Lisp_Object display;
4538 struct x_display_info *dpyinfo = check_x_display_info (display);
4540 return make_number (MAXREQUEST (dpyinfo->display));
4543 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4544 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4545 The optional argument DISPLAY specifies which display to ask about.\n\
4546 DISPLAY should be either a frame or a display name (a string).\n\
4547 If omitted or nil, that stands for the selected frame's display.")
4548 (display)
4549 Lisp_Object display;
4551 struct x_display_info *dpyinfo = check_x_display_info (display);
4552 char *vendor = ServerVendor (dpyinfo->display);
4554 if (! vendor) vendor = "";
4555 return build_string (vendor);
4558 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4559 "Returns the version numbers of the X server of display DISPLAY.\n\
4560 The value is a list of three integers: the major and minor\n\
4561 version numbers of the X Protocol in use, and the vendor-specific release\n\
4562 number. See also the function `x-server-vendor'.\n\n\
4563 The optional argument DISPLAY specifies which display to ask about.\n\
4564 DISPLAY should be either a frame or a display name (a string).\n\
4565 If omitted or nil, that stands for the selected frame's display.")
4566 (display)
4567 Lisp_Object display;
4569 struct x_display_info *dpyinfo = check_x_display_info (display);
4570 Display *dpy = dpyinfo->display;
4572 return Fcons (make_number (ProtocolVersion (dpy)),
4573 Fcons (make_number (ProtocolRevision (dpy)),
4574 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4577 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4578 "Returns the number of screens on the X server of display DISPLAY.\n\
4579 The optional argument DISPLAY specifies which display to ask about.\n\
4580 DISPLAY should be either a frame or a display name (a string).\n\
4581 If omitted or nil, that stands for the selected frame's display.")
4582 (display)
4583 Lisp_Object display;
4585 struct x_display_info *dpyinfo = check_x_display_info (display);
4587 return make_number (ScreenCount (dpyinfo->display));
4590 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4591 "Returns the height in millimeters of the X display DISPLAY.\n\
4592 The optional argument DISPLAY specifies which display to ask about.\n\
4593 DISPLAY should be either a frame or a display name (a string).\n\
4594 If omitted or nil, that stands for the selected frame's display.")
4595 (display)
4596 Lisp_Object display;
4598 struct x_display_info *dpyinfo = check_x_display_info (display);
4600 return make_number (HeightMMOfScreen (dpyinfo->screen));
4603 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4604 "Returns the width in millimeters of the X display DISPLAY.\n\
4605 The optional argument DISPLAY specifies which display to ask about.\n\
4606 DISPLAY should be either a frame or a display name (a string).\n\
4607 If omitted or nil, that stands for the selected frame's display.")
4608 (display)
4609 Lisp_Object display;
4611 struct x_display_info *dpyinfo = check_x_display_info (display);
4613 return make_number (WidthMMOfScreen (dpyinfo->screen));
4616 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4617 Sx_display_backing_store, 0, 1, 0,
4618 "Returns an indication of whether X display DISPLAY does backing store.\n\
4619 The value may be `always', `when-mapped', or `not-useful'.\n\
4620 The optional argument DISPLAY specifies which display to ask about.\n\
4621 DISPLAY should be either a frame or a display name (a string).\n\
4622 If omitted or nil, that stands for the selected frame's display.")
4623 (display)
4624 Lisp_Object display;
4626 struct x_display_info *dpyinfo = check_x_display_info (display);
4627 Lisp_Object result;
4629 switch (DoesBackingStore (dpyinfo->screen))
4631 case Always:
4632 result = intern ("always");
4633 break;
4635 case WhenMapped:
4636 result = intern ("when-mapped");
4637 break;
4639 case NotUseful:
4640 result = intern ("not-useful");
4641 break;
4643 default:
4644 error ("Strange value for BackingStore parameter of screen");
4645 result = Qnil;
4648 return result;
4651 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4652 Sx_display_visual_class, 0, 1, 0,
4653 "Returns the visual class of the X display DISPLAY.\n\
4654 The value is one of the symbols `static-gray', `gray-scale',\n\
4655 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4656 The optional argument DISPLAY specifies which display to ask about.\n\
4657 DISPLAY should be either a frame or a display name (a string).\n\
4658 If omitted or nil, that stands for the selected frame's display.")
4659 (display)
4660 Lisp_Object display;
4662 struct x_display_info *dpyinfo = check_x_display_info (display);
4663 Lisp_Object result;
4665 switch (dpyinfo->visual->class)
4667 case StaticGray:
4668 result = intern ("static-gray");
4669 break;
4670 case GrayScale:
4671 result = intern ("gray-scale");
4672 break;
4673 case StaticColor:
4674 result = intern ("static-color");
4675 break;
4676 case PseudoColor:
4677 result = intern ("pseudo-color");
4678 break;
4679 case TrueColor:
4680 result = intern ("true-color");
4681 break;
4682 case DirectColor:
4683 result = intern ("direct-color");
4684 break;
4685 default:
4686 error ("Display has an unknown visual class");
4687 result = Qnil;
4690 return result;
4693 DEFUN ("x-display-save-under", Fx_display_save_under,
4694 Sx_display_save_under, 0, 1, 0,
4695 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4696 The optional argument DISPLAY specifies which display to ask about.\n\
4697 DISPLAY should be either a frame or a display name (a string).\n\
4698 If omitted or nil, that stands for the selected frame's display.")
4699 (display)
4700 Lisp_Object display;
4702 struct x_display_info *dpyinfo = check_x_display_info (display);
4704 if (DoesSaveUnders (dpyinfo->screen) == True)
4705 return Qt;
4706 else
4707 return Qnil;
4711 x_pixel_width (f)
4712 register struct frame *f;
4714 return PIXEL_WIDTH (f);
4718 x_pixel_height (f)
4719 register struct frame *f;
4721 return PIXEL_HEIGHT (f);
4725 x_char_width (f)
4726 register struct frame *f;
4728 return FONT_WIDTH (f->output_data.x->font);
4732 x_char_height (f)
4733 register struct frame *f;
4735 return f->output_data.x->line_height;
4739 x_screen_planes (f)
4740 register struct frame *f;
4742 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4747 /************************************************************************
4748 X Displays
4749 ************************************************************************/
4752 /* Mapping visual names to visuals. */
4754 static struct visual_class
4756 char *name;
4757 int class;
4759 visual_classes[] =
4761 {"StaticGray", StaticGray},
4762 {"GrayScale", GrayScale},
4763 {"StaticColor", StaticColor},
4764 {"PseudoColor", PseudoColor},
4765 {"TrueColor", TrueColor},
4766 {"DirectColor", DirectColor},
4767 NULL
4771 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4773 /* Value is the screen number of screen SCR. This is a substitute for
4774 the X function with the same name when that doesn't exist. */
4777 XScreenNumberOfScreen (scr)
4778 register Screen *scr;
4780 Display *dpy = scr->display;
4781 int i;
4783 for (i = 0; i < dpy->nscreens; ++i)
4784 if (scr == dpy->screens[i])
4785 break;
4787 return i;
4790 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4793 /* Select the visual that should be used on display DPYINFO. Set
4794 members of DPYINFO appropriately. Called from x_term_init. */
4796 void
4797 select_visual (dpyinfo)
4798 struct x_display_info *dpyinfo;
4800 Display *dpy = dpyinfo->display;
4801 Screen *screen = dpyinfo->screen;
4802 Lisp_Object value;
4804 /* See if a visual is specified. */
4805 value = display_x_get_resource (dpyinfo,
4806 build_string ("visualClass"),
4807 build_string ("VisualClass"),
4808 Qnil, Qnil);
4809 if (STRINGP (value))
4811 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4812 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4813 depth, a decimal number. NAME is compared with case ignored. */
4814 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4815 char *dash;
4816 int i, class = -1;
4817 XVisualInfo vinfo;
4819 strcpy (s, XSTRING (value)->data);
4820 dash = index (s, '-');
4821 if (dash)
4823 dpyinfo->n_planes = atoi (dash + 1);
4824 *dash = '\0';
4826 else
4827 /* We won't find a matching visual with depth 0, so that
4828 an error will be printed below. */
4829 dpyinfo->n_planes = 0;
4831 /* Determine the visual class. */
4832 for (i = 0; visual_classes[i].name; ++i)
4833 if (xstricmp (s, visual_classes[i].name) == 0)
4835 class = visual_classes[i].class;
4836 break;
4839 /* Look up a matching visual for the specified class. */
4840 if (class == -1
4841 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4842 dpyinfo->n_planes, class, &vinfo))
4843 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
4845 dpyinfo->visual = vinfo.visual;
4847 else
4849 int n_visuals;
4850 XVisualInfo *vinfo, vinfo_template;
4852 dpyinfo->visual = DefaultVisualOfScreen (screen);
4854 #ifdef HAVE_X11R4
4855 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4856 #else
4857 vinfo_template.visualid = dpyinfo->visual->visualid;
4858 #endif
4859 vinfo_template.screen = XScreenNumberOfScreen (screen);
4860 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4861 &vinfo_template, &n_visuals);
4862 if (n_visuals != 1)
4863 fatal ("Can't get proper X visual info");
4865 dpyinfo->n_planes = vinfo->depth;
4866 XFree ((char *) vinfo);
4871 /* Return the X display structure for the display named NAME.
4872 Open a new connection if necessary. */
4874 struct x_display_info *
4875 x_display_info_for_name (name)
4876 Lisp_Object name;
4878 Lisp_Object names;
4879 struct x_display_info *dpyinfo;
4881 CHECK_STRING (name, 0);
4883 if (! EQ (Vwindow_system, intern ("x")))
4884 error ("Not using X Windows");
4886 for (dpyinfo = x_display_list, names = x_display_name_list;
4887 dpyinfo;
4888 dpyinfo = dpyinfo->next, names = XCDR (names))
4890 Lisp_Object tem;
4891 tem = Fstring_equal (XCAR (XCAR (names)), name);
4892 if (!NILP (tem))
4893 return dpyinfo;
4896 /* Use this general default value to start with. */
4897 Vx_resource_name = Vinvocation_name;
4899 validate_x_resource_name ();
4901 dpyinfo = x_term_init (name, (unsigned char *)0,
4902 (char *) XSTRING (Vx_resource_name)->data);
4904 if (dpyinfo == 0)
4905 error ("Cannot connect to X server %s", XSTRING (name)->data);
4907 x_in_use = 1;
4908 XSETFASTINT (Vwindow_system_version, 11);
4910 return dpyinfo;
4914 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4915 1, 3, 0, "Open a connection to an X server.\n\
4916 DISPLAY is the name of the display to connect to.\n\
4917 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4918 If the optional third arg MUST-SUCCEED is non-nil,\n\
4919 terminate Emacs if we can't open the connection.")
4920 (display, xrm_string, must_succeed)
4921 Lisp_Object display, xrm_string, must_succeed;
4923 unsigned char *xrm_option;
4924 struct x_display_info *dpyinfo;
4926 CHECK_STRING (display, 0);
4927 if (! NILP (xrm_string))
4928 CHECK_STRING (xrm_string, 1);
4930 if (! EQ (Vwindow_system, intern ("x")))
4931 error ("Not using X Windows");
4933 if (! NILP (xrm_string))
4934 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4935 else
4936 xrm_option = (unsigned char *) 0;
4938 validate_x_resource_name ();
4940 /* This is what opens the connection and sets x_current_display.
4941 This also initializes many symbols, such as those used for input. */
4942 dpyinfo = x_term_init (display, xrm_option,
4943 (char *) XSTRING (Vx_resource_name)->data);
4945 if (dpyinfo == 0)
4947 if (!NILP (must_succeed))
4948 fatal ("Cannot connect to X server %s.\n\
4949 Check the DISPLAY environment variable or use `-d'.\n\
4950 Also use the `xhost' program to verify that it is set to permit\n\
4951 connections from your machine.\n",
4952 XSTRING (display)->data);
4953 else
4954 error ("Cannot connect to X server %s", XSTRING (display)->data);
4957 x_in_use = 1;
4959 XSETFASTINT (Vwindow_system_version, 11);
4960 return Qnil;
4963 DEFUN ("x-close-connection", Fx_close_connection,
4964 Sx_close_connection, 1, 1, 0,
4965 "Close the connection to DISPLAY's X server.\n\
4966 For DISPLAY, specify either a frame or a display name (a string).\n\
4967 If DISPLAY is nil, that stands for the selected frame's display.")
4968 (display)
4969 Lisp_Object display;
4971 struct x_display_info *dpyinfo = check_x_display_info (display);
4972 int i;
4974 if (dpyinfo->reference_count > 0)
4975 error ("Display still has frames on it");
4977 BLOCK_INPUT;
4978 /* Free the fonts in the font table. */
4979 for (i = 0; i < dpyinfo->n_fonts; i++)
4980 if (dpyinfo->font_table[i].name)
4982 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4983 xfree (dpyinfo->font_table[i].full_name);
4984 xfree (dpyinfo->font_table[i].name);
4985 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4988 x_destroy_all_bitmaps (dpyinfo);
4989 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4991 #ifdef USE_X_TOOLKIT
4992 XtCloseDisplay (dpyinfo->display);
4993 #else
4994 XCloseDisplay (dpyinfo->display);
4995 #endif
4997 x_delete_display (dpyinfo);
4998 UNBLOCK_INPUT;
5000 return Qnil;
5003 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5004 "Return the list of display names that Emacs has connections to.")
5007 Lisp_Object tail, result;
5009 result = Qnil;
5010 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5011 result = Fcons (XCAR (XCAR (tail)), result);
5013 return result;
5016 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5017 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5018 If ON is nil, allow buffering of requests.\n\
5019 Turning on synchronization prohibits the Xlib routines from buffering\n\
5020 requests and seriously degrades performance, but makes debugging much\n\
5021 easier.\n\
5022 The optional second argument DISPLAY specifies which display to act on.\n\
5023 DISPLAY should be either a frame or a display name (a string).\n\
5024 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5025 (on, display)
5026 Lisp_Object display, on;
5028 struct x_display_info *dpyinfo = check_x_display_info (display);
5030 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5032 return Qnil;
5035 /* Wait for responses to all X commands issued so far for frame F. */
5037 void
5038 x_sync (f)
5039 FRAME_PTR f;
5041 BLOCK_INPUT;
5042 XSync (FRAME_X_DISPLAY (f), False);
5043 UNBLOCK_INPUT;
5047 /***********************************************************************
5048 Image types
5049 ***********************************************************************/
5051 /* Value is the number of elements of vector VECTOR. */
5053 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5055 /* List of supported image types. Use define_image_type to add new
5056 types. Use lookup_image_type to find a type for a given symbol. */
5058 static struct image_type *image_types;
5060 /* The symbol `image' which is the car of the lists used to represent
5061 images in Lisp. */
5063 extern Lisp_Object Qimage;
5065 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5067 Lisp_Object Qxbm;
5069 /* Keywords. */
5071 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5072 extern Lisp_Object QCdata;
5073 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5074 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
5075 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5077 /* Other symbols. */
5079 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5081 /* Time in seconds after which images should be removed from the cache
5082 if not displayed. */
5084 Lisp_Object Vimage_cache_eviction_delay;
5086 /* Function prototypes. */
5088 static void define_image_type P_ ((struct image_type *type));
5089 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5090 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5091 static void x_laplace P_ ((struct frame *, struct image *));
5092 static void x_emboss P_ ((struct frame *, struct image *));
5093 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5094 Lisp_Object));
5097 /* Define a new image type from TYPE. This adds a copy of TYPE to
5098 image_types and adds the symbol *TYPE->type to Vimage_types. */
5100 static void
5101 define_image_type (type)
5102 struct image_type *type;
5104 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5105 The initialized data segment is read-only. */
5106 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5107 bcopy (type, p, sizeof *p);
5108 p->next = image_types;
5109 image_types = p;
5110 Vimage_types = Fcons (*p->type, Vimage_types);
5114 /* Look up image type SYMBOL, and return a pointer to its image_type
5115 structure. Value is null if SYMBOL is not a known image type. */
5117 static INLINE struct image_type *
5118 lookup_image_type (symbol)
5119 Lisp_Object symbol;
5121 struct image_type *type;
5123 for (type = image_types; type; type = type->next)
5124 if (EQ (symbol, *type->type))
5125 break;
5127 return type;
5131 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5132 valid image specification is a list whose car is the symbol
5133 `image', and whose rest is a property list. The property list must
5134 contain a value for key `:type'. That value must be the name of a
5135 supported image type. The rest of the property list depends on the
5136 image type. */
5139 valid_image_p (object)
5140 Lisp_Object object;
5142 int valid_p = 0;
5144 if (CONSP (object) && EQ (XCAR (object), Qimage))
5146 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5147 struct image_type *type = lookup_image_type (symbol);
5149 if (type)
5150 valid_p = type->valid_p (object);
5153 return valid_p;
5157 /* Log error message with format string FORMAT and argument ARG.
5158 Signaling an error, e.g. when an image cannot be loaded, is not a
5159 good idea because this would interrupt redisplay, and the error
5160 message display would lead to another redisplay. This function
5161 therefore simply displays a message. */
5163 static void
5164 image_error (format, arg1, arg2)
5165 char *format;
5166 Lisp_Object arg1, arg2;
5168 add_to_log (format, arg1, arg2);
5173 /***********************************************************************
5174 Image specifications
5175 ***********************************************************************/
5177 enum image_value_type
5179 IMAGE_DONT_CHECK_VALUE_TYPE,
5180 IMAGE_STRING_VALUE,
5181 IMAGE_SYMBOL_VALUE,
5182 IMAGE_POSITIVE_INTEGER_VALUE,
5183 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5184 IMAGE_ASCENT_VALUE,
5185 IMAGE_INTEGER_VALUE,
5186 IMAGE_FUNCTION_VALUE,
5187 IMAGE_NUMBER_VALUE,
5188 IMAGE_BOOL_VALUE
5191 /* Structure used when parsing image specifications. */
5193 struct image_keyword
5195 /* Name of keyword. */
5196 char *name;
5198 /* The type of value allowed. */
5199 enum image_value_type type;
5201 /* Non-zero means key must be present. */
5202 int mandatory_p;
5204 /* Used to recognize duplicate keywords in a property list. */
5205 int count;
5207 /* The value that was found. */
5208 Lisp_Object value;
5212 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5213 int, Lisp_Object));
5214 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5217 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5218 has the format (image KEYWORD VALUE ...). One of the keyword/
5219 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5220 image_keywords structures of size NKEYWORDS describing other
5221 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5223 static int
5224 parse_image_spec (spec, keywords, nkeywords, type)
5225 Lisp_Object spec;
5226 struct image_keyword *keywords;
5227 int nkeywords;
5228 Lisp_Object type;
5230 int i;
5231 Lisp_Object plist;
5233 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5234 return 0;
5236 plist = XCDR (spec);
5237 while (CONSP (plist))
5239 Lisp_Object key, value;
5241 /* First element of a pair must be a symbol. */
5242 key = XCAR (plist);
5243 plist = XCDR (plist);
5244 if (!SYMBOLP (key))
5245 return 0;
5247 /* There must follow a value. */
5248 if (!CONSP (plist))
5249 return 0;
5250 value = XCAR (plist);
5251 plist = XCDR (plist);
5253 /* Find key in KEYWORDS. Error if not found. */
5254 for (i = 0; i < nkeywords; ++i)
5255 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5256 break;
5258 if (i == nkeywords)
5259 continue;
5261 /* Record that we recognized the keyword. If a keywords
5262 was found more than once, it's an error. */
5263 keywords[i].value = value;
5264 ++keywords[i].count;
5266 if (keywords[i].count > 1)
5267 return 0;
5269 /* Check type of value against allowed type. */
5270 switch (keywords[i].type)
5272 case IMAGE_STRING_VALUE:
5273 if (!STRINGP (value))
5274 return 0;
5275 break;
5277 case IMAGE_SYMBOL_VALUE:
5278 if (!SYMBOLP (value))
5279 return 0;
5280 break;
5282 case IMAGE_POSITIVE_INTEGER_VALUE:
5283 if (!INTEGERP (value) || XINT (value) <= 0)
5284 return 0;
5285 break;
5287 case IMAGE_ASCENT_VALUE:
5288 if (SYMBOLP (value) && EQ (value, Qcenter))
5289 break;
5290 else if (INTEGERP (value)
5291 && XINT (value) >= 0
5292 && XINT (value) <= 100)
5293 break;
5294 return 0;
5296 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5297 if (!INTEGERP (value) || XINT (value) < 0)
5298 return 0;
5299 break;
5301 case IMAGE_DONT_CHECK_VALUE_TYPE:
5302 break;
5304 case IMAGE_FUNCTION_VALUE:
5305 value = indirect_function (value);
5306 if (SUBRP (value)
5307 || COMPILEDP (value)
5308 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5309 break;
5310 return 0;
5312 case IMAGE_NUMBER_VALUE:
5313 if (!INTEGERP (value) && !FLOATP (value))
5314 return 0;
5315 break;
5317 case IMAGE_INTEGER_VALUE:
5318 if (!INTEGERP (value))
5319 return 0;
5320 break;
5322 case IMAGE_BOOL_VALUE:
5323 if (!NILP (value) && !EQ (value, Qt))
5324 return 0;
5325 break;
5327 default:
5328 abort ();
5329 break;
5332 if (EQ (key, QCtype) && !EQ (type, value))
5333 return 0;
5336 /* Check that all mandatory fields are present. */
5337 for (i = 0; i < nkeywords; ++i)
5338 if (keywords[i].mandatory_p && keywords[i].count == 0)
5339 return 0;
5341 return NILP (plist);
5345 /* Return the value of KEY in image specification SPEC. Value is nil
5346 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5347 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5349 static Lisp_Object
5350 image_spec_value (spec, key, found)
5351 Lisp_Object spec, key;
5352 int *found;
5354 Lisp_Object tail;
5356 xassert (valid_image_p (spec));
5358 for (tail = XCDR (spec);
5359 CONSP (tail) && CONSP (XCDR (tail));
5360 tail = XCDR (XCDR (tail)))
5362 if (EQ (XCAR (tail), key))
5364 if (found)
5365 *found = 1;
5366 return XCAR (XCDR (tail));
5370 if (found)
5371 *found = 0;
5372 return Qnil;
5376 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5377 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5378 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5379 size in canonical character units.\n\
5380 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5381 or omitted means use the selected frame.")
5382 (spec, pixels, frame)
5383 Lisp_Object spec, pixels, frame;
5385 Lisp_Object size;
5387 size = Qnil;
5388 if (valid_image_p (spec))
5390 struct frame *f = check_x_frame (frame);
5391 int id = lookup_image (f, spec);
5392 struct image *img = IMAGE_FROM_ID (f, id);
5393 int width = img->width + 2 * img->margin;
5394 int height = img->height + 2 * img->margin;
5396 if (NILP (pixels))
5397 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5398 make_float ((double) height / CANON_Y_UNIT (f)));
5399 else
5400 size = Fcons (make_number (width), make_number (height));
5402 else
5403 error ("Invalid image specification");
5405 return size;
5409 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5410 "Return t if image SPEC has a mask bitmap.\n\
5411 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5412 or omitted means use the selected frame.")
5413 (spec, frame)
5414 Lisp_Object spec, frame;
5416 Lisp_Object mask;
5418 mask = Qnil;
5419 if (valid_image_p (spec))
5421 struct frame *f = check_x_frame (frame);
5422 int id = lookup_image (f, spec);
5423 struct image *img = IMAGE_FROM_ID (f, id);
5424 if (img->mask)
5425 mask = Qt;
5427 else
5428 error ("Invalid image specification");
5430 return mask;
5435 /***********************************************************************
5436 Image type independent image structures
5437 ***********************************************************************/
5439 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5440 static void free_image P_ ((struct frame *f, struct image *img));
5443 /* Allocate and return a new image structure for image specification
5444 SPEC. SPEC has a hash value of HASH. */
5446 static struct image *
5447 make_image (spec, hash)
5448 Lisp_Object spec;
5449 unsigned hash;
5451 struct image *img = (struct image *) xmalloc (sizeof *img);
5453 xassert (valid_image_p (spec));
5454 bzero (img, sizeof *img);
5455 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5456 xassert (img->type != NULL);
5457 img->spec = spec;
5458 img->data.lisp_val = Qnil;
5459 img->ascent = DEFAULT_IMAGE_ASCENT;
5460 img->hash = hash;
5461 return img;
5465 /* Free image IMG which was used on frame F, including its resources. */
5467 static void
5468 free_image (f, img)
5469 struct frame *f;
5470 struct image *img;
5472 if (img)
5474 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5476 /* Remove IMG from the hash table of its cache. */
5477 if (img->prev)
5478 img->prev->next = img->next;
5479 else
5480 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5482 if (img->next)
5483 img->next->prev = img->prev;
5485 c->images[img->id] = NULL;
5487 /* Free resources, then free IMG. */
5488 img->type->free (f, img);
5489 xfree (img);
5494 /* Prepare image IMG for display on frame F. Must be called before
5495 drawing an image. */
5497 void
5498 prepare_image_for_display (f, img)
5499 struct frame *f;
5500 struct image *img;
5502 EMACS_TIME t;
5504 /* We're about to display IMG, so set its timestamp to `now'. */
5505 EMACS_GET_TIME (t);
5506 img->timestamp = EMACS_SECS (t);
5508 /* If IMG doesn't have a pixmap yet, load it now, using the image
5509 type dependent loader function. */
5510 if (img->pixmap == None && !img->load_failed_p)
5511 img->load_failed_p = img->type->load (f, img) == 0;
5515 /* Value is the number of pixels for the ascent of image IMG when
5516 drawn in face FACE. */
5519 image_ascent (img, face)
5520 struct image *img;
5521 struct face *face;
5523 int height = img->height + img->margin;
5524 int ascent;
5526 if (img->ascent == CENTERED_IMAGE_ASCENT)
5528 if (face->font)
5529 /* This expression is arranged so that if the image can't be
5530 exactly centered, it will be moved slightly up. This is
5531 because a typical font is `top-heavy' (due to the presence
5532 uppercase letters), so the image placement should err towards
5533 being top-heavy too. It also just generally looks better. */
5534 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5535 else
5536 ascent = height / 2;
5538 else
5539 ascent = height * img->ascent / 100.0;
5541 return ascent;
5546 /***********************************************************************
5547 Helper functions for X image types
5548 ***********************************************************************/
5550 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5551 int, int));
5552 static void x_clear_image P_ ((struct frame *f, struct image *img));
5553 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5554 struct image *img,
5555 Lisp_Object color_name,
5556 unsigned long dflt));
5559 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5560 free the pixmap if any. MASK_P non-zero means clear the mask
5561 pixmap if any. COLORS_P non-zero means free colors allocated for
5562 the image, if any. */
5564 static void
5565 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5566 struct frame *f;
5567 struct image *img;
5568 int pixmap_p, mask_p, colors_p;
5570 if (pixmap_p && img->pixmap)
5572 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5573 img->pixmap = None;
5576 if (mask_p && img->mask)
5578 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5579 img->mask = None;
5582 if (colors_p && img->ncolors)
5584 x_free_colors (f, img->colors, img->ncolors);
5585 xfree (img->colors);
5586 img->colors = NULL;
5587 img->ncolors = 0;
5591 /* Free X resources of image IMG which is used on frame F. */
5593 static void
5594 x_clear_image (f, img)
5595 struct frame *f;
5596 struct image *img;
5598 BLOCK_INPUT;
5599 x_clear_image_1 (f, img, 1, 1, 1);
5600 UNBLOCK_INPUT;
5604 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5605 cannot be allocated, use DFLT. Add a newly allocated color to
5606 IMG->colors, so that it can be freed again. Value is the pixel
5607 color. */
5609 static unsigned long
5610 x_alloc_image_color (f, img, color_name, dflt)
5611 struct frame *f;
5612 struct image *img;
5613 Lisp_Object color_name;
5614 unsigned long dflt;
5616 XColor color;
5617 unsigned long result;
5619 xassert (STRINGP (color_name));
5621 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5623 /* This isn't called frequently so we get away with simply
5624 reallocating the color vector to the needed size, here. */
5625 ++img->ncolors;
5626 img->colors =
5627 (unsigned long *) xrealloc (img->colors,
5628 img->ncolors * sizeof *img->colors);
5629 img->colors[img->ncolors - 1] = color.pixel;
5630 result = color.pixel;
5632 else
5633 result = dflt;
5635 return result;
5640 /***********************************************************************
5641 Image Cache
5642 ***********************************************************************/
5644 static void cache_image P_ ((struct frame *f, struct image *img));
5647 /* Return a new, initialized image cache that is allocated from the
5648 heap. Call free_image_cache to free an image cache. */
5650 struct image_cache *
5651 make_image_cache ()
5653 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5654 int size;
5656 bzero (c, sizeof *c);
5657 c->size = 50;
5658 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5659 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5660 c->buckets = (struct image **) xmalloc (size);
5661 bzero (c->buckets, size);
5662 return c;
5666 /* Free image cache of frame F. Be aware that X frames share images
5667 caches. */
5669 void
5670 free_image_cache (f)
5671 struct frame *f;
5673 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5674 if (c)
5676 int i;
5678 /* Cache should not be referenced by any frame when freed. */
5679 xassert (c->refcount == 0);
5681 for (i = 0; i < c->used; ++i)
5682 free_image (f, c->images[i]);
5683 xfree (c->images);
5684 xfree (c->buckets);
5685 xfree (c);
5686 FRAME_X_IMAGE_CACHE (f) = NULL;
5691 /* Clear image cache of frame F. FORCE_P non-zero means free all
5692 images. FORCE_P zero means clear only images that haven't been
5693 displayed for some time. Should be called from time to time to
5694 reduce the number of loaded images. If image-eviction-seconds is
5695 non-nil, this frees images in the cache which weren't displayed for
5696 at least that many seconds. */
5698 void
5699 clear_image_cache (f, force_p)
5700 struct frame *f;
5701 int force_p;
5703 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5705 if (c && INTEGERP (Vimage_cache_eviction_delay))
5707 EMACS_TIME t;
5708 unsigned long old;
5709 int i, nfreed;
5711 EMACS_GET_TIME (t);
5712 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5714 /* Block input so that we won't be interrupted by a SIGIO
5715 while being in an inconsistent state. */
5716 BLOCK_INPUT;
5718 for (i = nfreed = 0; i < c->used; ++i)
5720 struct image *img = c->images[i];
5721 if (img != NULL
5722 && (force_p || img->timestamp < old))
5724 free_image (f, img);
5725 ++nfreed;
5729 /* We may be clearing the image cache because, for example,
5730 Emacs was iconified for a longer period of time. In that
5731 case, current matrices may still contain references to
5732 images freed above. So, clear these matrices. */
5733 if (nfreed)
5735 Lisp_Object tail, frame;
5737 FOR_EACH_FRAME (tail, frame)
5739 struct frame *f = XFRAME (frame);
5740 if (FRAME_X_P (f)
5741 && FRAME_X_IMAGE_CACHE (f) == c)
5742 clear_current_matrices (f);
5745 ++windows_or_buffers_changed;
5748 UNBLOCK_INPUT;
5753 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5754 0, 1, 0,
5755 "Clear the image cache of FRAME.\n\
5756 FRAME nil or omitted means use the selected frame.\n\
5757 FRAME t means clear the image caches of all frames.")
5758 (frame)
5759 Lisp_Object frame;
5761 if (EQ (frame, Qt))
5763 Lisp_Object tail;
5765 FOR_EACH_FRAME (tail, frame)
5766 if (FRAME_X_P (XFRAME (frame)))
5767 clear_image_cache (XFRAME (frame), 1);
5769 else
5770 clear_image_cache (check_x_frame (frame), 1);
5772 return Qnil;
5776 /* Return the id of image with Lisp specification SPEC on frame F.
5777 SPEC must be a valid Lisp image specification (see valid_image_p). */
5780 lookup_image (f, spec)
5781 struct frame *f;
5782 Lisp_Object spec;
5784 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5785 struct image *img;
5786 int i;
5787 unsigned hash;
5788 struct gcpro gcpro1;
5789 EMACS_TIME now;
5791 /* F must be a window-system frame, and SPEC must be a valid image
5792 specification. */
5793 xassert (FRAME_WINDOW_P (f));
5794 xassert (valid_image_p (spec));
5796 GCPRO1 (spec);
5798 /* Look up SPEC in the hash table of the image cache. */
5799 hash = sxhash (spec, 0);
5800 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5802 for (img = c->buckets[i]; img; img = img->next)
5803 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5804 break;
5806 /* If not found, create a new image and cache it. */
5807 if (img == NULL)
5809 BLOCK_INPUT;
5810 img = make_image (spec, hash);
5811 cache_image (f, img);
5812 img->load_failed_p = img->type->load (f, img) == 0;
5814 /* If we can't load the image, and we don't have a width and
5815 height, use some arbitrary width and height so that we can
5816 draw a rectangle for it. */
5817 if (img->load_failed_p)
5819 Lisp_Object value;
5821 value = image_spec_value (spec, QCwidth, NULL);
5822 img->width = (INTEGERP (value)
5823 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5824 value = image_spec_value (spec, QCheight, NULL);
5825 img->height = (INTEGERP (value)
5826 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5828 else
5830 /* Handle image type independent image attributes
5831 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5832 Lisp_Object ascent, margin, relief;
5833 Lisp_Object file;
5835 ascent = image_spec_value (spec, QCascent, NULL);
5836 if (INTEGERP (ascent))
5837 img->ascent = XFASTINT (ascent);
5838 else if (EQ (ascent, Qcenter))
5839 img->ascent = CENTERED_IMAGE_ASCENT;
5841 margin = image_spec_value (spec, QCmargin, NULL);
5842 if (INTEGERP (margin) && XINT (margin) >= 0)
5843 img->margin = XFASTINT (margin);
5845 relief = image_spec_value (spec, QCrelief, NULL);
5846 if (INTEGERP (relief))
5848 img->relief = XINT (relief);
5849 img->margin += abs (img->relief);
5852 /* Manipulation of the image's mask. */
5853 if (img->pixmap)
5855 /* `:heuristic-mask t'
5856 `:mask heuristic'
5857 means build a mask heuristically.
5858 `:heuristic-mask (R G B)'
5859 `:mask (heuristic (R G B))'
5860 means build a mask from color (R G B) in the
5861 image.
5862 `:mask nil'
5863 means remove a mask, if any. */
5865 Lisp_Object mask;
5867 mask = image_spec_value (spec, QCheuristic_mask, NULL);
5868 if (!NILP (mask))
5869 x_build_heuristic_mask (f, img, mask);
5870 else
5872 int found_p;
5874 mask = image_spec_value (spec, QCmask, &found_p);
5876 if (EQ (mask, Qheuristic))
5877 x_build_heuristic_mask (f, img, Qt);
5878 else if (CONSP (mask)
5879 && EQ (XCAR (mask), Qheuristic))
5881 if (CONSP (XCDR (mask)))
5882 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
5883 else
5884 x_build_heuristic_mask (f, img, XCDR (mask));
5886 else if (NILP (mask) && found_p && img->mask)
5888 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5889 img->mask = None;
5894 /* Should we apply an image transformation algorithm? */
5895 if (img->pixmap)
5897 Lisp_Object algorithm;
5899 algorithm = image_spec_value (spec, QCalgorithm, NULL);
5900 if (EQ (algorithm, Qdisabled))
5901 x_disable_image (f, img);
5902 else if (EQ (algorithm, Qlaplace))
5903 x_laplace (f, img);
5904 else if (EQ (algorithm, Qemboss))
5905 x_emboss (f, img);
5906 else if (CONSP (algorithm)
5907 && EQ (XCAR (algorithm), Qedge_detection))
5909 Lisp_Object tem;
5910 tem = XCDR (algorithm);
5911 if (CONSP (tem))
5912 x_edge_detection (f, img,
5913 Fplist_get (tem, QCmatrix),
5914 Fplist_get (tem, QCcolor_adjustment));
5919 UNBLOCK_INPUT;
5920 xassert (!interrupt_input_blocked);
5923 /* We're using IMG, so set its timestamp to `now'. */
5924 EMACS_GET_TIME (now);
5925 img->timestamp = EMACS_SECS (now);
5927 UNGCPRO;
5929 /* Value is the image id. */
5930 return img->id;
5934 /* Cache image IMG in the image cache of frame F. */
5936 static void
5937 cache_image (f, img)
5938 struct frame *f;
5939 struct image *img;
5941 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5942 int i;
5944 /* Find a free slot in c->images. */
5945 for (i = 0; i < c->used; ++i)
5946 if (c->images[i] == NULL)
5947 break;
5949 /* If no free slot found, maybe enlarge c->images. */
5950 if (i == c->used && c->used == c->size)
5952 c->size *= 2;
5953 c->images = (struct image **) xrealloc (c->images,
5954 c->size * sizeof *c->images);
5957 /* Add IMG to c->images, and assign IMG an id. */
5958 c->images[i] = img;
5959 img->id = i;
5960 if (i == c->used)
5961 ++c->used;
5963 /* Add IMG to the cache's hash table. */
5964 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5965 img->next = c->buckets[i];
5966 if (img->next)
5967 img->next->prev = img;
5968 img->prev = NULL;
5969 c->buckets[i] = img;
5973 /* Call FN on every image in the image cache of frame F. Used to mark
5974 Lisp Objects in the image cache. */
5976 void
5977 forall_images_in_image_cache (f, fn)
5978 struct frame *f;
5979 void (*fn) P_ ((struct image *img));
5981 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5983 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5984 if (c)
5986 int i;
5987 for (i = 0; i < c->used; ++i)
5988 if (c->images[i])
5989 fn (c->images[i]);
5996 /***********************************************************************
5997 X support code
5998 ***********************************************************************/
6000 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
6001 XImage **, Pixmap *));
6002 static void x_destroy_x_image P_ ((XImage *));
6003 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6006 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6007 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6008 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6009 via xmalloc. Print error messages via image_error if an error
6010 occurs. Value is non-zero if successful. */
6012 static int
6013 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6014 struct frame *f;
6015 int width, height, depth;
6016 XImage **ximg;
6017 Pixmap *pixmap;
6019 Display *display = FRAME_X_DISPLAY (f);
6020 Screen *screen = FRAME_X_SCREEN (f);
6021 Window window = FRAME_X_WINDOW (f);
6023 xassert (interrupt_input_blocked);
6025 if (depth <= 0)
6026 depth = DefaultDepthOfScreen (screen);
6027 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6028 depth, ZPixmap, 0, NULL, width, height,
6029 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6030 if (*ximg == NULL)
6032 image_error ("Unable to allocate X image", Qnil, Qnil);
6033 return 0;
6036 /* Allocate image raster. */
6037 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6039 /* Allocate a pixmap of the same size. */
6040 *pixmap = XCreatePixmap (display, window, width, height, depth);
6041 if (*pixmap == None)
6043 x_destroy_x_image (*ximg);
6044 *ximg = NULL;
6045 image_error ("Unable to create X pixmap", Qnil, Qnil);
6046 return 0;
6049 return 1;
6053 /* Destroy XImage XIMG. Free XIMG->data. */
6055 static void
6056 x_destroy_x_image (ximg)
6057 XImage *ximg;
6059 xassert (interrupt_input_blocked);
6060 if (ximg)
6062 xfree (ximg->data);
6063 ximg->data = NULL;
6064 XDestroyImage (ximg);
6069 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6070 are width and height of both the image and pixmap. */
6072 static void
6073 x_put_x_image (f, ximg, pixmap, width, height)
6074 struct frame *f;
6075 XImage *ximg;
6076 Pixmap pixmap;
6078 GC gc;
6080 xassert (interrupt_input_blocked);
6081 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6082 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6083 XFreeGC (FRAME_X_DISPLAY (f), gc);
6088 /***********************************************************************
6089 File Handling
6090 ***********************************************************************/
6092 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6093 static char *slurp_file P_ ((char *, int *));
6096 /* Find image file FILE. Look in data-directory, then
6097 x-bitmap-file-path. Value is the full name of the file found, or
6098 nil if not found. */
6100 static Lisp_Object
6101 x_find_image_file (file)
6102 Lisp_Object file;
6104 Lisp_Object file_found, search_path;
6105 struct gcpro gcpro1, gcpro2;
6106 int fd;
6108 file_found = Qnil;
6109 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6110 GCPRO2 (file_found, search_path);
6112 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6113 fd = openp (search_path, file, "", &file_found, 0);
6115 if (fd < 0)
6116 file_found = Qnil;
6117 else
6118 close (fd);
6120 UNGCPRO;
6121 return file_found;
6125 /* Read FILE into memory. Value is a pointer to a buffer allocated
6126 with xmalloc holding FILE's contents. Value is null if an error
6127 occurred. *SIZE is set to the size of the file. */
6129 static char *
6130 slurp_file (file, size)
6131 char *file;
6132 int *size;
6134 FILE *fp = NULL;
6135 char *buf = NULL;
6136 struct stat st;
6138 if (stat (file, &st) == 0
6139 && (fp = fopen (file, "r")) != NULL
6140 && (buf = (char *) xmalloc (st.st_size),
6141 fread (buf, 1, st.st_size, fp) == st.st_size))
6143 *size = st.st_size;
6144 fclose (fp);
6146 else
6148 if (fp)
6149 fclose (fp);
6150 if (buf)
6152 xfree (buf);
6153 buf = NULL;
6157 return buf;
6162 /***********************************************************************
6163 XBM images
6164 ***********************************************************************/
6166 static int xbm_scan P_ ((char **, char *, char *, int *));
6167 static int xbm_load P_ ((struct frame *f, struct image *img));
6168 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6169 char *, char *));
6170 static int xbm_image_p P_ ((Lisp_Object object));
6171 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6172 unsigned char **));
6173 static int xbm_file_p P_ ((Lisp_Object));
6176 /* Indices of image specification fields in xbm_format, below. */
6178 enum xbm_keyword_index
6180 XBM_TYPE,
6181 XBM_FILE,
6182 XBM_WIDTH,
6183 XBM_HEIGHT,
6184 XBM_DATA,
6185 XBM_FOREGROUND,
6186 XBM_BACKGROUND,
6187 XBM_ASCENT,
6188 XBM_MARGIN,
6189 XBM_RELIEF,
6190 XBM_ALGORITHM,
6191 XBM_HEURISTIC_MASK,
6192 XBM_MASK,
6193 XBM_LAST
6196 /* Vector of image_keyword structures describing the format
6197 of valid XBM image specifications. */
6199 static struct image_keyword xbm_format[XBM_LAST] =
6201 {":type", IMAGE_SYMBOL_VALUE, 1},
6202 {":file", IMAGE_STRING_VALUE, 0},
6203 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6204 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6205 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6206 {":foreground", IMAGE_STRING_VALUE, 0},
6207 {":background", IMAGE_STRING_VALUE, 0},
6208 {":ascent", IMAGE_ASCENT_VALUE, 0},
6209 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6210 {":relief", IMAGE_INTEGER_VALUE, 0},
6211 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6212 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6213 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6216 /* Structure describing the image type XBM. */
6218 static struct image_type xbm_type =
6220 &Qxbm,
6221 xbm_image_p,
6222 xbm_load,
6223 x_clear_image,
6224 NULL
6227 /* Tokens returned from xbm_scan. */
6229 enum xbm_token
6231 XBM_TK_IDENT = 256,
6232 XBM_TK_NUMBER
6236 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6237 A valid specification is a list starting with the symbol `image'
6238 The rest of the list is a property list which must contain an
6239 entry `:type xbm..
6241 If the specification specifies a file to load, it must contain
6242 an entry `:file FILENAME' where FILENAME is a string.
6244 If the specification is for a bitmap loaded from memory it must
6245 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6246 WIDTH and HEIGHT are integers > 0. DATA may be:
6248 1. a string large enough to hold the bitmap data, i.e. it must
6249 have a size >= (WIDTH + 7) / 8 * HEIGHT
6251 2. a bool-vector of size >= WIDTH * HEIGHT
6253 3. a vector of strings or bool-vectors, one for each line of the
6254 bitmap.
6256 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6257 may not be specified in this case because they are defined in the
6258 XBM file.
6260 Both the file and data forms may contain the additional entries
6261 `:background COLOR' and `:foreground COLOR'. If not present,
6262 foreground and background of the frame on which the image is
6263 displayed is used. */
6265 static int
6266 xbm_image_p (object)
6267 Lisp_Object object;
6269 struct image_keyword kw[XBM_LAST];
6271 bcopy (xbm_format, kw, sizeof kw);
6272 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6273 return 0;
6275 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6277 if (kw[XBM_FILE].count)
6279 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6280 return 0;
6282 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6284 /* In-memory XBM file. */
6285 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6286 return 0;
6288 else
6290 Lisp_Object data;
6291 int width, height;
6293 /* Entries for `:width', `:height' and `:data' must be present. */
6294 if (!kw[XBM_WIDTH].count
6295 || !kw[XBM_HEIGHT].count
6296 || !kw[XBM_DATA].count)
6297 return 0;
6299 data = kw[XBM_DATA].value;
6300 width = XFASTINT (kw[XBM_WIDTH].value);
6301 height = XFASTINT (kw[XBM_HEIGHT].value);
6303 /* Check type of data, and width and height against contents of
6304 data. */
6305 if (VECTORP (data))
6307 int i;
6309 /* Number of elements of the vector must be >= height. */
6310 if (XVECTOR (data)->size < height)
6311 return 0;
6313 /* Each string or bool-vector in data must be large enough
6314 for one line of the image. */
6315 for (i = 0; i < height; ++i)
6317 Lisp_Object elt = XVECTOR (data)->contents[i];
6319 if (STRINGP (elt))
6321 if (XSTRING (elt)->size
6322 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6323 return 0;
6325 else if (BOOL_VECTOR_P (elt))
6327 if (XBOOL_VECTOR (elt)->size < width)
6328 return 0;
6330 else
6331 return 0;
6334 else if (STRINGP (data))
6336 if (XSTRING (data)->size
6337 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6338 return 0;
6340 else if (BOOL_VECTOR_P (data))
6342 if (XBOOL_VECTOR (data)->size < width * height)
6343 return 0;
6345 else
6346 return 0;
6349 return 1;
6353 /* Scan a bitmap file. FP is the stream to read from. Value is
6354 either an enumerator from enum xbm_token, or a character for a
6355 single-character token, or 0 at end of file. If scanning an
6356 identifier, store the lexeme of the identifier in SVAL. If
6357 scanning a number, store its value in *IVAL. */
6359 static int
6360 xbm_scan (s, end, sval, ival)
6361 char **s, *end;
6362 char *sval;
6363 int *ival;
6365 int c;
6367 loop:
6369 /* Skip white space. */
6370 while (*s < end && (c = *(*s)++, isspace (c)))
6373 if (*s >= end)
6374 c = 0;
6375 else if (isdigit (c))
6377 int value = 0, digit;
6379 if (c == '0' && *s < end)
6381 c = *(*s)++;
6382 if (c == 'x' || c == 'X')
6384 while (*s < end)
6386 c = *(*s)++;
6387 if (isdigit (c))
6388 digit = c - '0';
6389 else if (c >= 'a' && c <= 'f')
6390 digit = c - 'a' + 10;
6391 else if (c >= 'A' && c <= 'F')
6392 digit = c - 'A' + 10;
6393 else
6394 break;
6395 value = 16 * value + digit;
6398 else if (isdigit (c))
6400 value = c - '0';
6401 while (*s < end
6402 && (c = *(*s)++, isdigit (c)))
6403 value = 8 * value + c - '0';
6406 else
6408 value = c - '0';
6409 while (*s < end
6410 && (c = *(*s)++, isdigit (c)))
6411 value = 10 * value + c - '0';
6414 if (*s < end)
6415 *s = *s - 1;
6416 *ival = value;
6417 c = XBM_TK_NUMBER;
6419 else if (isalpha (c) || c == '_')
6421 *sval++ = c;
6422 while (*s < end
6423 && (c = *(*s)++, (isalnum (c) || c == '_')))
6424 *sval++ = c;
6425 *sval = 0;
6426 if (*s < end)
6427 *s = *s - 1;
6428 c = XBM_TK_IDENT;
6430 else if (c == '/' && **s == '*')
6432 /* C-style comment. */
6433 ++*s;
6434 while (**s && (**s != '*' || *(*s + 1) != '/'))
6435 ++*s;
6436 if (**s)
6438 *s += 2;
6439 goto loop;
6443 return c;
6447 /* Replacement for XReadBitmapFileData which isn't available under old
6448 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6449 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6450 the image. Return in *DATA the bitmap data allocated with xmalloc.
6451 Value is non-zero if successful. DATA null means just test if
6452 CONTENTS looks like an in-memory XBM file. */
6454 static int
6455 xbm_read_bitmap_data (contents, end, width, height, data)
6456 char *contents, *end;
6457 int *width, *height;
6458 unsigned char **data;
6460 char *s = contents;
6461 char buffer[BUFSIZ];
6462 int padding_p = 0;
6463 int v10 = 0;
6464 int bytes_per_line, i, nbytes;
6465 unsigned char *p;
6466 int value;
6467 int LA1;
6469 #define match() \
6470 LA1 = xbm_scan (&s, end, buffer, &value)
6472 #define expect(TOKEN) \
6473 if (LA1 != (TOKEN)) \
6474 goto failure; \
6475 else \
6476 match ()
6478 #define expect_ident(IDENT) \
6479 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6480 match (); \
6481 else \
6482 goto failure
6484 *width = *height = -1;
6485 if (data)
6486 *data = NULL;
6487 LA1 = xbm_scan (&s, end, buffer, &value);
6489 /* Parse defines for width, height and hot-spots. */
6490 while (LA1 == '#')
6492 match ();
6493 expect_ident ("define");
6494 expect (XBM_TK_IDENT);
6496 if (LA1 == XBM_TK_NUMBER);
6498 char *p = strrchr (buffer, '_');
6499 p = p ? p + 1 : buffer;
6500 if (strcmp (p, "width") == 0)
6501 *width = value;
6502 else if (strcmp (p, "height") == 0)
6503 *height = value;
6505 expect (XBM_TK_NUMBER);
6508 if (*width < 0 || *height < 0)
6509 goto failure;
6510 else if (data == NULL)
6511 goto success;
6513 /* Parse bits. Must start with `static'. */
6514 expect_ident ("static");
6515 if (LA1 == XBM_TK_IDENT)
6517 if (strcmp (buffer, "unsigned") == 0)
6519 match ();
6520 expect_ident ("char");
6522 else if (strcmp (buffer, "short") == 0)
6524 match ();
6525 v10 = 1;
6526 if (*width % 16 && *width % 16 < 9)
6527 padding_p = 1;
6529 else if (strcmp (buffer, "char") == 0)
6530 match ();
6531 else
6532 goto failure;
6534 else
6535 goto failure;
6537 expect (XBM_TK_IDENT);
6538 expect ('[');
6539 expect (']');
6540 expect ('=');
6541 expect ('{');
6543 bytes_per_line = (*width + 7) / 8 + padding_p;
6544 nbytes = bytes_per_line * *height;
6545 p = *data = (char *) xmalloc (nbytes);
6547 if (v10)
6549 for (i = 0; i < nbytes; i += 2)
6551 int val = value;
6552 expect (XBM_TK_NUMBER);
6554 *p++ = val;
6555 if (!padding_p || ((i + 2) % bytes_per_line))
6556 *p++ = value >> 8;
6558 if (LA1 == ',' || LA1 == '}')
6559 match ();
6560 else
6561 goto failure;
6564 else
6566 for (i = 0; i < nbytes; ++i)
6568 int val = value;
6569 expect (XBM_TK_NUMBER);
6571 *p++ = val;
6573 if (LA1 == ',' || LA1 == '}')
6574 match ();
6575 else
6576 goto failure;
6580 success:
6581 return 1;
6583 failure:
6585 if (data && *data)
6587 xfree (*data);
6588 *data = NULL;
6590 return 0;
6592 #undef match
6593 #undef expect
6594 #undef expect_ident
6598 /* Load XBM image IMG which will be displayed on frame F from buffer
6599 CONTENTS. END is the end of the buffer. Value is non-zero if
6600 successful. */
6602 static int
6603 xbm_load_image (f, img, contents, end)
6604 struct frame *f;
6605 struct image *img;
6606 char *contents, *end;
6608 int rc;
6609 unsigned char *data;
6610 int success_p = 0;
6612 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6613 if (rc)
6615 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6616 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6617 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6618 Lisp_Object value;
6620 xassert (img->width > 0 && img->height > 0);
6622 /* Get foreground and background colors, maybe allocate colors. */
6623 value = image_spec_value (img->spec, QCforeground, NULL);
6624 if (!NILP (value))
6625 foreground = x_alloc_image_color (f, img, value, foreground);
6627 value = image_spec_value (img->spec, QCbackground, NULL);
6628 if (!NILP (value))
6629 background = x_alloc_image_color (f, img, value, background);
6631 img->pixmap
6632 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6633 FRAME_X_WINDOW (f),
6634 data,
6635 img->width, img->height,
6636 foreground, background,
6637 depth);
6638 xfree (data);
6640 if (img->pixmap == None)
6642 x_clear_image (f, img);
6643 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6645 else
6646 success_p = 1;
6648 else
6649 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6651 return success_p;
6655 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6657 static int
6658 xbm_file_p (data)
6659 Lisp_Object data;
6661 int w, h;
6662 return (STRINGP (data)
6663 && xbm_read_bitmap_data (XSTRING (data)->data,
6664 (XSTRING (data)->data
6665 + STRING_BYTES (XSTRING (data))),
6666 &w, &h, NULL));
6670 /* Fill image IMG which is used on frame F with pixmap data. Value is
6671 non-zero if successful. */
6673 static int
6674 xbm_load (f, img)
6675 struct frame *f;
6676 struct image *img;
6678 int success_p = 0;
6679 Lisp_Object file_name;
6681 xassert (xbm_image_p (img->spec));
6683 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6684 file_name = image_spec_value (img->spec, QCfile, NULL);
6685 if (STRINGP (file_name))
6687 Lisp_Object file;
6688 char *contents;
6689 int size;
6690 struct gcpro gcpro1;
6692 file = x_find_image_file (file_name);
6693 GCPRO1 (file);
6694 if (!STRINGP (file))
6696 image_error ("Cannot find image file `%s'", file_name, Qnil);
6697 UNGCPRO;
6698 return 0;
6701 contents = slurp_file (XSTRING (file)->data, &size);
6702 if (contents == NULL)
6704 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6705 UNGCPRO;
6706 return 0;
6709 success_p = xbm_load_image (f, img, contents, contents + size);
6710 UNGCPRO;
6712 else
6714 struct image_keyword fmt[XBM_LAST];
6715 Lisp_Object data;
6716 unsigned char *bitmap_data;
6717 int depth;
6718 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6719 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6720 char *bits;
6721 int parsed_p, height, width;
6722 int in_memory_file_p = 0;
6724 /* See if data looks like an in-memory XBM file. */
6725 data = image_spec_value (img->spec, QCdata, NULL);
6726 in_memory_file_p = xbm_file_p (data);
6728 /* Parse the image specification. */
6729 bcopy (xbm_format, fmt, sizeof fmt);
6730 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6731 xassert (parsed_p);
6733 /* Get specified width, and height. */
6734 if (!in_memory_file_p)
6736 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6737 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6738 xassert (img->width > 0 && img->height > 0);
6741 /* Get foreground and background colors, maybe allocate colors. */
6742 if (fmt[XBM_FOREGROUND].count)
6743 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6744 foreground);
6745 if (fmt[XBM_BACKGROUND].count)
6746 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6747 background);
6749 if (in_memory_file_p)
6750 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6751 (XSTRING (data)->data
6752 + STRING_BYTES (XSTRING (data))));
6753 else
6755 if (VECTORP (data))
6757 int i;
6758 char *p;
6759 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6761 p = bits = (char *) alloca (nbytes * img->height);
6762 for (i = 0; i < img->height; ++i, p += nbytes)
6764 Lisp_Object line = XVECTOR (data)->contents[i];
6765 if (STRINGP (line))
6766 bcopy (XSTRING (line)->data, p, nbytes);
6767 else
6768 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6771 else if (STRINGP (data))
6772 bits = XSTRING (data)->data;
6773 else
6774 bits = XBOOL_VECTOR (data)->data;
6776 /* Create the pixmap. */
6777 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6778 img->pixmap
6779 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6780 FRAME_X_WINDOW (f),
6781 bits,
6782 img->width, img->height,
6783 foreground, background,
6784 depth);
6785 if (img->pixmap)
6786 success_p = 1;
6787 else
6789 image_error ("Unable to create pixmap for XBM image `%s'",
6790 img->spec, Qnil);
6791 x_clear_image (f, img);
6796 return success_p;
6801 /***********************************************************************
6802 XPM images
6803 ***********************************************************************/
6805 #if HAVE_XPM
6807 static int xpm_image_p P_ ((Lisp_Object object));
6808 static int xpm_load P_ ((struct frame *f, struct image *img));
6809 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6811 #include "X11/xpm.h"
6813 /* The symbol `xpm' identifying XPM-format images. */
6815 Lisp_Object Qxpm;
6817 /* Indices of image specification fields in xpm_format, below. */
6819 enum xpm_keyword_index
6821 XPM_TYPE,
6822 XPM_FILE,
6823 XPM_DATA,
6824 XPM_ASCENT,
6825 XPM_MARGIN,
6826 XPM_RELIEF,
6827 XPM_ALGORITHM,
6828 XPM_HEURISTIC_MASK,
6829 XPM_MASK,
6830 XPM_COLOR_SYMBOLS,
6831 XPM_LAST
6834 /* Vector of image_keyword structures describing the format
6835 of valid XPM image specifications. */
6837 static struct image_keyword xpm_format[XPM_LAST] =
6839 {":type", IMAGE_SYMBOL_VALUE, 1},
6840 {":file", IMAGE_STRING_VALUE, 0},
6841 {":data", IMAGE_STRING_VALUE, 0},
6842 {":ascent", IMAGE_ASCENT_VALUE, 0},
6843 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6844 {":relief", IMAGE_INTEGER_VALUE, 0},
6845 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6846 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6847 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6848 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6851 /* Structure describing the image type XBM. */
6853 static struct image_type xpm_type =
6855 &Qxpm,
6856 xpm_image_p,
6857 xpm_load,
6858 x_clear_image,
6859 NULL
6863 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6864 functions for allocating image colors. Our own functions handle
6865 color allocation failures more gracefully than the ones on the XPM
6866 lib. */
6868 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6869 #define ALLOC_XPM_COLORS
6870 #endif
6872 #ifdef ALLOC_XPM_COLORS
6874 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
6875 static void xpm_free_color_cache P_ ((void));
6876 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
6877 static int xpm_color_bucket P_ ((char *));
6878 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
6879 XColor *, int));
6881 /* An entry in a hash table used to cache color definitions of named
6882 colors. This cache is necessary to speed up XPM image loading in
6883 case we do color allocations ourselves. Without it, we would need
6884 a call to XParseColor per pixel in the image. */
6886 struct xpm_cached_color
6888 /* Next in collision chain. */
6889 struct xpm_cached_color *next;
6891 /* Color definition (RGB and pixel color). */
6892 XColor color;
6894 /* Color name. */
6895 char name[1];
6898 /* The hash table used for the color cache, and its bucket vector
6899 size. */
6901 #define XPM_COLOR_CACHE_BUCKETS 1001
6902 struct xpm_cached_color **xpm_color_cache;
6904 /* Initialize the color cache. */
6906 static void
6907 xpm_init_color_cache (f, attrs)
6908 struct frame *f;
6909 XpmAttributes *attrs;
6911 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
6912 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
6913 memset (xpm_color_cache, 0, nbytes);
6914 init_color_table ();
6916 if (attrs->valuemask & XpmColorSymbols)
6918 int i;
6919 XColor color;
6921 for (i = 0; i < attrs->numsymbols; ++i)
6922 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6923 attrs->colorsymbols[i].value, &color))
6925 color.pixel = lookup_rgb_color (f, color.red, color.green,
6926 color.blue);
6927 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
6933 /* Free the color cache. */
6935 static void
6936 xpm_free_color_cache ()
6938 struct xpm_cached_color *p, *next;
6939 int i;
6941 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
6942 for (p = xpm_color_cache[i]; p; p = next)
6944 next = p->next;
6945 xfree (p);
6948 xfree (xpm_color_cache);
6949 xpm_color_cache = NULL;
6950 free_color_table ();
6954 /* Return the bucket index for color named COLOR_NAME in the color
6955 cache. */
6957 static int
6958 xpm_color_bucket (color_name)
6959 char *color_name;
6961 unsigned h = 0;
6962 char *s;
6964 for (s = color_name; *s; ++s)
6965 h = (h << 2) ^ *s;
6966 return h %= XPM_COLOR_CACHE_BUCKETS;
6970 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6971 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6972 entry added. */
6974 static struct xpm_cached_color *
6975 xpm_cache_color (f, color_name, color, bucket)
6976 struct frame *f;
6977 char *color_name;
6978 XColor *color;
6979 int bucket;
6981 size_t nbytes;
6982 struct xpm_cached_color *p;
6984 if (bucket < 0)
6985 bucket = xpm_color_bucket (color_name);
6987 nbytes = sizeof *p + strlen (color_name);
6988 p = (struct xpm_cached_color *) xmalloc (nbytes);
6989 strcpy (p->name, color_name);
6990 p->color = *color;
6991 p->next = xpm_color_cache[bucket];
6992 xpm_color_cache[bucket] = p;
6993 return p;
6997 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6998 return the cached definition in *COLOR. Otherwise, make a new
6999 entry in the cache and allocate the color. Value is zero if color
7000 allocation failed. */
7002 static int
7003 xpm_lookup_color (f, color_name, color)
7004 struct frame *f;
7005 char *color_name;
7006 XColor *color;
7008 struct xpm_cached_color *p;
7009 int h = xpm_color_bucket (color_name);
7011 for (p = xpm_color_cache[h]; p; p = p->next)
7012 if (strcmp (p->name, color_name) == 0)
7013 break;
7015 if (p != NULL)
7016 *color = p->color;
7017 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7018 color_name, color))
7020 color->pixel = lookup_rgb_color (f, color->red, color->green,
7021 color->blue);
7022 p = xpm_cache_color (f, color_name, color, h);
7025 return p != NULL;
7029 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7030 CLOSURE is a pointer to the frame on which we allocate the
7031 color. Return in *COLOR the allocated color. Value is non-zero
7032 if successful. */
7034 static int
7035 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7036 Display *dpy;
7037 Colormap cmap;
7038 char *color_name;
7039 XColor *color;
7040 void *closure;
7042 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7046 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7047 is a pointer to the frame on which we allocate the color. Value is
7048 non-zero if successful. */
7050 static int
7051 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7052 Display *dpy;
7053 Colormap cmap;
7054 Pixel *pixels;
7055 int npixels;
7056 void *closure;
7058 return 1;
7061 #endif /* ALLOC_XPM_COLORS */
7064 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7065 for XPM images. Such a list must consist of conses whose car and
7066 cdr are strings. */
7068 static int
7069 xpm_valid_color_symbols_p (color_symbols)
7070 Lisp_Object color_symbols;
7072 while (CONSP (color_symbols))
7074 Lisp_Object sym = XCAR (color_symbols);
7075 if (!CONSP (sym)
7076 || !STRINGP (XCAR (sym))
7077 || !STRINGP (XCDR (sym)))
7078 break;
7079 color_symbols = XCDR (color_symbols);
7082 return NILP (color_symbols);
7086 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7088 static int
7089 xpm_image_p (object)
7090 Lisp_Object object;
7092 struct image_keyword fmt[XPM_LAST];
7093 bcopy (xpm_format, fmt, sizeof fmt);
7094 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7095 /* Either `:file' or `:data' must be present. */
7096 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7097 /* Either no `:color-symbols' or it's a list of conses
7098 whose car and cdr are strings. */
7099 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7100 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7104 /* Load image IMG which will be displayed on frame F. Value is
7105 non-zero if successful. */
7107 static int
7108 xpm_load (f, img)
7109 struct frame *f;
7110 struct image *img;
7112 int rc, i;
7113 XpmAttributes attrs;
7114 Lisp_Object specified_file, color_symbols;
7116 /* Configure the XPM lib. Use the visual of frame F. Allocate
7117 close colors. Return colors allocated. */
7118 bzero (&attrs, sizeof attrs);
7119 attrs.visual = FRAME_X_VISUAL (f);
7120 attrs.colormap = FRAME_X_COLORMAP (f);
7121 attrs.valuemask |= XpmVisual;
7122 attrs.valuemask |= XpmColormap;
7124 #ifdef ALLOC_XPM_COLORS
7125 /* Allocate colors with our own functions which handle
7126 failing color allocation more gracefully. */
7127 attrs.color_closure = f;
7128 attrs.alloc_color = xpm_alloc_color;
7129 attrs.free_colors = xpm_free_colors;
7130 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7131 #else /* not ALLOC_XPM_COLORS */
7132 /* Let the XPM lib allocate colors. */
7133 attrs.valuemask |= XpmReturnAllocPixels;
7134 #ifdef XpmAllocCloseColors
7135 attrs.alloc_close_colors = 1;
7136 attrs.valuemask |= XpmAllocCloseColors;
7137 #else /* not XpmAllocCloseColors */
7138 attrs.closeness = 600;
7139 attrs.valuemask |= XpmCloseness;
7140 #endif /* not XpmAllocCloseColors */
7141 #endif /* ALLOC_XPM_COLORS */
7143 /* If image specification contains symbolic color definitions, add
7144 these to `attrs'. */
7145 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7146 if (CONSP (color_symbols))
7148 Lisp_Object tail;
7149 XpmColorSymbol *xpm_syms;
7150 int i, size;
7152 attrs.valuemask |= XpmColorSymbols;
7154 /* Count number of symbols. */
7155 attrs.numsymbols = 0;
7156 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7157 ++attrs.numsymbols;
7159 /* Allocate an XpmColorSymbol array. */
7160 size = attrs.numsymbols * sizeof *xpm_syms;
7161 xpm_syms = (XpmColorSymbol *) alloca (size);
7162 bzero (xpm_syms, size);
7163 attrs.colorsymbols = xpm_syms;
7165 /* Fill the color symbol array. */
7166 for (tail = color_symbols, i = 0;
7167 CONSP (tail);
7168 ++i, tail = XCDR (tail))
7170 Lisp_Object name = XCAR (XCAR (tail));
7171 Lisp_Object color = XCDR (XCAR (tail));
7172 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7173 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7174 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7175 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7179 /* Create a pixmap for the image, either from a file, or from a
7180 string buffer containing data in the same format as an XPM file. */
7181 #ifdef ALLOC_XPM_COLORS
7182 xpm_init_color_cache (f, &attrs);
7183 #endif
7185 specified_file = image_spec_value (img->spec, QCfile, NULL);
7186 if (STRINGP (specified_file))
7188 Lisp_Object file = x_find_image_file (specified_file);
7189 if (!STRINGP (file))
7191 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7192 return 0;
7195 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7196 XSTRING (file)->data, &img->pixmap, &img->mask,
7197 &attrs);
7199 else
7201 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7202 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7203 XSTRING (buffer)->data,
7204 &img->pixmap, &img->mask,
7205 &attrs);
7208 if (rc == XpmSuccess)
7210 #ifdef ALLOC_XPM_COLORS
7211 img->colors = colors_in_color_table (&img->ncolors);
7212 #else /* not ALLOC_XPM_COLORS */
7213 img->ncolors = attrs.nalloc_pixels;
7214 img->colors = (unsigned long *) xmalloc (img->ncolors
7215 * sizeof *img->colors);
7216 for (i = 0; i < attrs.nalloc_pixels; ++i)
7218 img->colors[i] = attrs.alloc_pixels[i];
7219 #ifdef DEBUG_X_COLORS
7220 register_color (img->colors[i]);
7221 #endif
7223 #endif /* not ALLOC_XPM_COLORS */
7225 img->width = attrs.width;
7226 img->height = attrs.height;
7227 xassert (img->width > 0 && img->height > 0);
7229 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7230 XpmFreeAttributes (&attrs);
7232 else
7234 switch (rc)
7236 case XpmOpenFailed:
7237 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7238 break;
7240 case XpmFileInvalid:
7241 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7242 break;
7244 case XpmNoMemory:
7245 image_error ("Out of memory (%s)", img->spec, Qnil);
7246 break;
7248 case XpmColorFailed:
7249 image_error ("Color allocation error (%s)", img->spec, Qnil);
7250 break;
7252 default:
7253 image_error ("Unknown error (%s)", img->spec, Qnil);
7254 break;
7258 #ifdef ALLOC_XPM_COLORS
7259 xpm_free_color_cache ();
7260 #endif
7261 return rc == XpmSuccess;
7264 #endif /* HAVE_XPM != 0 */
7267 /***********************************************************************
7268 Color table
7269 ***********************************************************************/
7271 /* An entry in the color table mapping an RGB color to a pixel color. */
7273 struct ct_color
7275 int r, g, b;
7276 unsigned long pixel;
7278 /* Next in color table collision list. */
7279 struct ct_color *next;
7282 /* The bucket vector size to use. Must be prime. */
7284 #define CT_SIZE 101
7286 /* Value is a hash of the RGB color given by R, G, and B. */
7288 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7290 /* The color hash table. */
7292 struct ct_color **ct_table;
7294 /* Number of entries in the color table. */
7296 int ct_colors_allocated;
7298 /* Initialize the color table. */
7300 static void
7301 init_color_table ()
7303 int size = CT_SIZE * sizeof (*ct_table);
7304 ct_table = (struct ct_color **) xmalloc (size);
7305 bzero (ct_table, size);
7306 ct_colors_allocated = 0;
7310 /* Free memory associated with the color table. */
7312 static void
7313 free_color_table ()
7315 int i;
7316 struct ct_color *p, *next;
7318 for (i = 0; i < CT_SIZE; ++i)
7319 for (p = ct_table[i]; p; p = next)
7321 next = p->next;
7322 xfree (p);
7325 xfree (ct_table);
7326 ct_table = NULL;
7330 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7331 entry for that color already is in the color table, return the
7332 pixel color of that entry. Otherwise, allocate a new color for R,
7333 G, B, and make an entry in the color table. */
7335 static unsigned long
7336 lookup_rgb_color (f, r, g, b)
7337 struct frame *f;
7338 int r, g, b;
7340 unsigned hash = CT_HASH_RGB (r, g, b);
7341 int i = hash % CT_SIZE;
7342 struct ct_color *p;
7344 for (p = ct_table[i]; p; p = p->next)
7345 if (p->r == r && p->g == g && p->b == b)
7346 break;
7348 if (p == NULL)
7350 XColor color;
7351 Colormap cmap;
7352 int rc;
7354 color.red = r;
7355 color.green = g;
7356 color.blue = b;
7358 cmap = FRAME_X_COLORMAP (f);
7359 rc = x_alloc_nearest_color (f, cmap, &color);
7361 if (rc)
7363 ++ct_colors_allocated;
7365 p = (struct ct_color *) xmalloc (sizeof *p);
7366 p->r = r;
7367 p->g = g;
7368 p->b = b;
7369 p->pixel = color.pixel;
7370 p->next = ct_table[i];
7371 ct_table[i] = p;
7373 else
7374 return FRAME_FOREGROUND_PIXEL (f);
7377 return p->pixel;
7381 /* Look up pixel color PIXEL which is used on frame F in the color
7382 table. If not already present, allocate it. Value is PIXEL. */
7384 static unsigned long
7385 lookup_pixel_color (f, pixel)
7386 struct frame *f;
7387 unsigned long pixel;
7389 int i = pixel % CT_SIZE;
7390 struct ct_color *p;
7392 for (p = ct_table[i]; p; p = p->next)
7393 if (p->pixel == pixel)
7394 break;
7396 if (p == NULL)
7398 XColor color;
7399 Colormap cmap;
7400 int rc;
7402 cmap = FRAME_X_COLORMAP (f);
7403 color.pixel = pixel;
7404 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
7405 rc = x_alloc_nearest_color (f, cmap, &color);
7407 if (rc)
7409 ++ct_colors_allocated;
7411 p = (struct ct_color *) xmalloc (sizeof *p);
7412 p->r = color.red;
7413 p->g = color.green;
7414 p->b = color.blue;
7415 p->pixel = pixel;
7416 p->next = ct_table[i];
7417 ct_table[i] = p;
7419 else
7420 return FRAME_FOREGROUND_PIXEL (f);
7423 return p->pixel;
7427 /* Value is a vector of all pixel colors contained in the color table,
7428 allocated via xmalloc. Set *N to the number of colors. */
7430 static unsigned long *
7431 colors_in_color_table (n)
7432 int *n;
7434 int i, j;
7435 struct ct_color *p;
7436 unsigned long *colors;
7438 if (ct_colors_allocated == 0)
7440 *n = 0;
7441 colors = NULL;
7443 else
7445 colors = (unsigned long *) xmalloc (ct_colors_allocated
7446 * sizeof *colors);
7447 *n = ct_colors_allocated;
7449 for (i = j = 0; i < CT_SIZE; ++i)
7450 for (p = ct_table[i]; p; p = p->next)
7451 colors[j++] = p->pixel;
7454 return colors;
7459 /***********************************************************************
7460 Algorithms
7461 ***********************************************************************/
7463 static void x_laplace_write_row P_ ((struct frame *, long *,
7464 int, XImage *, int));
7465 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7466 XColor *, int, XImage *, int));
7467 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7468 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7469 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7471 /* Non-zero means draw a cross on images having `:algorithm
7472 disabled'. */
7474 int cross_disabled_images;
7476 /* Edge detection matrices for different edge-detection
7477 strategies. */
7479 static int emboss_matrix[9] = {
7480 /* x - 1 x x + 1 */
7481 2, -1, 0, /* y - 1 */
7482 -1, 0, 1, /* y */
7483 0, 1, -2 /* y + 1 */
7486 static int laplace_matrix[9] = {
7487 /* x - 1 x x + 1 */
7488 1, 0, 0, /* y - 1 */
7489 0, 0, 0, /* y */
7490 0, 0, -1 /* y + 1 */
7493 /* Value is the intensity of the color whose red/green/blue values
7494 are R, G, and B. */
7496 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7499 /* On frame F, return an array of XColor structures describing image
7500 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7501 non-zero means also fill the red/green/blue members of the XColor
7502 structures. Value is a pointer to the array of XColors structures,
7503 allocated with xmalloc; it must be freed by the caller. */
7505 static XColor *
7506 x_to_xcolors (f, img, rgb_p)
7507 struct frame *f;
7508 struct image *img;
7509 int rgb_p;
7511 int x, y;
7512 XColor *colors, *p;
7513 XImage *ximg;
7515 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7517 /* Get the X image IMG->pixmap. */
7518 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7519 0, 0, img->width, img->height, ~0, ZPixmap);
7521 /* Fill the `pixel' members of the XColor array. I wished there
7522 were an easy and portable way to circumvent XGetPixel. */
7523 p = colors;
7524 for (y = 0; y < img->height; ++y)
7526 XColor *row = p;
7528 for (x = 0; x < img->width; ++x, ++p)
7529 p->pixel = XGetPixel (ximg, x, y);
7531 if (rgb_p)
7532 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7533 row, img->width);
7536 XDestroyImage (ximg);
7537 return colors;
7541 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7542 RGB members are set. F is the frame on which this all happens.
7543 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7545 static void
7546 x_from_xcolors (f, img, colors)
7547 struct frame *f;
7548 struct image *img;
7549 XColor *colors;
7551 int x, y;
7552 XImage *oimg;
7553 Pixmap pixmap;
7554 XColor *p;
7556 init_color_table ();
7558 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7559 &oimg, &pixmap);
7560 p = colors;
7561 for (y = 0; y < img->height; ++y)
7562 for (x = 0; x < img->width; ++x, ++p)
7564 unsigned long pixel;
7565 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7566 XPutPixel (oimg, x, y, pixel);
7569 xfree (colors);
7570 x_clear_image_1 (f, img, 1, 0, 1);
7572 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7573 x_destroy_x_image (oimg);
7574 img->pixmap = pixmap;
7575 img->colors = colors_in_color_table (&img->ncolors);
7576 free_color_table ();
7580 /* On frame F, perform edge-detection on image IMG.
7582 MATRIX is a nine-element array specifying the transformation
7583 matrix. See emboss_matrix for an example.
7585 COLOR_ADJUST is a color adjustment added to each pixel of the
7586 outgoing image. */
7588 static void
7589 x_detect_edges (f, img, matrix, color_adjust)
7590 struct frame *f;
7591 struct image *img;
7592 int matrix[9], color_adjust;
7594 XColor *colors = x_to_xcolors (f, img, 1);
7595 XColor *new, *p;
7596 int x, y, i, sum;
7598 for (i = sum = 0; i < 9; ++i)
7599 sum += abs (matrix[i]);
7601 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7603 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
7605 for (y = 0; y < img->height; ++y)
7607 p = COLOR (new, 0, y);
7608 p->red = p->green = p->blue = 0xffff/2;
7609 p = COLOR (new, img->width - 1, y);
7610 p->red = p->green = p->blue = 0xffff/2;
7613 for (x = 1; x < img->width - 1; ++x)
7615 p = COLOR (new, x, 0);
7616 p->red = p->green = p->blue = 0xffff/2;
7617 p = COLOR (new, x, img->height - 1);
7618 p->red = p->green = p->blue = 0xffff/2;
7621 for (y = 1; y < img->height - 1; ++y)
7623 p = COLOR (new, 1, y);
7625 for (x = 1; x < img->width - 1; ++x, ++p)
7627 int r, g, b, y1, x1;
7629 r = g = b = i = 0;
7630 for (y1 = y - 1; y1 < y + 2; ++y1)
7631 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7632 if (matrix[i])
7634 XColor *t = COLOR (colors, x1, y1);
7635 r += matrix[i] * t->red;
7636 g += matrix[i] * t->green;
7637 b += matrix[i] * t->blue;
7640 r = (r / sum + color_adjust) & 0xffff;
7641 g = (g / sum + color_adjust) & 0xffff;
7642 b = (b / sum + color_adjust) & 0xffff;
7643 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7647 xfree (colors);
7648 x_from_xcolors (f, img, new);
7650 #undef COLOR
7654 /* Perform the pre-defined `emboss' edge-detection on image IMG
7655 on frame F. */
7657 static void
7658 x_emboss (f, img)
7659 struct frame *f;
7660 struct image *img;
7662 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7666 /* Perform the pre-defined `laplace' edge-detection on image IMG
7667 on frame F. */
7669 static void
7670 x_laplace (f, img)
7671 struct frame *f;
7672 struct image *img;
7674 x_detect_edges (f, img, laplace_matrix, 45000);
7678 /* Perform edge-detection on image IMG on frame F, with specified
7679 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7681 MATRIX must be either
7683 - a list of at least 9 numbers in row-major form
7684 - a vector of at least 9 numbers
7686 COLOR_ADJUST nil means use a default; otherwise it must be a
7687 number. */
7689 static void
7690 x_edge_detection (f, img, matrix, color_adjust)
7691 struct frame *f;
7692 struct image *img;
7693 Lisp_Object matrix, color_adjust;
7695 int i = 0;
7696 int trans[9];
7698 if (CONSP (matrix))
7700 for (i = 0;
7701 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7702 ++i, matrix = XCDR (matrix))
7703 trans[i] = XFLOATINT (XCAR (matrix));
7705 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7707 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7708 trans[i] = XFLOATINT (AREF (matrix, i));
7711 if (NILP (color_adjust))
7712 color_adjust = make_number (0xffff / 2);
7714 if (i == 9 && NUMBERP (color_adjust))
7715 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7719 /* Transform image IMG on frame F so that it looks disabled. */
7721 static void
7722 x_disable_image (f, img)
7723 struct frame *f;
7724 struct image *img;
7726 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7728 if (dpyinfo->n_planes >= 2)
7730 /* Color (or grayscale). Convert to gray, and equalize. Just
7731 drawing such images with a stipple can look very odd, so
7732 we're using this method instead. */
7733 XColor *colors = x_to_xcolors (f, img, 1);
7734 XColor *p, *end;
7735 const int h = 15000;
7736 const int l = 30000;
7738 for (p = colors, end = colors + img->width * img->height;
7739 p < end;
7740 ++p)
7742 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7743 int i2 = (0xffff - h - l) * i / 0xffff + l;
7744 p->red = p->green = p->blue = i2;
7747 x_from_xcolors (f, img, colors);
7750 /* Draw a cross over the disabled image, if we must or if we
7751 should. */
7752 if (dpyinfo->n_planes < 2 || cross_disabled_images)
7754 Display *dpy = FRAME_X_DISPLAY (f);
7755 GC gc;
7757 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
7758 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
7759 XDrawLine (dpy, img->pixmap, gc, 0, 0,
7760 img->width - 1, img->height - 1);
7761 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
7762 img->width - 1, 0);
7763 XFreeGC (dpy, gc);
7765 if (img->mask)
7767 gc = XCreateGC (dpy, img->mask, 0, NULL);
7768 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
7769 XDrawLine (dpy, img->mask, gc, 0, 0,
7770 img->width - 1, img->height - 1);
7771 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
7772 img->width - 1, 0);
7773 XFreeGC (dpy, gc);
7779 /* Build a mask for image IMG which is used on frame F. FILE is the
7780 name of an image file, for error messages. HOW determines how to
7781 determine the background color of IMG. If it is a list '(R G B)',
7782 with R, G, and B being integers >= 0, take that as the color of the
7783 background. Otherwise, determine the background color of IMG
7784 heuristically. Value is non-zero if successful. */
7786 static int
7787 x_build_heuristic_mask (f, img, how)
7788 struct frame *f;
7789 struct image *img;
7790 Lisp_Object how;
7792 Display *dpy = FRAME_X_DISPLAY (f);
7793 XImage *ximg, *mask_img;
7794 int x, y, rc, look_at_corners_p;
7795 unsigned long bg = 0;
7797 if (img->mask)
7799 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
7800 img->mask = None;
7803 /* Create an image and pixmap serving as mask. */
7804 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7805 &mask_img, &img->mask);
7806 if (!rc)
7807 return 0;
7809 /* Get the X image of IMG->pixmap. */
7810 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7811 ~0, ZPixmap);
7813 /* Determine the background color of ximg. If HOW is `(R G B)'
7814 take that as color. Otherwise, try to determine the color
7815 heuristically. */
7816 look_at_corners_p = 1;
7818 if (CONSP (how))
7820 int rgb[3], i = 0;
7822 while (i < 3
7823 && CONSP (how)
7824 && NATNUMP (XCAR (how)))
7826 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7827 how = XCDR (how);
7830 if (i == 3 && NILP (how))
7832 char color_name[30];
7833 XColor exact, color;
7834 Colormap cmap;
7836 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7838 cmap = FRAME_X_COLORMAP (f);
7839 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
7841 bg = color.pixel;
7842 look_at_corners_p = 0;
7847 if (look_at_corners_p)
7849 unsigned long corners[4];
7850 int i, best_count;
7852 /* Get the colors at the corners of ximg. */
7853 corners[0] = XGetPixel (ximg, 0, 0);
7854 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7855 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7856 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7858 /* Choose the most frequently found color as background. */
7859 for (i = best_count = 0; i < 4; ++i)
7861 int j, n;
7863 for (j = n = 0; j < 4; ++j)
7864 if (corners[i] == corners[j])
7865 ++n;
7867 if (n > best_count)
7868 bg = corners[i], best_count = n;
7872 /* Set all bits in mask_img to 1 whose color in ximg is different
7873 from the background color bg. */
7874 for (y = 0; y < img->height; ++y)
7875 for (x = 0; x < img->width; ++x)
7876 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7878 /* Put mask_img into img->mask. */
7879 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7880 x_destroy_x_image (mask_img);
7881 XDestroyImage (ximg);
7883 return 1;
7888 /***********************************************************************
7889 PBM (mono, gray, color)
7890 ***********************************************************************/
7892 static int pbm_image_p P_ ((Lisp_Object object));
7893 static int pbm_load P_ ((struct frame *f, struct image *img));
7894 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7896 /* The symbol `pbm' identifying images of this type. */
7898 Lisp_Object Qpbm;
7900 /* Indices of image specification fields in gs_format, below. */
7902 enum pbm_keyword_index
7904 PBM_TYPE,
7905 PBM_FILE,
7906 PBM_DATA,
7907 PBM_ASCENT,
7908 PBM_MARGIN,
7909 PBM_RELIEF,
7910 PBM_ALGORITHM,
7911 PBM_HEURISTIC_MASK,
7912 PBM_MASK,
7913 PBM_LAST
7916 /* Vector of image_keyword structures describing the format
7917 of valid user-defined image specifications. */
7919 static struct image_keyword pbm_format[PBM_LAST] =
7921 {":type", IMAGE_SYMBOL_VALUE, 1},
7922 {":file", IMAGE_STRING_VALUE, 0},
7923 {":data", IMAGE_STRING_VALUE, 0},
7924 {":ascent", IMAGE_ASCENT_VALUE, 0},
7925 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7926 {":relief", IMAGE_INTEGER_VALUE, 0},
7927 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7928 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7929 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7932 /* Structure describing the image type `pbm'. */
7934 static struct image_type pbm_type =
7936 &Qpbm,
7937 pbm_image_p,
7938 pbm_load,
7939 x_clear_image,
7940 NULL
7944 /* Return non-zero if OBJECT is a valid PBM image specification. */
7946 static int
7947 pbm_image_p (object)
7948 Lisp_Object object;
7950 struct image_keyword fmt[PBM_LAST];
7952 bcopy (pbm_format, fmt, sizeof fmt);
7954 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7955 return 0;
7957 /* Must specify either :data or :file. */
7958 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7962 /* Scan a decimal number from *S and return it. Advance *S while
7963 reading the number. END is the end of the string. Value is -1 at
7964 end of input. */
7966 static int
7967 pbm_scan_number (s, end)
7968 unsigned char **s, *end;
7970 int c = 0, val = -1;
7972 while (*s < end)
7974 /* Skip white-space. */
7975 while (*s < end && (c = *(*s)++, isspace (c)))
7978 if (c == '#')
7980 /* Skip comment to end of line. */
7981 while (*s < end && (c = *(*s)++, c != '\n'))
7984 else if (isdigit (c))
7986 /* Read decimal number. */
7987 val = c - '0';
7988 while (*s < end && (c = *(*s)++, isdigit (c)))
7989 val = 10 * val + c - '0';
7990 break;
7992 else
7993 break;
7996 return val;
8000 /* Load PBM image IMG for use on frame F. */
8002 static int
8003 pbm_load (f, img)
8004 struct frame *f;
8005 struct image *img;
8007 int raw_p, x, y;
8008 int width, height, max_color_idx = 0;
8009 XImage *ximg;
8010 Lisp_Object file, specified_file;
8011 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8012 struct gcpro gcpro1;
8013 unsigned char *contents = NULL;
8014 unsigned char *end, *p;
8015 int size;
8017 specified_file = image_spec_value (img->spec, QCfile, NULL);
8018 file = Qnil;
8019 GCPRO1 (file);
8021 if (STRINGP (specified_file))
8023 file = x_find_image_file (specified_file);
8024 if (!STRINGP (file))
8026 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8027 UNGCPRO;
8028 return 0;
8031 contents = slurp_file (XSTRING (file)->data, &size);
8032 if (contents == NULL)
8034 image_error ("Error reading `%s'", file, Qnil);
8035 UNGCPRO;
8036 return 0;
8039 p = contents;
8040 end = contents + size;
8042 else
8044 Lisp_Object data;
8045 data = image_spec_value (img->spec, QCdata, NULL);
8046 p = XSTRING (data)->data;
8047 end = p + STRING_BYTES (XSTRING (data));
8050 /* Check magic number. */
8051 if (end - p < 2 || *p++ != 'P')
8053 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8054 error:
8055 xfree (contents);
8056 UNGCPRO;
8057 return 0;
8060 switch (*p++)
8062 case '1':
8063 raw_p = 0, type = PBM_MONO;
8064 break;
8066 case '2':
8067 raw_p = 0, type = PBM_GRAY;
8068 break;
8070 case '3':
8071 raw_p = 0, type = PBM_COLOR;
8072 break;
8074 case '4':
8075 raw_p = 1, type = PBM_MONO;
8076 break;
8078 case '5':
8079 raw_p = 1, type = PBM_GRAY;
8080 break;
8082 case '6':
8083 raw_p = 1, type = PBM_COLOR;
8084 break;
8086 default:
8087 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8088 goto error;
8091 /* Read width, height, maximum color-component. Characters
8092 starting with `#' up to the end of a line are ignored. */
8093 width = pbm_scan_number (&p, end);
8094 height = pbm_scan_number (&p, end);
8096 if (type != PBM_MONO)
8098 max_color_idx = pbm_scan_number (&p, end);
8099 if (raw_p && max_color_idx > 255)
8100 max_color_idx = 255;
8103 if (width < 0
8104 || height < 0
8105 || (type != PBM_MONO && max_color_idx < 0))
8106 goto error;
8108 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8109 &ximg, &img->pixmap))
8110 goto error;
8112 /* Initialize the color hash table. */
8113 init_color_table ();
8115 if (type == PBM_MONO)
8117 int c = 0, g;
8119 for (y = 0; y < height; ++y)
8120 for (x = 0; x < width; ++x)
8122 if (raw_p)
8124 if ((x & 7) == 0)
8125 c = *p++;
8126 g = c & 0x80;
8127 c <<= 1;
8129 else
8130 g = pbm_scan_number (&p, end);
8132 XPutPixel (ximg, x, y, (g
8133 ? FRAME_FOREGROUND_PIXEL (f)
8134 : FRAME_BACKGROUND_PIXEL (f)));
8137 else
8139 for (y = 0; y < height; ++y)
8140 for (x = 0; x < width; ++x)
8142 int r, g, b;
8144 if (type == PBM_GRAY)
8145 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8146 else if (raw_p)
8148 r = *p++;
8149 g = *p++;
8150 b = *p++;
8152 else
8154 r = pbm_scan_number (&p, end);
8155 g = pbm_scan_number (&p, end);
8156 b = pbm_scan_number (&p, end);
8159 if (r < 0 || g < 0 || b < 0)
8161 xfree (ximg->data);
8162 ximg->data = NULL;
8163 XDestroyImage (ximg);
8164 image_error ("Invalid pixel value in image `%s'",
8165 img->spec, Qnil);
8166 goto error;
8169 /* RGB values are now in the range 0..max_color_idx.
8170 Scale this to the range 0..0xffff supported by X. */
8171 r = (double) r * 65535 / max_color_idx;
8172 g = (double) g * 65535 / max_color_idx;
8173 b = (double) b * 65535 / max_color_idx;
8174 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8178 /* Store in IMG->colors the colors allocated for the image, and
8179 free the color table. */
8180 img->colors = colors_in_color_table (&img->ncolors);
8181 free_color_table ();
8183 /* Put the image into a pixmap. */
8184 x_put_x_image (f, ximg, img->pixmap, width, height);
8185 x_destroy_x_image (ximg);
8187 img->width = width;
8188 img->height = height;
8190 UNGCPRO;
8191 xfree (contents);
8192 return 1;
8197 /***********************************************************************
8199 ***********************************************************************/
8201 #if HAVE_PNG
8203 #include <png.h>
8205 /* Function prototypes. */
8207 static int png_image_p P_ ((Lisp_Object object));
8208 static int png_load P_ ((struct frame *f, struct image *img));
8210 /* The symbol `png' identifying images of this type. */
8212 Lisp_Object Qpng;
8214 /* Indices of image specification fields in png_format, below. */
8216 enum png_keyword_index
8218 PNG_TYPE,
8219 PNG_DATA,
8220 PNG_FILE,
8221 PNG_ASCENT,
8222 PNG_MARGIN,
8223 PNG_RELIEF,
8224 PNG_ALGORITHM,
8225 PNG_HEURISTIC_MASK,
8226 PNG_MASK,
8227 PNG_LAST
8230 /* Vector of image_keyword structures describing the format
8231 of valid user-defined image specifications. */
8233 static struct image_keyword png_format[PNG_LAST] =
8235 {":type", IMAGE_SYMBOL_VALUE, 1},
8236 {":data", IMAGE_STRING_VALUE, 0},
8237 {":file", IMAGE_STRING_VALUE, 0},
8238 {":ascent", IMAGE_ASCENT_VALUE, 0},
8239 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8240 {":relief", IMAGE_INTEGER_VALUE, 0},
8241 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8242 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8243 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8246 /* Structure describing the image type `png'. */
8248 static struct image_type png_type =
8250 &Qpng,
8251 png_image_p,
8252 png_load,
8253 x_clear_image,
8254 NULL
8258 /* Return non-zero if OBJECT is a valid PNG image specification. */
8260 static int
8261 png_image_p (object)
8262 Lisp_Object object;
8264 struct image_keyword fmt[PNG_LAST];
8265 bcopy (png_format, fmt, sizeof fmt);
8267 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8268 return 0;
8270 /* Must specify either the :data or :file keyword. */
8271 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8275 /* Error and warning handlers installed when the PNG library
8276 is initialized. */
8278 static void
8279 my_png_error (png_ptr, msg)
8280 png_struct *png_ptr;
8281 char *msg;
8283 xassert (png_ptr != NULL);
8284 image_error ("PNG error: %s", build_string (msg), Qnil);
8285 longjmp (png_ptr->jmpbuf, 1);
8289 static void
8290 my_png_warning (png_ptr, msg)
8291 png_struct *png_ptr;
8292 char *msg;
8294 xassert (png_ptr != NULL);
8295 image_error ("PNG warning: %s", build_string (msg), Qnil);
8298 /* Memory source for PNG decoding. */
8300 struct png_memory_storage
8302 unsigned char *bytes; /* The data */
8303 size_t len; /* How big is it? */
8304 int index; /* Where are we? */
8308 /* Function set as reader function when reading PNG image from memory.
8309 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8310 bytes from the input to DATA. */
8312 static void
8313 png_read_from_memory (png_ptr, data, length)
8314 png_structp png_ptr;
8315 png_bytep data;
8316 png_size_t length;
8318 struct png_memory_storage *tbr
8319 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8321 if (length > tbr->len - tbr->index)
8322 png_error (png_ptr, "Read error");
8324 bcopy (tbr->bytes + tbr->index, data, length);
8325 tbr->index = tbr->index + length;
8328 /* Load PNG image IMG for use on frame F. Value is non-zero if
8329 successful. */
8331 static int
8332 png_load (f, img)
8333 struct frame *f;
8334 struct image *img;
8336 Lisp_Object file, specified_file;
8337 Lisp_Object specified_data;
8338 int x, y, i;
8339 XImage *ximg, *mask_img = NULL;
8340 struct gcpro gcpro1;
8341 png_struct *png_ptr = NULL;
8342 png_info *info_ptr = NULL, *end_info = NULL;
8343 FILE *volatile fp = NULL;
8344 png_byte sig[8];
8345 png_byte * volatile pixels = NULL;
8346 png_byte ** volatile rows = NULL;
8347 png_uint_32 width, height;
8348 int bit_depth, color_type, interlace_type;
8349 png_byte channels;
8350 png_uint_32 row_bytes;
8351 int transparent_p;
8352 char *gamma_str;
8353 double screen_gamma, image_gamma;
8354 int intent;
8355 struct png_memory_storage tbr; /* Data to be read */
8357 /* Find out what file to load. */
8358 specified_file = image_spec_value (img->spec, QCfile, NULL);
8359 specified_data = image_spec_value (img->spec, QCdata, NULL);
8360 file = Qnil;
8361 GCPRO1 (file);
8363 if (NILP (specified_data))
8365 file = x_find_image_file (specified_file);
8366 if (!STRINGP (file))
8368 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8369 UNGCPRO;
8370 return 0;
8373 /* Open the image file. */
8374 fp = fopen (XSTRING (file)->data, "rb");
8375 if (!fp)
8377 image_error ("Cannot open image file `%s'", file, Qnil);
8378 UNGCPRO;
8379 fclose (fp);
8380 return 0;
8383 /* Check PNG signature. */
8384 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8385 || !png_check_sig (sig, sizeof sig))
8387 image_error ("Not a PNG file: `%s'", file, Qnil);
8388 UNGCPRO;
8389 fclose (fp);
8390 return 0;
8393 else
8395 /* Read from memory. */
8396 tbr.bytes = XSTRING (specified_data)->data;
8397 tbr.len = STRING_BYTES (XSTRING (specified_data));
8398 tbr.index = 0;
8400 /* Check PNG signature. */
8401 if (tbr.len < sizeof sig
8402 || !png_check_sig (tbr.bytes, sizeof sig))
8404 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8405 UNGCPRO;
8406 return 0;
8409 /* Need to skip past the signature. */
8410 tbr.bytes += sizeof (sig);
8413 /* Initialize read and info structs for PNG lib. */
8414 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8415 my_png_error, my_png_warning);
8416 if (!png_ptr)
8418 if (fp) fclose (fp);
8419 UNGCPRO;
8420 return 0;
8423 info_ptr = png_create_info_struct (png_ptr);
8424 if (!info_ptr)
8426 png_destroy_read_struct (&png_ptr, NULL, NULL);
8427 if (fp) fclose (fp);
8428 UNGCPRO;
8429 return 0;
8432 end_info = png_create_info_struct (png_ptr);
8433 if (!end_info)
8435 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8436 if (fp) fclose (fp);
8437 UNGCPRO;
8438 return 0;
8441 /* Set error jump-back. We come back here when the PNG library
8442 detects an error. */
8443 if (setjmp (png_ptr->jmpbuf))
8445 error:
8446 if (png_ptr)
8447 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8448 xfree (pixels);
8449 xfree (rows);
8450 if (fp) fclose (fp);
8451 UNGCPRO;
8452 return 0;
8455 /* Read image info. */
8456 if (!NILP (specified_data))
8457 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8458 else
8459 png_init_io (png_ptr, fp);
8461 png_set_sig_bytes (png_ptr, sizeof sig);
8462 png_read_info (png_ptr, info_ptr);
8463 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8464 &interlace_type, NULL, NULL);
8466 /* If image contains simply transparency data, we prefer to
8467 construct a clipping mask. */
8468 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8469 transparent_p = 1;
8470 else
8471 transparent_p = 0;
8473 /* This function is easier to write if we only have to handle
8474 one data format: RGB or RGBA with 8 bits per channel. Let's
8475 transform other formats into that format. */
8477 /* Strip more than 8 bits per channel. */
8478 if (bit_depth == 16)
8479 png_set_strip_16 (png_ptr);
8481 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8482 if available. */
8483 png_set_expand (png_ptr);
8485 /* Convert grayscale images to RGB. */
8486 if (color_type == PNG_COLOR_TYPE_GRAY
8487 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8488 png_set_gray_to_rgb (png_ptr);
8490 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8491 gamma_str = getenv ("SCREEN_GAMMA");
8492 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8494 /* Tell the PNG lib to handle gamma correction for us. */
8496 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8497 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8498 /* There is a special chunk in the image specifying the gamma. */
8499 png_set_sRGB (png_ptr, info_ptr, intent);
8500 else
8501 #endif
8502 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8503 /* Image contains gamma information. */
8504 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8505 else
8506 /* Use a default of 0.5 for the image gamma. */
8507 png_set_gamma (png_ptr, screen_gamma, 0.5);
8509 /* Handle alpha channel by combining the image with a background
8510 color. Do this only if a real alpha channel is supplied. For
8511 simple transparency, we prefer a clipping mask. */
8512 if (!transparent_p)
8514 png_color_16 *image_background;
8516 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8517 /* Image contains a background color with which to
8518 combine the image. */
8519 png_set_background (png_ptr, image_background,
8520 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8521 else
8523 /* Image does not contain a background color with which
8524 to combine the image data via an alpha channel. Use
8525 the frame's background instead. */
8526 XColor color;
8527 Colormap cmap;
8528 png_color_16 frame_background;
8530 cmap = FRAME_X_COLORMAP (f);
8531 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8532 XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
8534 bzero (&frame_background, sizeof frame_background);
8535 frame_background.red = color.red;
8536 frame_background.green = color.green;
8537 frame_background.blue = color.blue;
8539 png_set_background (png_ptr, &frame_background,
8540 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8544 /* Update info structure. */
8545 png_read_update_info (png_ptr, info_ptr);
8547 /* Get number of channels. Valid values are 1 for grayscale images
8548 and images with a palette, 2 for grayscale images with transparency
8549 information (alpha channel), 3 for RGB images, and 4 for RGB
8550 images with alpha channel, i.e. RGBA. If conversions above were
8551 sufficient we should only have 3 or 4 channels here. */
8552 channels = png_get_channels (png_ptr, info_ptr);
8553 xassert (channels == 3 || channels == 4);
8555 /* Number of bytes needed for one row of the image. */
8556 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8558 /* Allocate memory for the image. */
8559 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8560 rows = (png_byte **) xmalloc (height * sizeof *rows);
8561 for (i = 0; i < height; ++i)
8562 rows[i] = pixels + i * row_bytes;
8564 /* Read the entire image. */
8565 png_read_image (png_ptr, rows);
8566 png_read_end (png_ptr, info_ptr);
8567 if (fp)
8569 fclose (fp);
8570 fp = NULL;
8573 /* Create the X image and pixmap. */
8574 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8575 &img->pixmap))
8576 goto error;
8578 /* Create an image and pixmap serving as mask if the PNG image
8579 contains an alpha channel. */
8580 if (channels == 4
8581 && !transparent_p
8582 && !x_create_x_image_and_pixmap (f, width, height, 1,
8583 &mask_img, &img->mask))
8585 x_destroy_x_image (ximg);
8586 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8587 img->pixmap = None;
8588 goto error;
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)
8600 unsigned r, g, b;
8602 r = *p++ << 8;
8603 g = *p++ << 8;
8604 b = *p++ << 8;
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. */
8623 if (channels == 4)
8625 if (mask_img)
8626 XPutPixel (mask_img, x, y, *p > 0);
8627 ++p;
8632 /* Remember colors allocated for this image. */
8633 img->colors = colors_in_color_table (&img->ncolors);
8634 free_color_table ();
8636 /* Clean up. */
8637 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8638 xfree (rows);
8639 xfree (pixels);
8641 img->width = width;
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. */
8649 if (mask_img)
8651 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8652 x_destroy_x_image (mask_img);
8655 UNGCPRO;
8656 return 1;
8659 #endif /* HAVE_PNG != 0 */
8663 /***********************************************************************
8664 JPEG
8665 ***********************************************************************/
8667 #if HAVE_JPEG
8669 /* Work around a warning about HAVE_STDLIB_H being redefined in
8670 jconfig.h. */
8671 #ifdef HAVE_STDLIB_H
8672 #define HAVE_STDLIB_H_1
8673 #undef HAVE_STDLIB_H
8674 #endif /* HAVE_STLIB_H */
8676 #include <jpeglib.h>
8677 #include <jerror.h>
8678 #include <setjmp.h>
8680 #ifdef HAVE_STLIB_H_1
8681 #define HAVE_STDLIB_H 1
8682 #endif
8684 static int jpeg_image_p P_ ((Lisp_Object object));
8685 static int jpeg_load P_ ((struct frame *f, struct image *img));
8687 /* The symbol `jpeg' identifying images of this type. */
8689 Lisp_Object Qjpeg;
8691 /* Indices of image specification fields in gs_format, below. */
8693 enum jpeg_keyword_index
8695 JPEG_TYPE,
8696 JPEG_DATA,
8697 JPEG_FILE,
8698 JPEG_ASCENT,
8699 JPEG_MARGIN,
8700 JPEG_RELIEF,
8701 JPEG_ALGORITHM,
8702 JPEG_HEURISTIC_MASK,
8703 JPEG_MASK,
8704 JPEG_LAST
8707 /* Vector of image_keyword structures describing the format
8708 of valid user-defined image specifications. */
8710 static struct image_keyword jpeg_format[JPEG_LAST] =
8712 {":type", IMAGE_SYMBOL_VALUE, 1},
8713 {":data", IMAGE_STRING_VALUE, 0},
8714 {":file", IMAGE_STRING_VALUE, 0},
8715 {":ascent", IMAGE_ASCENT_VALUE, 0},
8716 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8717 {":relief", IMAGE_INTEGER_VALUE, 0},
8718 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8719 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8720 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8723 /* Structure describing the image type `jpeg'. */
8725 static struct image_type jpeg_type =
8727 &Qjpeg,
8728 jpeg_image_p,
8729 jpeg_load,
8730 x_clear_image,
8731 NULL
8735 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8737 static int
8738 jpeg_image_p (object)
8739 Lisp_Object object;
8741 struct image_keyword fmt[JPEG_LAST];
8743 bcopy (jpeg_format, fmt, sizeof fmt);
8745 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8746 return 0;
8748 /* Must specify either the :data or :file keyword. */
8749 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8753 struct my_jpeg_error_mgr
8755 struct jpeg_error_mgr pub;
8756 jmp_buf setjmp_buffer;
8760 static void
8761 my_error_exit (cinfo)
8762 j_common_ptr cinfo;
8764 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8765 longjmp (mgr->setjmp_buffer, 1);
8769 /* Init source method for JPEG data source manager. Called by
8770 jpeg_read_header() before any data is actually read. See
8771 libjpeg.doc from the JPEG lib distribution. */
8773 static void
8774 our_init_source (cinfo)
8775 j_decompress_ptr cinfo;
8780 /* Fill input buffer method for JPEG data source manager. Called
8781 whenever more data is needed. We read the whole image in one step,
8782 so this only adds a fake end of input marker at the end. */
8784 static boolean
8785 our_fill_input_buffer (cinfo)
8786 j_decompress_ptr cinfo;
8788 /* Insert a fake EOI marker. */
8789 struct jpeg_source_mgr *src = cinfo->src;
8790 static JOCTET buffer[2];
8792 buffer[0] = (JOCTET) 0xFF;
8793 buffer[1] = (JOCTET) JPEG_EOI;
8795 src->next_input_byte = buffer;
8796 src->bytes_in_buffer = 2;
8797 return TRUE;
8801 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8802 is the JPEG data source manager. */
8804 static void
8805 our_skip_input_data (cinfo, num_bytes)
8806 j_decompress_ptr cinfo;
8807 long num_bytes;
8809 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8811 if (src)
8813 if (num_bytes > src->bytes_in_buffer)
8814 ERREXIT (cinfo, JERR_INPUT_EOF);
8816 src->bytes_in_buffer -= num_bytes;
8817 src->next_input_byte += num_bytes;
8822 /* Method to terminate data source. Called by
8823 jpeg_finish_decompress() after all data has been processed. */
8825 static void
8826 our_term_source (cinfo)
8827 j_decompress_ptr cinfo;
8832 /* Set up the JPEG lib for reading an image from DATA which contains
8833 LEN bytes. CINFO is the decompression info structure created for
8834 reading the image. */
8836 static void
8837 jpeg_memory_src (cinfo, data, len)
8838 j_decompress_ptr cinfo;
8839 JOCTET *data;
8840 unsigned int len;
8842 struct jpeg_source_mgr *src;
8844 if (cinfo->src == NULL)
8846 /* First time for this JPEG object? */
8847 cinfo->src = (struct jpeg_source_mgr *)
8848 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8849 sizeof (struct jpeg_source_mgr));
8850 src = (struct jpeg_source_mgr *) cinfo->src;
8851 src->next_input_byte = data;
8854 src = (struct jpeg_source_mgr *) cinfo->src;
8855 src->init_source = our_init_source;
8856 src->fill_input_buffer = our_fill_input_buffer;
8857 src->skip_input_data = our_skip_input_data;
8858 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8859 src->term_source = our_term_source;
8860 src->bytes_in_buffer = len;
8861 src->next_input_byte = data;
8865 /* Load image IMG for use on frame F. Patterned after example.c
8866 from the JPEG lib. */
8868 static int
8869 jpeg_load (f, img)
8870 struct frame *f;
8871 struct image *img;
8873 struct jpeg_decompress_struct cinfo;
8874 struct my_jpeg_error_mgr mgr;
8875 Lisp_Object file, specified_file;
8876 Lisp_Object specified_data;
8877 FILE * volatile fp = NULL;
8878 JSAMPARRAY buffer;
8879 int row_stride, x, y;
8880 XImage *ximg = NULL;
8881 int rc;
8882 unsigned long *colors;
8883 int width, height;
8884 struct gcpro gcpro1;
8886 /* Open the JPEG file. */
8887 specified_file = image_spec_value (img->spec, QCfile, NULL);
8888 specified_data = image_spec_value (img->spec, QCdata, NULL);
8889 file = Qnil;
8890 GCPRO1 (file);
8892 if (NILP (specified_data))
8894 file = x_find_image_file (specified_file);
8895 if (!STRINGP (file))
8897 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8898 UNGCPRO;
8899 return 0;
8902 fp = fopen (XSTRING (file)->data, "r");
8903 if (fp == NULL)
8905 image_error ("Cannot open `%s'", file, Qnil);
8906 UNGCPRO;
8907 return 0;
8911 /* Customize libjpeg's error handling to call my_error_exit when an
8912 error is detected. This function will perform a longjmp. */
8913 cinfo.err = jpeg_std_error (&mgr.pub);
8914 mgr.pub.error_exit = my_error_exit;
8916 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8918 if (rc == 1)
8920 /* Called from my_error_exit. Display a JPEG error. */
8921 char buffer[JMSG_LENGTH_MAX];
8922 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8923 image_error ("Error reading JPEG image `%s': %s", img->spec,
8924 build_string (buffer));
8927 /* Close the input file and destroy the JPEG object. */
8928 if (fp)
8929 fclose ((FILE *) fp);
8930 jpeg_destroy_decompress (&cinfo);
8932 /* If we already have an XImage, free that. */
8933 x_destroy_x_image (ximg);
8935 /* Free pixmap and colors. */
8936 x_clear_image (f, img);
8938 UNGCPRO;
8939 return 0;
8942 /* Create the JPEG decompression object. Let it read from fp.
8943 Read the JPEG image header. */
8944 jpeg_create_decompress (&cinfo);
8946 if (NILP (specified_data))
8947 jpeg_stdio_src (&cinfo, (FILE *) fp);
8948 else
8949 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
8950 STRING_BYTES (XSTRING (specified_data)));
8952 jpeg_read_header (&cinfo, TRUE);
8954 /* Customize decompression so that color quantization will be used.
8955 Start decompression. */
8956 cinfo.quantize_colors = TRUE;
8957 jpeg_start_decompress (&cinfo);
8958 width = img->width = cinfo.output_width;
8959 height = img->height = cinfo.output_height;
8961 /* Create X image and pixmap. */
8962 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8963 longjmp (mgr.setjmp_buffer, 2);
8965 /* Allocate colors. When color quantization is used,
8966 cinfo.actual_number_of_colors has been set with the number of
8967 colors generated, and cinfo.colormap is a two-dimensional array
8968 of color indices in the range 0..cinfo.actual_number_of_colors.
8969 No more than 255 colors will be generated. */
8971 int i, ir, ig, ib;
8973 if (cinfo.out_color_components > 2)
8974 ir = 0, ig = 1, ib = 2;
8975 else if (cinfo.out_color_components > 1)
8976 ir = 0, ig = 1, ib = 0;
8977 else
8978 ir = 0, ig = 0, ib = 0;
8980 /* Use the color table mechanism because it handles colors that
8981 cannot be allocated nicely. Such colors will be replaced with
8982 a default color, and we don't have to care about which colors
8983 can be freed safely, and which can't. */
8984 init_color_table ();
8985 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8986 * sizeof *colors);
8988 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8990 /* Multiply RGB values with 255 because X expects RGB values
8991 in the range 0..0xffff. */
8992 int r = cinfo.colormap[ir][i] << 8;
8993 int g = cinfo.colormap[ig][i] << 8;
8994 int b = cinfo.colormap[ib][i] << 8;
8995 colors[i] = lookup_rgb_color (f, r, g, b);
8998 /* Remember those colors actually allocated. */
8999 img->colors = colors_in_color_table (&img->ncolors);
9000 free_color_table ();
9003 /* Read pixels. */
9004 row_stride = width * cinfo.output_components;
9005 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9006 row_stride, 1);
9007 for (y = 0; y < height; ++y)
9009 jpeg_read_scanlines (&cinfo, buffer, 1);
9010 for (x = 0; x < cinfo.output_width; ++x)
9011 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9014 /* Clean up. */
9015 jpeg_finish_decompress (&cinfo);
9016 jpeg_destroy_decompress (&cinfo);
9017 if (fp)
9018 fclose ((FILE *) fp);
9020 /* Put the image into the pixmap. */
9021 x_put_x_image (f, ximg, img->pixmap, width, height);
9022 x_destroy_x_image (ximg);
9023 UNGCPRO;
9024 return 1;
9027 #endif /* HAVE_JPEG */
9031 /***********************************************************************
9032 TIFF
9033 ***********************************************************************/
9035 #if HAVE_TIFF
9037 #include <tiffio.h>
9039 static int tiff_image_p P_ ((Lisp_Object object));
9040 static int tiff_load P_ ((struct frame *f, struct image *img));
9042 /* The symbol `tiff' identifying images of this type. */
9044 Lisp_Object Qtiff;
9046 /* Indices of image specification fields in tiff_format, below. */
9048 enum tiff_keyword_index
9050 TIFF_TYPE,
9051 TIFF_DATA,
9052 TIFF_FILE,
9053 TIFF_ASCENT,
9054 TIFF_MARGIN,
9055 TIFF_RELIEF,
9056 TIFF_ALGORITHM,
9057 TIFF_HEURISTIC_MASK,
9058 TIFF_MASK,
9059 TIFF_LAST
9062 /* Vector of image_keyword structures describing the format
9063 of valid user-defined image specifications. */
9065 static struct image_keyword tiff_format[TIFF_LAST] =
9067 {":type", IMAGE_SYMBOL_VALUE, 1},
9068 {":data", IMAGE_STRING_VALUE, 0},
9069 {":file", IMAGE_STRING_VALUE, 0},
9070 {":ascent", IMAGE_ASCENT_VALUE, 0},
9071 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9072 {":relief", IMAGE_INTEGER_VALUE, 0},
9073 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9074 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9075 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9078 /* Structure describing the image type `tiff'. */
9080 static struct image_type tiff_type =
9082 &Qtiff,
9083 tiff_image_p,
9084 tiff_load,
9085 x_clear_image,
9086 NULL
9090 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9092 static int
9093 tiff_image_p (object)
9094 Lisp_Object object;
9096 struct image_keyword fmt[TIFF_LAST];
9097 bcopy (tiff_format, fmt, sizeof fmt);
9099 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9100 return 0;
9102 /* Must specify either the :data or :file keyword. */
9103 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9107 /* Reading from a memory buffer for TIFF images Based on the PNG
9108 memory source, but we have to provide a lot of extra functions.
9109 Blah.
9111 We really only need to implement read and seek, but I am not
9112 convinced that the TIFF library is smart enough not to destroy
9113 itself if we only hand it the function pointers we need to
9114 override. */
9116 typedef struct
9118 unsigned char *bytes;
9119 size_t len;
9120 int index;
9122 tiff_memory_source;
9125 static size_t
9126 tiff_read_from_memory (data, buf, size)
9127 thandle_t data;
9128 tdata_t buf;
9129 tsize_t size;
9131 tiff_memory_source *src = (tiff_memory_source *) data;
9133 if (size > src->len - src->index)
9134 return (size_t) -1;
9135 bcopy (src->bytes + src->index, buf, size);
9136 src->index += size;
9137 return size;
9141 static size_t
9142 tiff_write_from_memory (data, buf, size)
9143 thandle_t data;
9144 tdata_t buf;
9145 tsize_t size;
9147 return (size_t) -1;
9151 static toff_t
9152 tiff_seek_in_memory (data, off, whence)
9153 thandle_t data;
9154 toff_t off;
9155 int whence;
9157 tiff_memory_source *src = (tiff_memory_source *) data;
9158 int idx;
9160 switch (whence)
9162 case SEEK_SET: /* Go from beginning of source. */
9163 idx = off;
9164 break;
9166 case SEEK_END: /* Go from end of source. */
9167 idx = src->len + off;
9168 break;
9170 case SEEK_CUR: /* Go from current position. */
9171 idx = src->index + off;
9172 break;
9174 default: /* Invalid `whence'. */
9175 return -1;
9178 if (idx > src->len || idx < 0)
9179 return -1;
9181 src->index = idx;
9182 return src->index;
9186 static int
9187 tiff_close_memory (data)
9188 thandle_t data;
9190 /* NOOP */
9191 return 0;
9195 static int
9196 tiff_mmap_memory (data, pbase, psize)
9197 thandle_t data;
9198 tdata_t *pbase;
9199 toff_t *psize;
9201 /* It is already _IN_ memory. */
9202 return 0;
9206 static void
9207 tiff_unmap_memory (data, base, size)
9208 thandle_t data;
9209 tdata_t base;
9210 toff_t size;
9212 /* We don't need to do this. */
9216 static toff_t
9217 tiff_size_of_memory (data)
9218 thandle_t data;
9220 return ((tiff_memory_source *) data)->len;
9224 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9225 successful. */
9227 static int
9228 tiff_load (f, img)
9229 struct frame *f;
9230 struct image *img;
9232 Lisp_Object file, specified_file;
9233 Lisp_Object specified_data;
9234 TIFF *tiff;
9235 int width, height, x, y;
9236 uint32 *buf;
9237 int rc;
9238 XImage *ximg;
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);
9244 file = Qnil;
9245 GCPRO1 (file);
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);
9254 UNGCPRO;
9255 return 0;
9258 /* Try to open the image file. */
9259 tiff = TIFFOpen (XSTRING (file)->data, "r");
9260 if (tiff == NULL)
9262 image_error ("Cannot open `%s'", file, Qnil);
9263 UNGCPRO;
9264 return 0;
9267 else
9269 /* Memory source! */
9270 memsrc.bytes = XSTRING (specified_data)->data;
9271 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9272 memsrc.index = 0;
9274 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9275 (TIFFReadWriteProc) tiff_read_from_memory,
9276 (TIFFReadWriteProc) tiff_write_from_memory,
9277 tiff_seek_in_memory,
9278 tiff_close_memory,
9279 tiff_size_of_memory,
9280 tiff_mmap_memory,
9281 tiff_unmap_memory);
9283 if (!tiff)
9285 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9286 UNGCPRO;
9287 return 0;
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);
9298 TIFFClose (tiff);
9299 if (!rc)
9301 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9302 xfree (buf);
9303 UNGCPRO;
9304 return 0;
9307 /* Create the X image and pixmap. */
9308 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9310 xfree (buf);
9311 UNGCPRO;
9312 return 0;
9315 /* Initialize the color table. */
9316 init_color_table ();
9318 /* Process the pixel raster. Origin is in the lower-left corner. */
9319 for (y = 0; y < height; ++y)
9321 uint32 *row = buf + y * width;
9323 for (x = 0; x < width; ++x)
9325 uint32 abgr = row[x];
9326 int r = TIFFGetR (abgr) << 8;
9327 int g = TIFFGetG (abgr) << 8;
9328 int b = TIFFGetB (abgr) << 8;
9329 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9333 /* Remember the colors allocated for the image. Free the color table. */
9334 img->colors = colors_in_color_table (&img->ncolors);
9335 free_color_table ();
9337 /* Put the image into the pixmap, then free the X image and its buffer. */
9338 x_put_x_image (f, ximg, img->pixmap, width, height);
9339 x_destroy_x_image (ximg);
9340 xfree (buf);
9342 img->width = width;
9343 img->height = height;
9345 UNGCPRO;
9346 return 1;
9349 #endif /* HAVE_TIFF != 0 */
9353 /***********************************************************************
9355 ***********************************************************************/
9357 #if HAVE_GIF
9359 #include <gif_lib.h>
9361 static int gif_image_p P_ ((Lisp_Object object));
9362 static int gif_load P_ ((struct frame *f, struct image *img));
9364 /* The symbol `gif' identifying images of this type. */
9366 Lisp_Object Qgif;
9368 /* Indices of image specification fields in gif_format, below. */
9370 enum gif_keyword_index
9372 GIF_TYPE,
9373 GIF_DATA,
9374 GIF_FILE,
9375 GIF_ASCENT,
9376 GIF_MARGIN,
9377 GIF_RELIEF,
9378 GIF_ALGORITHM,
9379 GIF_HEURISTIC_MASK,
9380 GIF_MASK,
9381 GIF_IMAGE,
9382 GIF_LAST
9385 /* Vector of image_keyword structures describing the format
9386 of valid user-defined image specifications. */
9388 static struct image_keyword gif_format[GIF_LAST] =
9390 {":type", IMAGE_SYMBOL_VALUE, 1},
9391 {":data", IMAGE_STRING_VALUE, 0},
9392 {":file", IMAGE_STRING_VALUE, 0},
9393 {":ascent", IMAGE_ASCENT_VALUE, 0},
9394 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9395 {":relief", IMAGE_INTEGER_VALUE, 0},
9396 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9397 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9398 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9399 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9402 /* Structure describing the image type `gif'. */
9404 static struct image_type gif_type =
9406 &Qgif,
9407 gif_image_p,
9408 gif_load,
9409 x_clear_image,
9410 NULL
9414 /* Return non-zero if OBJECT is a valid GIF image specification. */
9416 static int
9417 gif_image_p (object)
9418 Lisp_Object object;
9420 struct image_keyword fmt[GIF_LAST];
9421 bcopy (gif_format, fmt, sizeof fmt);
9423 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9424 return 0;
9426 /* Must specify either the :data or :file keyword. */
9427 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9431 /* Reading a GIF image from memory
9432 Based on the PNG memory stuff to a certain extent. */
9434 typedef struct
9436 unsigned char *bytes;
9437 size_t len;
9438 int index;
9440 gif_memory_source;
9443 /* Make the current memory source available to gif_read_from_memory.
9444 It's done this way because not all versions of libungif support
9445 a UserData field in the GifFileType structure. */
9446 static gif_memory_source *current_gif_memory_src;
9448 static int
9449 gif_read_from_memory (file, buf, len)
9450 GifFileType *file;
9451 GifByteType *buf;
9452 int len;
9454 gif_memory_source *src = current_gif_memory_src;
9456 if (len > src->len - src->index)
9457 return -1;
9459 bcopy (src->bytes + src->index, buf, len);
9460 src->index += len;
9461 return len;
9465 /* Load GIF image IMG for use on frame F. Value is non-zero if
9466 successful. */
9468 static int
9469 gif_load (f, img)
9470 struct frame *f;
9471 struct image *img;
9473 Lisp_Object file, specified_file;
9474 Lisp_Object specified_data;
9475 int rc, width, height, x, y, i;
9476 XImage *ximg;
9477 ColorMapObject *gif_color_map;
9478 unsigned long pixel_colors[256];
9479 GifFileType *gif;
9480 struct gcpro gcpro1;
9481 Lisp_Object image;
9482 int ino, image_left, image_top, image_width, image_height;
9483 gif_memory_source memsrc;
9484 unsigned char *raster;
9486 specified_file = image_spec_value (img->spec, QCfile, NULL);
9487 specified_data = image_spec_value (img->spec, QCdata, NULL);
9488 file = Qnil;
9489 GCPRO1 (file);
9491 if (NILP (specified_data))
9493 file = x_find_image_file (specified_file);
9494 if (!STRINGP (file))
9496 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9497 UNGCPRO;
9498 return 0;
9501 /* Open the GIF file. */
9502 gif = DGifOpenFileName (XSTRING (file)->data);
9503 if (gif == NULL)
9505 image_error ("Cannot open `%s'", file, Qnil);
9506 UNGCPRO;
9507 return 0;
9510 else
9512 /* Read from memory! */
9513 current_gif_memory_src = &memsrc;
9514 memsrc.bytes = XSTRING (specified_data)->data;
9515 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9516 memsrc.index = 0;
9518 gif = DGifOpen(&memsrc, gif_read_from_memory);
9519 if (!gif)
9521 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9522 UNGCPRO;
9523 return 0;
9527 /* Read entire contents. */
9528 rc = DGifSlurp (gif);
9529 if (rc == GIF_ERROR)
9531 image_error ("Error reading `%s'", img->spec, Qnil);
9532 DGifCloseFile (gif);
9533 UNGCPRO;
9534 return 0;
9537 image = image_spec_value (img->spec, QCindex, NULL);
9538 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9539 if (ino >= gif->ImageCount)
9541 image_error ("Invalid image number `%s' in image `%s'",
9542 image, img->spec);
9543 DGifCloseFile (gif);
9544 UNGCPRO;
9545 return 0;
9548 width = img->width = gif->SWidth;
9549 height = img->height = gif->SHeight;
9551 /* Create the X image and pixmap. */
9552 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9554 DGifCloseFile (gif);
9555 UNGCPRO;
9556 return 0;
9559 /* Allocate colors. */
9560 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9561 if (!gif_color_map)
9562 gif_color_map = gif->SColorMap;
9563 init_color_table ();
9564 bzero (pixel_colors, sizeof pixel_colors);
9566 for (i = 0; i < gif_color_map->ColorCount; ++i)
9568 int r = gif_color_map->Colors[i].Red << 8;
9569 int g = gif_color_map->Colors[i].Green << 8;
9570 int b = gif_color_map->Colors[i].Blue << 8;
9571 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9574 img->colors = colors_in_color_table (&img->ncolors);
9575 free_color_table ();
9577 /* Clear the part of the screen image that are not covered by
9578 the image from the GIF file. Full animated GIF support
9579 requires more than can be done here (see the gif89 spec,
9580 disposal methods). Let's simply assume that the part
9581 not covered by a sub-image is in the frame's background color. */
9582 image_top = gif->SavedImages[ino].ImageDesc.Top;
9583 image_left = gif->SavedImages[ino].ImageDesc.Left;
9584 image_width = gif->SavedImages[ino].ImageDesc.Width;
9585 image_height = gif->SavedImages[ino].ImageDesc.Height;
9587 for (y = 0; y < image_top; ++y)
9588 for (x = 0; x < width; ++x)
9589 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9591 for (y = image_top + image_height; y < height; ++y)
9592 for (x = 0; x < width; ++x)
9593 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9595 for (y = image_top; y < image_top + image_height; ++y)
9597 for (x = 0; x < image_left; ++x)
9598 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9599 for (x = image_left + image_width; x < width; ++x)
9600 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9603 /* Read the GIF image into the X image. We use a local variable
9604 `raster' here because RasterBits below is a char *, and invites
9605 problems with bytes >= 0x80. */
9606 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9608 if (gif->SavedImages[ino].ImageDesc.Interlace)
9610 static int interlace_start[] = {0, 4, 2, 1};
9611 static int interlace_increment[] = {8, 8, 4, 2};
9612 int pass, inc;
9613 int row = interlace_start[0];
9615 pass = 0;
9617 for (y = 0; y < image_height; y++)
9619 if (row >= image_height)
9621 row = interlace_start[++pass];
9622 while (row >= image_height)
9623 row = interlace_start[++pass];
9626 for (x = 0; x < image_width; x++)
9628 int i = raster[(y * image_width) + x];
9629 XPutPixel (ximg, x + image_left, row + image_top,
9630 pixel_colors[i]);
9633 row += interlace_increment[pass];
9636 else
9638 for (y = 0; y < image_height; ++y)
9639 for (x = 0; x < image_width; ++x)
9641 int i = raster[y * image_width + x];
9642 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9646 DGifCloseFile (gif);
9648 /* Put the image into the pixmap, then free the X image and its buffer. */
9649 x_put_x_image (f, ximg, img->pixmap, width, height);
9650 x_destroy_x_image (ximg);
9652 UNGCPRO;
9653 return 1;
9656 #endif /* HAVE_GIF != 0 */
9660 /***********************************************************************
9661 Ghostscript
9662 ***********************************************************************/
9664 static int gs_image_p P_ ((Lisp_Object object));
9665 static int gs_load P_ ((struct frame *f, struct image *img));
9666 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9668 /* The symbol `postscript' identifying images of this type. */
9670 Lisp_Object Qpostscript;
9672 /* Keyword symbols. */
9674 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9676 /* Indices of image specification fields in gs_format, below. */
9678 enum gs_keyword_index
9680 GS_TYPE,
9681 GS_PT_WIDTH,
9682 GS_PT_HEIGHT,
9683 GS_FILE,
9684 GS_LOADER,
9685 GS_BOUNDING_BOX,
9686 GS_ASCENT,
9687 GS_MARGIN,
9688 GS_RELIEF,
9689 GS_ALGORITHM,
9690 GS_HEURISTIC_MASK,
9691 GS_MASK,
9692 GS_LAST
9695 /* Vector of image_keyword structures describing the format
9696 of valid user-defined image specifications. */
9698 static struct image_keyword gs_format[GS_LAST] =
9700 {":type", IMAGE_SYMBOL_VALUE, 1},
9701 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9702 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9703 {":file", IMAGE_STRING_VALUE, 1},
9704 {":loader", IMAGE_FUNCTION_VALUE, 0},
9705 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9706 {":ascent", IMAGE_ASCENT_VALUE, 0},
9707 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9708 {":relief", IMAGE_INTEGER_VALUE, 0},
9709 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9710 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9711 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9714 /* Structure describing the image type `ghostscript'. */
9716 static struct image_type gs_type =
9718 &Qpostscript,
9719 gs_image_p,
9720 gs_load,
9721 gs_clear_image,
9722 NULL
9726 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9728 static void
9729 gs_clear_image (f, img)
9730 struct frame *f;
9731 struct image *img;
9733 /* IMG->data.ptr_val may contain a recorded colormap. */
9734 xfree (img->data.ptr_val);
9735 x_clear_image (f, img);
9739 /* Return non-zero if OBJECT is a valid Ghostscript image
9740 specification. */
9742 static int
9743 gs_image_p (object)
9744 Lisp_Object object;
9746 struct image_keyword fmt[GS_LAST];
9747 Lisp_Object tem;
9748 int i;
9750 bcopy (gs_format, fmt, sizeof fmt);
9752 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9753 return 0;
9755 /* Bounding box must be a list or vector containing 4 integers. */
9756 tem = fmt[GS_BOUNDING_BOX].value;
9757 if (CONSP (tem))
9759 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9760 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9761 return 0;
9762 if (!NILP (tem))
9763 return 0;
9765 else if (VECTORP (tem))
9767 if (XVECTOR (tem)->size != 4)
9768 return 0;
9769 for (i = 0; i < 4; ++i)
9770 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9771 return 0;
9773 else
9774 return 0;
9776 return 1;
9780 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9781 if successful. */
9783 static int
9784 gs_load (f, img)
9785 struct frame *f;
9786 struct image *img;
9788 char buffer[100];
9789 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9790 struct gcpro gcpro1, gcpro2;
9791 Lisp_Object frame;
9792 double in_width, in_height;
9793 Lisp_Object pixel_colors = Qnil;
9795 /* Compute pixel size of pixmap needed from the given size in the
9796 image specification. Sizes in the specification are in pt. 1 pt
9797 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9798 info. */
9799 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9800 in_width = XFASTINT (pt_width) / 72.0;
9801 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9802 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9803 in_height = XFASTINT (pt_height) / 72.0;
9804 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9806 /* Create the pixmap. */
9807 xassert (img->pixmap == None);
9808 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9809 img->width, img->height,
9810 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9812 if (!img->pixmap)
9814 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9815 return 0;
9818 /* Call the loader to fill the pixmap. It returns a process object
9819 if successful. We do not record_unwind_protect here because
9820 other places in redisplay like calling window scroll functions
9821 don't either. Let the Lisp loader use `unwind-protect' instead. */
9822 GCPRO2 (window_and_pixmap_id, pixel_colors);
9824 sprintf (buffer, "%lu %lu",
9825 (unsigned long) FRAME_X_WINDOW (f),
9826 (unsigned long) img->pixmap);
9827 window_and_pixmap_id = build_string (buffer);
9829 sprintf (buffer, "%lu %lu",
9830 FRAME_FOREGROUND_PIXEL (f),
9831 FRAME_BACKGROUND_PIXEL (f));
9832 pixel_colors = build_string (buffer);
9834 XSETFRAME (frame, f);
9835 loader = image_spec_value (img->spec, QCloader, NULL);
9836 if (NILP (loader))
9837 loader = intern ("gs-load-image");
9839 img->data.lisp_val = call6 (loader, frame, img->spec,
9840 make_number (img->width),
9841 make_number (img->height),
9842 window_and_pixmap_id,
9843 pixel_colors);
9844 UNGCPRO;
9845 return PROCESSP (img->data.lisp_val);
9849 /* Kill the Ghostscript process that was started to fill PIXMAP on
9850 frame F. Called from XTread_socket when receiving an event
9851 telling Emacs that Ghostscript has finished drawing. */
9853 void
9854 x_kill_gs_process (pixmap, f)
9855 Pixmap pixmap;
9856 struct frame *f;
9858 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9859 int class, i;
9860 struct image *img;
9862 /* Find the image containing PIXMAP. */
9863 for (i = 0; i < c->used; ++i)
9864 if (c->images[i]->pixmap == pixmap)
9865 break;
9867 /* Kill the GS process. We should have found PIXMAP in the image
9868 cache and its image should contain a process object. */
9869 xassert (i < c->used);
9870 img = c->images[i];
9871 xassert (PROCESSP (img->data.lisp_val));
9872 Fkill_process (img->data.lisp_val, Qnil);
9873 img->data.lisp_val = Qnil;
9875 /* On displays with a mutable colormap, figure out the colors
9876 allocated for the image by looking at the pixels of an XImage for
9877 img->pixmap. */
9878 class = FRAME_X_VISUAL (f)->class;
9879 if (class != StaticColor && class != StaticGray && class != TrueColor)
9881 XImage *ximg;
9883 BLOCK_INPUT;
9885 /* Try to get an XImage for img->pixmep. */
9886 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9887 0, 0, img->width, img->height, ~0, ZPixmap);
9888 if (ximg)
9890 int x, y;
9892 /* Initialize the color table. */
9893 init_color_table ();
9895 /* For each pixel of the image, look its color up in the
9896 color table. After having done so, the color table will
9897 contain an entry for each color used by the image. */
9898 for (y = 0; y < img->height; ++y)
9899 for (x = 0; x < img->width; ++x)
9901 unsigned long pixel = XGetPixel (ximg, x, y);
9902 lookup_pixel_color (f, pixel);
9905 /* Record colors in the image. Free color table and XImage. */
9906 img->colors = colors_in_color_table (&img->ncolors);
9907 free_color_table ();
9908 XDestroyImage (ximg);
9910 #if 0 /* This doesn't seem to be the case. If we free the colors
9911 here, we get a BadAccess later in x_clear_image when
9912 freeing the colors. */
9913 /* We have allocated colors once, but Ghostscript has also
9914 allocated colors on behalf of us. So, to get the
9915 reference counts right, free them once. */
9916 if (img->ncolors)
9917 x_free_colors (f, img->colors, img->ncolors);
9918 #endif
9920 else
9921 image_error ("Cannot get X image of `%s'; colors will not be freed",
9922 img->spec, Qnil);
9924 UNBLOCK_INPUT;
9930 /***********************************************************************
9931 Window properties
9932 ***********************************************************************/
9934 DEFUN ("x-change-window-property", Fx_change_window_property,
9935 Sx_change_window_property, 2, 3, 0,
9936 "Change window property PROP to VALUE on the X window of FRAME.\n\
9937 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9938 selected frame. Value is VALUE.")
9939 (prop, value, frame)
9940 Lisp_Object frame, prop, value;
9942 struct frame *f = check_x_frame (frame);
9943 Atom prop_atom;
9945 CHECK_STRING (prop, 1);
9946 CHECK_STRING (value, 2);
9948 BLOCK_INPUT;
9949 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9950 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9951 prop_atom, XA_STRING, 8, PropModeReplace,
9952 XSTRING (value)->data, XSTRING (value)->size);
9954 /* Make sure the property is set when we return. */
9955 XFlush (FRAME_X_DISPLAY (f));
9956 UNBLOCK_INPUT;
9958 return value;
9962 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9963 Sx_delete_window_property, 1, 2, 0,
9964 "Remove window property PROP from X window of FRAME.\n\
9965 FRAME nil or omitted means use the selected frame. Value is PROP.")
9966 (prop, frame)
9967 Lisp_Object prop, frame;
9969 struct frame *f = check_x_frame (frame);
9970 Atom prop_atom;
9972 CHECK_STRING (prop, 1);
9973 BLOCK_INPUT;
9974 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9975 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9977 /* Make sure the property is removed when we return. */
9978 XFlush (FRAME_X_DISPLAY (f));
9979 UNBLOCK_INPUT;
9981 return prop;
9985 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9986 1, 2, 0,
9987 "Value is the value of window property PROP on FRAME.\n\
9988 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9989 if FRAME hasn't a property with name PROP or if PROP has no string\n\
9990 value.")
9991 (prop, frame)
9992 Lisp_Object prop, frame;
9994 struct frame *f = check_x_frame (frame);
9995 Atom prop_atom;
9996 int rc;
9997 Lisp_Object prop_value = Qnil;
9998 char *tmp_data = NULL;
9999 Atom actual_type;
10000 int actual_format;
10001 unsigned long actual_size, bytes_remaining;
10003 CHECK_STRING (prop, 1);
10004 BLOCK_INPUT;
10005 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10006 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10007 prop_atom, 0, 0, False, XA_STRING,
10008 &actual_type, &actual_format, &actual_size,
10009 &bytes_remaining, (unsigned char **) &tmp_data);
10010 if (rc == Success)
10012 int size = bytes_remaining;
10014 XFree (tmp_data);
10015 tmp_data = NULL;
10017 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10018 prop_atom, 0, bytes_remaining,
10019 False, XA_STRING,
10020 &actual_type, &actual_format,
10021 &actual_size, &bytes_remaining,
10022 (unsigned char **) &tmp_data);
10023 if (rc == Success)
10024 prop_value = make_string (tmp_data, size);
10026 XFree (tmp_data);
10029 UNBLOCK_INPUT;
10030 return prop_value;
10035 /***********************************************************************
10036 Busy cursor
10037 ***********************************************************************/
10039 /* If non-null, an asynchronous timer that, when it expires, displays
10040 a busy cursor on all frames. */
10042 static struct atimer *busy_cursor_atimer;
10044 /* Non-zero means a busy cursor is currently shown. */
10046 static int busy_cursor_shown_p;
10048 /* Number of seconds to wait before displaying a busy cursor. */
10050 static Lisp_Object Vbusy_cursor_delay;
10052 /* Default number of seconds to wait before displaying a busy
10053 cursor. */
10055 #define DEFAULT_BUSY_CURSOR_DELAY 1
10057 /* Function prototypes. */
10059 static void show_busy_cursor P_ ((struct atimer *));
10060 static void hide_busy_cursor P_ ((void));
10063 /* Cancel a currently active busy-cursor timer, and start a new one. */
10065 void
10066 start_busy_cursor ()
10068 EMACS_TIME delay;
10069 int secs, usecs = 0;
10071 cancel_busy_cursor ();
10073 if (INTEGERP (Vbusy_cursor_delay)
10074 && XINT (Vbusy_cursor_delay) > 0)
10075 secs = XFASTINT (Vbusy_cursor_delay);
10076 else if (FLOATP (Vbusy_cursor_delay)
10077 && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
10079 Lisp_Object tem;
10080 tem = Ftruncate (Vbusy_cursor_delay, Qnil);
10081 secs = XFASTINT (tem);
10082 usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
10084 else
10085 secs = DEFAULT_BUSY_CURSOR_DELAY;
10087 EMACS_SET_SECS_USECS (delay, secs, usecs);
10088 busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
10089 show_busy_cursor, NULL);
10093 /* Cancel the busy cursor timer if active, hide a busy cursor if
10094 shown. */
10096 void
10097 cancel_busy_cursor ()
10099 if (busy_cursor_atimer)
10101 cancel_atimer (busy_cursor_atimer);
10102 busy_cursor_atimer = NULL;
10105 if (busy_cursor_shown_p)
10106 hide_busy_cursor ();
10110 /* Timer function of busy_cursor_atimer. TIMER is equal to
10111 busy_cursor_atimer.
10113 Display a busy cursor on all frames by mapping the frames'
10114 busy_window. Set the busy_p flag in the frames' output_data.x
10115 structure to indicate that a busy cursor is shown on the
10116 frames. */
10118 static void
10119 show_busy_cursor (timer)
10120 struct atimer *timer;
10122 /* The timer implementation will cancel this timer automatically
10123 after this function has run. Set busy_cursor_atimer to null
10124 so that we know the timer doesn't have to be canceled. */
10125 busy_cursor_atimer = NULL;
10127 if (!busy_cursor_shown_p)
10129 Lisp_Object rest, frame;
10131 BLOCK_INPUT;
10133 FOR_EACH_FRAME (rest, frame)
10134 if (FRAME_X_P (XFRAME (frame)))
10136 struct frame *f = XFRAME (frame);
10138 f->output_data.x->busy_p = 1;
10140 if (!f->output_data.x->busy_window)
10142 unsigned long mask = CWCursor;
10143 XSetWindowAttributes attrs;
10145 attrs.cursor = f->output_data.x->busy_cursor;
10147 f->output_data.x->busy_window
10148 = XCreateWindow (FRAME_X_DISPLAY (f),
10149 FRAME_OUTER_WINDOW (f),
10150 0, 0, 32000, 32000, 0, 0,
10151 InputOnly,
10152 CopyFromParent,
10153 mask, &attrs);
10156 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10157 XFlush (FRAME_X_DISPLAY (f));
10160 busy_cursor_shown_p = 1;
10161 UNBLOCK_INPUT;
10166 /* Hide the busy cursor on all frames, if it is currently shown. */
10168 static void
10169 hide_busy_cursor ()
10171 if (busy_cursor_shown_p)
10173 Lisp_Object rest, frame;
10175 BLOCK_INPUT;
10176 FOR_EACH_FRAME (rest, frame)
10178 struct frame *f = XFRAME (frame);
10180 if (FRAME_X_P (f)
10181 /* Watch out for newly created frames. */
10182 && f->output_data.x->busy_window)
10184 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10185 /* Sync here because XTread_socket looks at the busy_p flag
10186 that is reset to zero below. */
10187 XSync (FRAME_X_DISPLAY (f), False);
10188 f->output_data.x->busy_p = 0;
10192 busy_cursor_shown_p = 0;
10193 UNBLOCK_INPUT;
10199 /***********************************************************************
10200 Tool tips
10201 ***********************************************************************/
10203 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10204 Lisp_Object));
10206 /* The frame of a currently visible tooltip, or null. */
10208 struct frame *tip_frame;
10210 /* If non-nil, a timer started that hides the last tooltip when it
10211 fires. */
10213 Lisp_Object tip_timer;
10214 Window tip_window;
10216 /* Create a frame for a tooltip on the display described by DPYINFO.
10217 PARMS is a list of frame parameters. Value is the frame. */
10219 static Lisp_Object
10220 x_create_tip_frame (dpyinfo, parms)
10221 struct x_display_info *dpyinfo;
10222 Lisp_Object parms;
10224 struct frame *f;
10225 Lisp_Object frame, tem;
10226 Lisp_Object name;
10227 long window_prompting = 0;
10228 int width, height;
10229 int count = specpdl_ptr - specpdl;
10230 struct gcpro gcpro1, gcpro2, gcpro3;
10231 struct kboard *kb;
10233 check_x ();
10235 /* Use this general default value to start with until we know if
10236 this frame has a specified name. */
10237 Vx_resource_name = Vinvocation_name;
10239 #ifdef MULTI_KBOARD
10240 kb = dpyinfo->kboard;
10241 #else
10242 kb = &the_only_kboard;
10243 #endif
10245 /* Get the name of the frame to use for resource lookup. */
10246 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10247 if (!STRINGP (name)
10248 && !EQ (name, Qunbound)
10249 && !NILP (name))
10250 error ("Invalid frame name--not a string or nil");
10251 Vx_resource_name = name;
10253 frame = Qnil;
10254 GCPRO3 (parms, name, frame);
10255 tip_frame = f = make_frame (1);
10256 XSETFRAME (frame, f);
10257 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10259 f->output_method = output_x_window;
10260 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10261 bzero (f->output_data.x, sizeof (struct x_output));
10262 f->output_data.x->icon_bitmap = -1;
10263 f->output_data.x->fontset = -1;
10264 f->output_data.x->scroll_bar_foreground_pixel = -1;
10265 f->output_data.x->scroll_bar_background_pixel = -1;
10266 f->icon_name = Qnil;
10267 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10268 #ifdef MULTI_KBOARD
10269 FRAME_KBOARD (f) = kb;
10270 #endif
10271 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10272 f->output_data.x->explicit_parent = 0;
10274 /* These colors will be set anyway later, but it's important
10275 to get the color reference counts right, so initialize them! */
10277 Lisp_Object black;
10278 struct gcpro gcpro1;
10280 black = build_string ("black");
10281 GCPRO1 (black);
10282 f->output_data.x->foreground_pixel
10283 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10284 f->output_data.x->background_pixel
10285 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10286 f->output_data.x->cursor_pixel
10287 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10288 f->output_data.x->cursor_foreground_pixel
10289 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10290 f->output_data.x->border_pixel
10291 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10292 f->output_data.x->mouse_pixel
10293 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10294 UNGCPRO;
10297 /* Set the name; the functions to which we pass f expect the name to
10298 be set. */
10299 if (EQ (name, Qunbound) || NILP (name))
10301 f->name = build_string (dpyinfo->x_id_name);
10302 f->explicit_name = 0;
10304 else
10306 f->name = name;
10307 f->explicit_name = 1;
10308 /* use the frame's title when getting resources for this frame. */
10309 specbind (Qx_resource_name, name);
10312 /* Extract the window parameters from the supplied values
10313 that are needed to determine window geometry. */
10315 Lisp_Object font;
10317 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10319 BLOCK_INPUT;
10320 /* First, try whatever font the caller has specified. */
10321 if (STRINGP (font))
10323 tem = Fquery_fontset (font, Qnil);
10324 if (STRINGP (tem))
10325 font = x_new_fontset (f, XSTRING (tem)->data);
10326 else
10327 font = x_new_font (f, XSTRING (font)->data);
10330 /* Try out a font which we hope has bold and italic variations. */
10331 if (!STRINGP (font))
10332 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10333 if (!STRINGP (font))
10334 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10335 if (! STRINGP (font))
10336 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10337 if (! STRINGP (font))
10338 /* This was formerly the first thing tried, but it finds too many fonts
10339 and takes too long. */
10340 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10341 /* If those didn't work, look for something which will at least work. */
10342 if (! STRINGP (font))
10343 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10344 UNBLOCK_INPUT;
10345 if (! STRINGP (font))
10346 font = build_string ("fixed");
10348 x_default_parameter (f, parms, Qfont, font,
10349 "font", "Font", RES_TYPE_STRING);
10352 x_default_parameter (f, parms, Qborder_width, make_number (2),
10353 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10355 /* This defaults to 2 in order to match xterm. We recognize either
10356 internalBorderWidth or internalBorder (which is what xterm calls
10357 it). */
10358 if (NILP (Fassq (Qinternal_border_width, parms)))
10360 Lisp_Object value;
10362 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10363 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10364 if (! EQ (value, Qunbound))
10365 parms = Fcons (Fcons (Qinternal_border_width, value),
10366 parms);
10369 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10370 "internalBorderWidth", "internalBorderWidth",
10371 RES_TYPE_NUMBER);
10373 /* Also do the stuff which must be set before the window exists. */
10374 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10375 "foreground", "Foreground", RES_TYPE_STRING);
10376 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10377 "background", "Background", RES_TYPE_STRING);
10378 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10379 "pointerColor", "Foreground", RES_TYPE_STRING);
10380 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10381 "cursorColor", "Foreground", RES_TYPE_STRING);
10382 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10383 "borderColor", "BorderColor", RES_TYPE_STRING);
10385 /* Init faces before x_default_parameter is called for scroll-bar
10386 parameters because that function calls x_set_scroll_bar_width,
10387 which calls change_frame_size, which calls Fset_window_buffer,
10388 which runs hooks, which call Fvertical_motion. At the end, we
10389 end up in init_iterator with a null face cache, which should not
10390 happen. */
10391 init_frame_faces (f);
10393 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10394 window_prompting = x_figure_window_size (f, parms);
10396 if (window_prompting & XNegative)
10398 if (window_prompting & YNegative)
10399 f->output_data.x->win_gravity = SouthEastGravity;
10400 else
10401 f->output_data.x->win_gravity = NorthEastGravity;
10403 else
10405 if (window_prompting & YNegative)
10406 f->output_data.x->win_gravity = SouthWestGravity;
10407 else
10408 f->output_data.x->win_gravity = NorthWestGravity;
10411 f->output_data.x->size_hint_flags = window_prompting;
10413 XSetWindowAttributes attrs;
10414 unsigned long mask;
10416 BLOCK_INPUT;
10417 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
10418 /* Window managers look at the override-redirect flag to determine
10419 whether or net to give windows a decoration (Xlib spec, chapter
10420 3.2.8). */
10421 attrs.override_redirect = True;
10422 attrs.save_under = True;
10423 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10424 /* Arrange for getting MapNotify and UnmapNotify events. */
10425 attrs.event_mask = StructureNotifyMask;
10426 tip_window
10427 = FRAME_X_WINDOW (f)
10428 = XCreateWindow (FRAME_X_DISPLAY (f),
10429 FRAME_X_DISPLAY_INFO (f)->root_window,
10430 /* x, y, width, height */
10431 0, 0, 1, 1,
10432 /* Border. */
10434 CopyFromParent, InputOutput, CopyFromParent,
10435 mask, &attrs);
10436 UNBLOCK_INPUT;
10439 x_make_gc (f);
10441 x_default_parameter (f, parms, Qauto_raise, Qnil,
10442 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10443 x_default_parameter (f, parms, Qauto_lower, Qnil,
10444 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10445 x_default_parameter (f, parms, Qcursor_type, Qbox,
10446 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10448 /* Dimensions, especially f->height, must be done via change_frame_size.
10449 Change will not be effected unless different from the current
10450 f->height. */
10451 width = f->width;
10452 height = f->height;
10453 f->height = 0;
10454 SET_FRAME_WIDTH (f, 0);
10455 change_frame_size (f, height, width, 1, 0, 0);
10457 f->no_split = 1;
10459 UNGCPRO;
10461 /* It is now ok to make the frame official even if we get an error
10462 below. And the frame needs to be on Vframe_list or making it
10463 visible won't work. */
10464 Vframe_list = Fcons (frame, Vframe_list);
10466 /* Now that the frame is official, it counts as a reference to
10467 its display. */
10468 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10470 return unbind_to (count, frame);
10474 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10475 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10476 A tooltip window is a small X window displaying a string.\n\
10478 FRAME nil or omitted means use the selected frame.\n\
10480 PARMS is an optional list of frame parameters which can be\n\
10481 used to change the tooltip's appearance.\n\
10483 Automatically hide the tooltip after TIMEOUT seconds.\n\
10484 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10486 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10487 the tooltip is displayed at that x-position. Otherwise it is\n\
10488 displayed at the mouse position, with offset DX added (default is 5 if\n\
10489 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10490 parameter is specified, it determines the y-position of the tooltip\n\
10491 window, otherwise it is displayed at the mouse position, with offset\n\
10492 DY added (default is -5).")
10493 (string, frame, parms, timeout, dx, dy)
10494 Lisp_Object string, frame, parms, timeout, dx, dy;
10496 struct frame *f;
10497 struct window *w;
10498 Window root, child;
10499 Lisp_Object buffer, top, left;
10500 struct buffer *old_buffer;
10501 struct text_pos pos;
10502 int i, width, height;
10503 int root_x, root_y, win_x, win_y;
10504 unsigned pmask;
10505 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10506 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10507 int count = specpdl_ptr - specpdl;
10509 specbind (Qinhibit_redisplay, Qt);
10511 GCPRO4 (string, parms, frame, timeout);
10513 CHECK_STRING (string, 0);
10514 f = check_x_frame (frame);
10515 if (NILP (timeout))
10516 timeout = make_number (5);
10517 else
10518 CHECK_NATNUM (timeout, 2);
10520 if (NILP (dx))
10521 dx = make_number (5);
10522 else
10523 CHECK_NUMBER (dx, 5);
10525 if (NILP (dy))
10526 dy = make_number (-5);
10527 else
10528 CHECK_NUMBER (dy, 6);
10530 /* Hide a previous tip, if any. */
10531 Fx_hide_tip ();
10533 /* Add default values to frame parameters. */
10534 if (NILP (Fassq (Qname, parms)))
10535 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10536 if (NILP (Fassq (Qinternal_border_width, parms)))
10537 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10538 if (NILP (Fassq (Qborder_width, parms)))
10539 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10540 if (NILP (Fassq (Qborder_color, parms)))
10541 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10542 if (NILP (Fassq (Qbackground_color, parms)))
10543 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10544 parms);
10546 /* Create a frame for the tooltip, and record it in the global
10547 variable tip_frame. */
10548 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
10549 tip_frame = f = XFRAME (frame);
10551 /* Set up the frame's root window. Currently we use a size of 80
10552 columns x 40 lines. If someone wants to show a larger tip, he
10553 will loose. I don't think this is a realistic case. */
10554 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10555 w->left = w->top = make_number (0);
10556 w->width = make_number (80);
10557 w->height = make_number (40);
10558 adjust_glyphs (f);
10559 w->pseudo_window_p = 1;
10561 /* Display the tooltip text in a temporary buffer. */
10562 buffer = Fget_buffer_create (build_string (" *tip*"));
10563 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10564 old_buffer = current_buffer;
10565 set_buffer_internal_1 (XBUFFER (buffer));
10566 Ferase_buffer ();
10567 Finsert (1, &string);
10568 clear_glyph_matrix (w->desired_matrix);
10569 clear_glyph_matrix (w->current_matrix);
10570 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10571 try_window (FRAME_ROOT_WINDOW (f), pos);
10573 /* Compute width and height of the tooltip. */
10574 width = height = 0;
10575 for (i = 0; i < w->desired_matrix->nrows; ++i)
10577 struct glyph_row *row = &w->desired_matrix->rows[i];
10578 struct glyph *last;
10579 int row_width;
10581 /* Stop at the first empty row at the end. */
10582 if (!row->enabled_p || !row->displays_text_p)
10583 break;
10585 /* Let the row go over the full width of the frame. */
10586 row->full_width_p = 1;
10588 /* There's a glyph at the end of rows that is used to place
10589 the cursor there. Don't include the width of this glyph. */
10590 if (row->used[TEXT_AREA])
10592 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10593 row_width = row->pixel_width - last->pixel_width;
10595 else
10596 row_width = row->pixel_width;
10598 height += row->height;
10599 width = max (width, row_width);
10602 /* Add the frame's internal border to the width and height the X
10603 window should have. */
10604 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10605 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10607 /* User-specified position? */
10608 left = Fcdr (Fassq (Qleft, parms));
10609 top = Fcdr (Fassq (Qtop, parms));
10611 /* Move the tooltip window where the mouse pointer is. Resize and
10612 show it. */
10613 BLOCK_INPUT;
10614 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10615 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
10616 UNBLOCK_INPUT;
10618 root_x += XINT (dx);
10619 root_y += XINT (dy);
10621 if (INTEGERP (left))
10622 root_x = XINT (left);
10623 if (INTEGERP (top))
10624 root_y = XINT (top);
10626 BLOCK_INPUT;
10627 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10628 root_x, root_y - height, width, height);
10629 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10630 UNBLOCK_INPUT;
10632 /* Draw into the window. */
10633 w->must_be_updated_p = 1;
10634 update_single_window (w, 1);
10636 /* Restore original current buffer. */
10637 set_buffer_internal_1 (old_buffer);
10638 windows_or_buffers_changed = old_windows_or_buffers_changed;
10640 /* Let the tip disappear after timeout seconds. */
10641 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10642 intern ("x-hide-tip"));
10644 UNGCPRO;
10645 return unbind_to (count, Qnil);
10649 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10650 "Hide the current tooltip window, if there is any.\n\
10651 Value is t is tooltip was open, nil otherwise.")
10654 int count = specpdl_ptr - specpdl;
10655 int deleted_p = 0;
10657 specbind (Qinhibit_redisplay, Qt);
10659 if (!NILP (tip_timer))
10661 call1 (intern ("cancel-timer"), tip_timer);
10662 tip_timer = Qnil;
10665 if (tip_frame)
10667 Lisp_Object frame;
10669 XSETFRAME (frame, tip_frame);
10670 Fdelete_frame (frame, Qt);
10671 tip_frame = NULL;
10672 deleted_p = 1;
10675 return unbind_to (count, deleted_p ? Qt : Qnil);
10680 /***********************************************************************
10681 File selection dialog
10682 ***********************************************************************/
10684 #ifdef USE_MOTIF
10686 /* Callback for "OK" and "Cancel" on file selection dialog. */
10688 static void
10689 file_dialog_cb (widget, client_data, call_data)
10690 Widget widget;
10691 XtPointer call_data, client_data;
10693 int *result = (int *) client_data;
10694 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10695 *result = cb->reason;
10699 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10700 "Read file name, prompting with PROMPT in directory DIR.\n\
10701 Use a file selection dialog.\n\
10702 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10703 specified. Don't let the user enter a file name in the file\n\
10704 selection dialog's entry field, if MUSTMATCH is non-nil.")
10705 (prompt, dir, default_filename, mustmatch)
10706 Lisp_Object prompt, dir, default_filename, mustmatch;
10708 int result;
10709 struct frame *f = SELECTED_FRAME ();
10710 Lisp_Object file = Qnil;
10711 Widget dialog, text, list, help;
10712 Arg al[10];
10713 int ac = 0;
10714 extern XtAppContext Xt_app_con;
10715 char *title;
10716 XmString dir_xmstring, pattern_xmstring;
10717 int popup_activated_flag;
10718 int count = specpdl_ptr - specpdl;
10719 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10721 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10722 CHECK_STRING (prompt, 0);
10723 CHECK_STRING (dir, 1);
10725 /* Prevent redisplay. */
10726 specbind (Qinhibit_redisplay, Qt);
10728 BLOCK_INPUT;
10730 /* Create the dialog with PROMPT as title, using DIR as initial
10731 directory and using "*" as pattern. */
10732 dir = Fexpand_file_name (dir, Qnil);
10733 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
10734 pattern_xmstring = XmStringCreateLocalized ("*");
10736 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
10737 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10738 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10739 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10740 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10741 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10742 "fsb", al, ac);
10743 XmStringFree (dir_xmstring);
10744 XmStringFree (pattern_xmstring);
10746 /* Add callbacks for OK and Cancel. */
10747 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10748 (XtPointer) &result);
10749 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10750 (XtPointer) &result);
10752 /* Disable the help button since we can't display help. */
10753 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10754 XtSetSensitive (help, False);
10756 /* Mark OK button as default. */
10757 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10758 XmNshowAsDefault, True, NULL);
10760 /* If MUSTMATCH is non-nil, disable the file entry field of the
10761 dialog, so that the user must select a file from the files list
10762 box. We can't remove it because we wouldn't have a way to get at
10763 the result file name, then. */
10764 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10765 if (!NILP (mustmatch))
10767 Widget label;
10768 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10769 XtSetSensitive (text, False);
10770 XtSetSensitive (label, False);
10773 /* Manage the dialog, so that list boxes get filled. */
10774 XtManageChild (dialog);
10776 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10777 must include the path for this to work. */
10778 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10779 if (STRINGP (default_filename))
10781 XmString default_xmstring;
10782 int item_pos;
10784 default_xmstring
10785 = XmStringCreateLocalized (XSTRING (default_filename)->data);
10787 if (!XmListItemExists (list, default_xmstring))
10789 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10790 XmListAddItem (list, default_xmstring, 0);
10791 item_pos = 0;
10793 else
10794 item_pos = XmListItemPos (list, default_xmstring);
10795 XmStringFree (default_xmstring);
10797 /* Select the item and scroll it into view. */
10798 XmListSelectPos (list, item_pos, True);
10799 XmListSetPos (list, item_pos);
10802 #ifdef HAVE_MOTIF_2_1
10804 /* Process events until the user presses Cancel or OK. */
10805 result = 0;
10806 while (result == 0 || XtAppPending (Xt_app_con))
10807 XtAppProcessEvent (Xt_app_con, XtIMAll);
10809 #else /* not HAVE_MOTIF_2_1 */
10811 /* Process all events until the user presses Cancel or OK. */
10812 for (result = 0; result == 0;)
10814 XEvent event;
10815 Widget widget, parent;
10817 XtAppNextEvent (Xt_app_con, &event);
10819 /* See if the receiver of the event is one of the widgets of
10820 the file selection dialog. If so, dispatch it. If not,
10821 discard it. */
10822 widget = XtWindowToWidget (event.xany.display, event.xany.window);
10823 parent = widget;
10824 while (parent && parent != dialog)
10825 parent = XtParent (parent);
10827 if (parent == dialog
10828 || (event.type == Expose
10829 && !process_expose_from_menu (event)))
10830 XtDispatchEvent (&event);
10833 #endif /* not HAVE_MOTIF_2_1 */
10835 /* Get the result. */
10836 if (result == XmCR_OK)
10838 XmString text;
10839 String data;
10841 XtVaGetValues (dialog, XmNtextString, &text, NULL);
10842 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10843 XmStringFree (text);
10844 file = build_string (data);
10845 XtFree (data);
10847 else
10848 file = Qnil;
10850 /* Clean up. */
10851 XtUnmanageChild (dialog);
10852 XtDestroyWidget (dialog);
10853 UNBLOCK_INPUT;
10854 UNGCPRO;
10856 /* Make "Cancel" equivalent to C-g. */
10857 if (NILP (file))
10858 Fsignal (Qquit, Qnil);
10860 return unbind_to (count, file);
10863 #endif /* USE_MOTIF */
10867 /***********************************************************************
10868 Initialization
10869 ***********************************************************************/
10871 void
10872 syms_of_xfns ()
10874 /* This is zero if not using X windows. */
10875 x_in_use = 0;
10877 /* The section below is built by the lisp expression at the top of the file,
10878 just above where these variables are declared. */
10879 /*&&& init symbols here &&&*/
10880 Qauto_raise = intern ("auto-raise");
10881 staticpro (&Qauto_raise);
10882 Qauto_lower = intern ("auto-lower");
10883 staticpro (&Qauto_lower);
10884 Qbar = intern ("bar");
10885 staticpro (&Qbar);
10886 Qborder_color = intern ("border-color");
10887 staticpro (&Qborder_color);
10888 Qborder_width = intern ("border-width");
10889 staticpro (&Qborder_width);
10890 Qbox = intern ("box");
10891 staticpro (&Qbox);
10892 Qcursor_color = intern ("cursor-color");
10893 staticpro (&Qcursor_color);
10894 Qcursor_type = intern ("cursor-type");
10895 staticpro (&Qcursor_type);
10896 Qgeometry = intern ("geometry");
10897 staticpro (&Qgeometry);
10898 Qicon_left = intern ("icon-left");
10899 staticpro (&Qicon_left);
10900 Qicon_top = intern ("icon-top");
10901 staticpro (&Qicon_top);
10902 Qicon_type = intern ("icon-type");
10903 staticpro (&Qicon_type);
10904 Qicon_name = intern ("icon-name");
10905 staticpro (&Qicon_name);
10906 Qinternal_border_width = intern ("internal-border-width");
10907 staticpro (&Qinternal_border_width);
10908 Qleft = intern ("left");
10909 staticpro (&Qleft);
10910 Qright = intern ("right");
10911 staticpro (&Qright);
10912 Qmouse_color = intern ("mouse-color");
10913 staticpro (&Qmouse_color);
10914 Qnone = intern ("none");
10915 staticpro (&Qnone);
10916 Qparent_id = intern ("parent-id");
10917 staticpro (&Qparent_id);
10918 Qscroll_bar_width = intern ("scroll-bar-width");
10919 staticpro (&Qscroll_bar_width);
10920 Qsuppress_icon = intern ("suppress-icon");
10921 staticpro (&Qsuppress_icon);
10922 Qundefined_color = intern ("undefined-color");
10923 staticpro (&Qundefined_color);
10924 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10925 staticpro (&Qvertical_scroll_bars);
10926 Qvisibility = intern ("visibility");
10927 staticpro (&Qvisibility);
10928 Qwindow_id = intern ("window-id");
10929 staticpro (&Qwindow_id);
10930 Qouter_window_id = intern ("outer-window-id");
10931 staticpro (&Qouter_window_id);
10932 Qx_frame_parameter = intern ("x-frame-parameter");
10933 staticpro (&Qx_frame_parameter);
10934 Qx_resource_name = intern ("x-resource-name");
10935 staticpro (&Qx_resource_name);
10936 Quser_position = intern ("user-position");
10937 staticpro (&Quser_position);
10938 Quser_size = intern ("user-size");
10939 staticpro (&Quser_size);
10940 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10941 staticpro (&Qscroll_bar_foreground);
10942 Qscroll_bar_background = intern ("scroll-bar-background");
10943 staticpro (&Qscroll_bar_background);
10944 Qscreen_gamma = intern ("screen-gamma");
10945 staticpro (&Qscreen_gamma);
10946 Qline_spacing = intern ("line-spacing");
10947 staticpro (&Qline_spacing);
10948 Qcenter = intern ("center");
10949 staticpro (&Qcenter);
10950 Qcompound_text = intern ("compound-text");
10951 staticpro (&Qcompound_text);
10952 /* This is the end of symbol initialization. */
10954 /* Text property `display' should be nonsticky by default. */
10955 Vtext_property_default_nonsticky
10956 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10959 Qlaplace = intern ("laplace");
10960 staticpro (&Qlaplace);
10961 Qemboss = intern ("emboss");
10962 staticpro (&Qemboss);
10963 Qedge_detection = intern ("edge-detection");
10964 staticpro (&Qedge_detection);
10965 Qheuristic = intern ("heuristic");
10966 staticpro (&Qheuristic);
10967 QCmatrix = intern (":matrix");
10968 staticpro (&QCmatrix);
10969 QCcolor_adjustment = intern (":color-adjustment");
10970 staticpro (&QCcolor_adjustment);
10971 QCmask = intern (":mask");
10972 staticpro (&QCmask);
10974 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10975 staticpro (&Qface_set_after_frame_default);
10977 Fput (Qundefined_color, Qerror_conditions,
10978 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10979 Fput (Qundefined_color, Qerror_message,
10980 build_string ("Undefined color"));
10982 init_x_parm_symbols ();
10984 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10985 "Non-nil means always draw a cross over disabled images.\n\
10986 Disabled images are those having an `:algorithm disabled' property.\n\
10987 A cross is always drawn on black & white displays.");
10988 cross_disabled_images = 0;
10990 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10991 "List of directories to search for bitmap files for X.");
10992 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
10994 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10995 "The shape of the pointer when over text.\n\
10996 Changing the value does not affect existing frames\n\
10997 unless you set the mouse color.");
10998 Vx_pointer_shape = Qnil;
11000 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11001 "The name Emacs uses to look up X resources.\n\
11002 `x-get-resource' uses this as the first component of the instance name\n\
11003 when requesting resource values.\n\
11004 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11005 was invoked, or to the value specified with the `-name' or `-rn'\n\
11006 switches, if present.\n\
11008 It may be useful to bind this variable locally around a call\n\
11009 to `x-get-resource'. See also the variable `x-resource-class'.");
11010 Vx_resource_name = Qnil;
11012 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11013 "The class Emacs uses to look up X resources.\n\
11014 `x-get-resource' uses this as the first component of the instance class\n\
11015 when requesting resource values.\n\
11016 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11018 Setting this variable permanently is not a reasonable thing to do,\n\
11019 but binding this variable locally around a call to `x-get-resource'\n\
11020 is a reasonable practice. See also the variable `x-resource-name'.");
11021 Vx_resource_class = build_string (EMACS_CLASS);
11023 #if 0 /* This doesn't really do anything. */
11024 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11025 "The shape of the pointer when not over text.\n\
11026 This variable takes effect when you create a new frame\n\
11027 or when you set the mouse color.");
11028 #endif
11029 Vx_nontext_pointer_shape = Qnil;
11031 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
11032 "The shape of the pointer when Emacs is busy.\n\
11033 This variable takes effect when you create a new frame\n\
11034 or when you set the mouse color.");
11035 Vx_busy_pointer_shape = Qnil;
11037 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
11038 "Non-zero means Emacs displays a busy cursor on window systems.");
11039 display_busy_cursor_p = 1;
11041 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
11042 "*Seconds to wait before displaying a busy-cursor.\n\
11043 Value must be an integer or float.");
11044 Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
11046 #if 0 /* This doesn't really do anything. */
11047 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11048 "The shape of the pointer when over the mode line.\n\
11049 This variable takes effect when you create a new frame\n\
11050 or when you set the mouse color.");
11051 #endif
11052 Vx_mode_pointer_shape = Qnil;
11054 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11055 &Vx_sensitive_text_pointer_shape,
11056 "The shape of the pointer when over mouse-sensitive text.\n\
11057 This variable takes effect when you create a new frame\n\
11058 or when you set the mouse color.");
11059 Vx_sensitive_text_pointer_shape = Qnil;
11061 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11062 "A string indicating the foreground color of the cursor box.");
11063 Vx_cursor_fore_pixel = Qnil;
11065 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11066 "Non-nil if no X window manager is in use.\n\
11067 Emacs doesn't try to figure this out; this is always nil\n\
11068 unless you set it to something else.");
11069 /* We don't have any way to find this out, so set it to nil
11070 and maybe the user would like to set it to t. */
11071 Vx_no_window_manager = Qnil;
11073 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11074 &Vx_pixel_size_width_font_regexp,
11075 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11077 Since Emacs gets width of a font matching with this regexp from\n\
11078 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11079 such a font. This is especially effective for such large fonts as\n\
11080 Chinese, Japanese, and Korean.");
11081 Vx_pixel_size_width_font_regexp = Qnil;
11083 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11084 "Time after which cached images are removed from the cache.\n\
11085 When an image has not been displayed this many seconds, remove it\n\
11086 from the image cache. Value must be an integer or nil with nil\n\
11087 meaning don't clear the cache.");
11088 Vimage_cache_eviction_delay = make_number (30 * 60);
11090 #ifdef USE_X_TOOLKIT
11091 Fprovide (intern ("x-toolkit"));
11092 #endif
11093 #ifdef USE_MOTIF
11094 Fprovide (intern ("motif"));
11095 #endif
11097 defsubr (&Sx_get_resource);
11099 /* X window properties. */
11100 defsubr (&Sx_change_window_property);
11101 defsubr (&Sx_delete_window_property);
11102 defsubr (&Sx_window_property);
11104 defsubr (&Sxw_display_color_p);
11105 defsubr (&Sx_display_grayscale_p);
11106 defsubr (&Sxw_color_defined_p);
11107 defsubr (&Sxw_color_values);
11108 defsubr (&Sx_server_max_request_size);
11109 defsubr (&Sx_server_vendor);
11110 defsubr (&Sx_server_version);
11111 defsubr (&Sx_display_pixel_width);
11112 defsubr (&Sx_display_pixel_height);
11113 defsubr (&Sx_display_mm_width);
11114 defsubr (&Sx_display_mm_height);
11115 defsubr (&Sx_display_screens);
11116 defsubr (&Sx_display_planes);
11117 defsubr (&Sx_display_color_cells);
11118 defsubr (&Sx_display_visual_class);
11119 defsubr (&Sx_display_backing_store);
11120 defsubr (&Sx_display_save_under);
11121 defsubr (&Sx_parse_geometry);
11122 defsubr (&Sx_create_frame);
11123 defsubr (&Sx_open_connection);
11124 defsubr (&Sx_close_connection);
11125 defsubr (&Sx_display_list);
11126 defsubr (&Sx_synchronize);
11127 defsubr (&Sx_focus_frame);
11129 /* Setting callback functions for fontset handler. */
11130 get_font_info_func = x_get_font_info;
11132 #if 0 /* This function pointer doesn't seem to be used anywhere.
11133 And the pointer assigned has the wrong type, anyway. */
11134 list_fonts_func = x_list_fonts;
11135 #endif
11137 load_font_func = x_load_font;
11138 find_ccl_program_func = x_find_ccl_program;
11139 query_font_func = x_query_font;
11140 set_frame_fontset_func = x_set_font;
11141 check_window_system_func = check_x;
11143 /* Images. */
11144 Qxbm = intern ("xbm");
11145 staticpro (&Qxbm);
11146 QCtype = intern (":type");
11147 staticpro (&QCtype);
11148 QCalgorithm = intern (":algorithm");
11149 staticpro (&QCalgorithm);
11150 QCheuristic_mask = intern (":heuristic-mask");
11151 staticpro (&QCheuristic_mask);
11152 QCcolor_symbols = intern (":color-symbols");
11153 staticpro (&QCcolor_symbols);
11154 QCascent = intern (":ascent");
11155 staticpro (&QCascent);
11156 QCmargin = intern (":margin");
11157 staticpro (&QCmargin);
11158 QCrelief = intern (":relief");
11159 staticpro (&QCrelief);
11160 Qpostscript = intern ("postscript");
11161 staticpro (&Qpostscript);
11162 QCloader = intern (":loader");
11163 staticpro (&QCloader);
11164 QCbounding_box = intern (":bounding-box");
11165 staticpro (&QCbounding_box);
11166 QCpt_width = intern (":pt-width");
11167 staticpro (&QCpt_width);
11168 QCpt_height = intern (":pt-height");
11169 staticpro (&QCpt_height);
11170 QCindex = intern (":index");
11171 staticpro (&QCindex);
11172 Qpbm = intern ("pbm");
11173 staticpro (&Qpbm);
11175 #if HAVE_XPM
11176 Qxpm = intern ("xpm");
11177 staticpro (&Qxpm);
11178 #endif
11180 #if HAVE_JPEG
11181 Qjpeg = intern ("jpeg");
11182 staticpro (&Qjpeg);
11183 #endif
11185 #if HAVE_TIFF
11186 Qtiff = intern ("tiff");
11187 staticpro (&Qtiff);
11188 #endif
11190 #if HAVE_GIF
11191 Qgif = intern ("gif");
11192 staticpro (&Qgif);
11193 #endif
11195 #if HAVE_PNG
11196 Qpng = intern ("png");
11197 staticpro (&Qpng);
11198 #endif
11200 defsubr (&Sclear_image_cache);
11201 defsubr (&Simage_size);
11202 defsubr (&Simage_mask_p);
11204 busy_cursor_atimer = NULL;
11205 busy_cursor_shown_p = 0;
11207 defsubr (&Sx_show_tip);
11208 defsubr (&Sx_hide_tip);
11209 staticpro (&tip_timer);
11210 tip_timer = Qnil;
11212 #ifdef USE_MOTIF
11213 defsubr (&Sx_file_dialog);
11214 #endif
11218 void
11219 init_xfns ()
11221 image_types = NULL;
11222 Vimage_types = Qnil;
11224 define_image_type (&xbm_type);
11225 define_image_type (&gs_type);
11226 define_image_type (&pbm_type);
11228 #if HAVE_XPM
11229 define_image_type (&xpm_type);
11230 #endif
11232 #if HAVE_JPEG
11233 define_image_type (&jpeg_type);
11234 #endif
11236 #if HAVE_TIFF
11237 define_image_type (&tiff_type);
11238 #endif
11240 #if HAVE_GIF
11241 define_image_type (&gif_type);
11242 #endif
11244 #if HAVE_PNG
11245 define_image_type (&png_type);
11246 #endif
11249 #endif /* HAVE_X_WINDOWS */