Fix var names in doc.
[emacs.git] / src / xfns.c
blobe0e57abc6cb844c1a0ec924e6dba32a3c95c1188
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 x_query_color (f, &fore_color);
1510 back_color.pixel = mask_color;
1511 x_query_color (f, &back_color);
1513 XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
1514 &fore_color, &back_color);
1515 XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
1516 &fore_color, &back_color);
1517 XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
1518 &fore_color, &back_color);
1519 XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
1520 &fore_color, &back_color);
1521 XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
1522 &fore_color, &back_color);
1525 if (FRAME_X_WINDOW (f) != 0)
1526 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
1528 if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
1529 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
1530 f->output_data.x->text_cursor = cursor;
1532 if (nontext_cursor != f->output_data.x->nontext_cursor
1533 && f->output_data.x->nontext_cursor != 0)
1534 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
1535 f->output_data.x->nontext_cursor = nontext_cursor;
1537 if (busy_cursor != f->output_data.x->busy_cursor
1538 && f->output_data.x->busy_cursor != 0)
1539 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
1540 f->output_data.x->busy_cursor = busy_cursor;
1542 if (mode_cursor != f->output_data.x->modeline_cursor
1543 && f->output_data.x->modeline_cursor != 0)
1544 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
1545 f->output_data.x->modeline_cursor = mode_cursor;
1547 if (cross_cursor != f->output_data.x->cross_cursor
1548 && f->output_data.x->cross_cursor != 0)
1549 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
1550 f->output_data.x->cross_cursor = cross_cursor;
1552 XFlush (FRAME_X_DISPLAY (f));
1553 UNBLOCK_INPUT;
1555 update_face_from_frame_parameter (f, Qmouse_color, arg);
1558 void
1559 x_set_cursor_color (f, arg, oldval)
1560 struct frame *f;
1561 Lisp_Object arg, oldval;
1563 unsigned long fore_pixel, pixel;
1564 int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
1566 if (!NILP (Vx_cursor_fore_pixel))
1568 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1569 WHITE_PIX_DEFAULT (f));
1570 fore_pixel_allocated_p = 1;
1572 else
1573 fore_pixel = f->output_data.x->background_pixel;
1575 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1576 pixel_allocated_p = 1;
1578 /* Make sure that the cursor color differs from the background color. */
1579 if (pixel == f->output_data.x->background_pixel)
1581 if (pixel_allocated_p)
1583 x_free_colors (f, &pixel, 1);
1584 pixel_allocated_p = 0;
1587 pixel = f->output_data.x->mouse_pixel;
1588 if (pixel == fore_pixel)
1590 if (fore_pixel_allocated_p)
1592 x_free_colors (f, &fore_pixel, 1);
1593 fore_pixel_allocated_p = 0;
1595 fore_pixel = f->output_data.x->background_pixel;
1599 unload_color (f, f->output_data.x->cursor_foreground_pixel);
1600 if (!fore_pixel_allocated_p)
1601 fore_pixel = x_copy_color (f, fore_pixel);
1602 f->output_data.x->cursor_foreground_pixel = fore_pixel;
1604 unload_color (f, f->output_data.x->cursor_pixel);
1605 if (!pixel_allocated_p)
1606 pixel = x_copy_color (f, pixel);
1607 f->output_data.x->cursor_pixel = pixel;
1609 if (FRAME_X_WINDOW (f) != 0)
1611 BLOCK_INPUT;
1612 XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1613 f->output_data.x->cursor_pixel);
1614 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
1615 fore_pixel);
1616 UNBLOCK_INPUT;
1618 if (FRAME_VISIBLE_P (f))
1620 x_update_cursor (f, 0);
1621 x_update_cursor (f, 1);
1625 update_face_from_frame_parameter (f, Qcursor_color, arg);
1628 /* Set the border-color of frame F to value described by ARG.
1629 ARG can be a string naming a color.
1630 The border-color is used for the border that is drawn by the X server.
1631 Note that this does not fully take effect if done before
1632 F has an x-window; it must be redone when the window is created.
1634 Note: this is done in two routines because of the way X10 works.
1636 Note: under X11, this is normally the province of the window manager,
1637 and so emacs' border colors may be overridden. */
1639 void
1640 x_set_border_color (f, arg, oldval)
1641 struct frame *f;
1642 Lisp_Object arg, oldval;
1644 int pix;
1646 CHECK_STRING (arg, 0);
1647 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1648 x_set_border_pixel (f, pix);
1649 update_face_from_frame_parameter (f, Qborder_color, arg);
1652 /* Set the border-color of frame F to pixel value PIX.
1653 Note that this does not fully take effect if done before
1654 F has an x-window. */
1656 void
1657 x_set_border_pixel (f, pix)
1658 struct frame *f;
1659 int pix;
1661 unload_color (f, f->output_data.x->border_pixel);
1662 f->output_data.x->border_pixel = pix;
1664 if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
1666 BLOCK_INPUT;
1667 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1668 (unsigned long)pix);
1669 UNBLOCK_INPUT;
1671 if (FRAME_VISIBLE_P (f))
1672 redraw_frame (f);
1677 /* Value is the internal representation of the specified cursor type
1678 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
1679 of the bar cursor. */
1681 enum text_cursor_kinds
1682 x_specified_cursor_type (arg, width)
1683 Lisp_Object arg;
1684 int *width;
1686 enum text_cursor_kinds type;
1688 if (EQ (arg, Qbar))
1690 type = BAR_CURSOR;
1691 *width = 2;
1693 else if (CONSP (arg)
1694 && EQ (XCAR (arg), Qbar)
1695 && INTEGERP (XCDR (arg))
1696 && XINT (XCDR (arg)) >= 0)
1698 type = BAR_CURSOR;
1699 *width = XINT (XCDR (arg));
1701 else if (NILP (arg))
1702 type = NO_CURSOR;
1703 else
1704 /* Treat anything unknown as "box cursor".
1705 It was bad to signal an error; people have trouble fixing
1706 .Xdefaults with Emacs, when it has something bad in it. */
1707 type = FILLED_BOX_CURSOR;
1709 return type;
1712 void
1713 x_set_cursor_type (f, arg, oldval)
1714 FRAME_PTR f;
1715 Lisp_Object arg, oldval;
1717 int width;
1719 FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
1720 f->output_data.x->cursor_width = width;
1722 /* Make sure the cursor gets redrawn. This is overkill, but how
1723 often do people change cursor types? */
1724 update_mode_lines++;
1727 void
1728 x_set_icon_type (f, arg, oldval)
1729 struct frame *f;
1730 Lisp_Object arg, oldval;
1732 int result;
1734 if (STRINGP (arg))
1736 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1737 return;
1739 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1740 return;
1742 BLOCK_INPUT;
1743 if (NILP (arg))
1744 result = x_text_icon (f,
1745 (char *) XSTRING ((!NILP (f->icon_name)
1746 ? f->icon_name
1747 : f->name))->data);
1748 else
1749 result = x_bitmap_icon (f, arg);
1751 if (result)
1753 UNBLOCK_INPUT;
1754 error ("No icon window available");
1757 XFlush (FRAME_X_DISPLAY (f));
1758 UNBLOCK_INPUT;
1761 /* Return non-nil if frame F wants a bitmap icon. */
1763 Lisp_Object
1764 x_icon_type (f)
1765 FRAME_PTR f;
1767 Lisp_Object tem;
1769 tem = assq_no_quit (Qicon_type, f->param_alist);
1770 if (CONSP (tem))
1771 return XCDR (tem);
1772 else
1773 return Qnil;
1776 void
1777 x_set_icon_name (f, arg, oldval)
1778 struct frame *f;
1779 Lisp_Object arg, oldval;
1781 int result;
1783 if (STRINGP (arg))
1785 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1786 return;
1788 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1789 return;
1791 f->icon_name = arg;
1793 if (f->output_data.x->icon_bitmap != 0)
1794 return;
1796 BLOCK_INPUT;
1798 result = x_text_icon (f,
1799 (char *) XSTRING ((!NILP (f->icon_name)
1800 ? f->icon_name
1801 : !NILP (f->title)
1802 ? f->title
1803 : f->name))->data);
1805 if (result)
1807 UNBLOCK_INPUT;
1808 error ("No icon window available");
1811 XFlush (FRAME_X_DISPLAY (f));
1812 UNBLOCK_INPUT;
1815 void
1816 x_set_font (f, arg, oldval)
1817 struct frame *f;
1818 Lisp_Object arg, oldval;
1820 Lisp_Object result;
1821 Lisp_Object fontset_name;
1822 Lisp_Object frame;
1824 CHECK_STRING (arg, 1);
1826 fontset_name = Fquery_fontset (arg, Qnil);
1828 BLOCK_INPUT;
1829 result = (STRINGP (fontset_name)
1830 ? x_new_fontset (f, XSTRING (fontset_name)->data)
1831 : x_new_font (f, XSTRING (arg)->data));
1832 UNBLOCK_INPUT;
1834 if (EQ (result, Qnil))
1835 error ("Font `%s' is not defined", XSTRING (arg)->data);
1836 else if (EQ (result, Qt))
1837 error ("The characters of the given font have varying widths");
1838 else if (STRINGP (result))
1840 store_frame_param (f, Qfont, result);
1841 recompute_basic_faces (f);
1843 else
1844 abort ();
1846 do_pending_window_change (0);
1848 /* Don't call `face-set-after-frame-default' when faces haven't been
1849 initialized yet. This is the case when called from
1850 Fx_create_frame. In that case, the X widget or window doesn't
1851 exist either, and we can end up in x_report_frame_params with a
1852 null widget which gives a segfault. */
1853 if (FRAME_FACE_CACHE (f))
1855 XSETFRAME (frame, f);
1856 call1 (Qface_set_after_frame_default, frame);
1860 void
1861 x_set_border_width (f, arg, oldval)
1862 struct frame *f;
1863 Lisp_Object arg, oldval;
1865 CHECK_NUMBER (arg, 0);
1867 if (XINT (arg) == f->output_data.x->border_width)
1868 return;
1870 if (FRAME_X_WINDOW (f) != 0)
1871 error ("Cannot change the border width of a window");
1873 f->output_data.x->border_width = XINT (arg);
1876 void
1877 x_set_internal_border_width (f, arg, oldval)
1878 struct frame *f;
1879 Lisp_Object arg, oldval;
1881 int old = f->output_data.x->internal_border_width;
1883 CHECK_NUMBER (arg, 0);
1884 f->output_data.x->internal_border_width = XINT (arg);
1885 if (f->output_data.x->internal_border_width < 0)
1886 f->output_data.x->internal_border_width = 0;
1888 #ifdef USE_X_TOOLKIT
1889 if (f->output_data.x->edit_widget)
1890 widget_store_internal_border (f->output_data.x->edit_widget);
1891 #endif
1893 if (f->output_data.x->internal_border_width == old)
1894 return;
1896 if (FRAME_X_WINDOW (f) != 0)
1898 x_set_window_size (f, 0, f->width, f->height);
1899 SET_FRAME_GARBAGED (f);
1900 do_pending_window_change (0);
1904 void
1905 x_set_visibility (f, value, oldval)
1906 struct frame *f;
1907 Lisp_Object value, oldval;
1909 Lisp_Object frame;
1910 XSETFRAME (frame, f);
1912 if (NILP (value))
1913 Fmake_frame_invisible (frame, Qt);
1914 else if (EQ (value, Qicon))
1915 Ficonify_frame (frame);
1916 else
1917 Fmake_frame_visible (frame);
1921 /* Change window heights in windows rooted in WINDOW by N lines. */
1923 static void
1924 x_change_window_heights (window, n)
1925 Lisp_Object window;
1926 int n;
1928 struct window *w = XWINDOW (window);
1930 XSETFASTINT (w->top, XFASTINT (w->top) + n);
1931 XSETFASTINT (w->height, XFASTINT (w->height) - n);
1933 if (INTEGERP (w->orig_top))
1934 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
1935 if (INTEGERP (w->orig_height))
1936 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
1938 /* Handle just the top child in a vertical split. */
1939 if (!NILP (w->vchild))
1940 x_change_window_heights (w->vchild, n);
1942 /* Adjust all children in a horizontal split. */
1943 for (window = w->hchild; !NILP (window); window = w->next)
1945 w = XWINDOW (window);
1946 x_change_window_heights (window, n);
1950 void
1951 x_set_menu_bar_lines (f, value, oldval)
1952 struct frame *f;
1953 Lisp_Object value, oldval;
1955 int nlines;
1956 #ifndef USE_X_TOOLKIT
1957 int olines = FRAME_MENU_BAR_LINES (f);
1958 #endif
1960 /* Right now, menu bars don't work properly in minibuf-only frames;
1961 most of the commands try to apply themselves to the minibuffer
1962 frame itself, and get an error because you can't switch buffers
1963 in or split the minibuffer window. */
1964 if (FRAME_MINIBUF_ONLY_P (f))
1965 return;
1967 if (INTEGERP (value))
1968 nlines = XINT (value);
1969 else
1970 nlines = 0;
1972 /* Make sure we redisplay all windows in this frame. */
1973 windows_or_buffers_changed++;
1975 #ifdef USE_X_TOOLKIT
1976 FRAME_MENU_BAR_LINES (f) = 0;
1977 if (nlines)
1979 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1980 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1981 /* Make sure next redisplay shows the menu bar. */
1982 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
1984 else
1986 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1987 free_frame_menubar (f);
1988 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1989 if (FRAME_X_P (f))
1990 f->output_data.x->menubar_widget = 0;
1992 #else /* not USE_X_TOOLKIT */
1993 FRAME_MENU_BAR_LINES (f) = nlines;
1994 x_change_window_heights (f->root_window, nlines - olines);
1995 #endif /* not USE_X_TOOLKIT */
1996 adjust_glyphs (f);
2000 /* Set the number of lines used for the tool bar of frame F to VALUE.
2001 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2002 is the old number of tool bar lines. This function changes the
2003 height of all windows on frame F to match the new tool bar height.
2004 The frame's height doesn't change. */
2006 void
2007 x_set_tool_bar_lines (f, value, oldval)
2008 struct frame *f;
2009 Lisp_Object value, oldval;
2011 int delta, nlines, root_height;
2012 Lisp_Object root_window;
2014 /* Use VALUE only if an integer >= 0. */
2015 if (INTEGERP (value) && XINT (value) >= 0)
2016 nlines = XFASTINT (value);
2017 else
2018 nlines = 0;
2020 /* Make sure we redisplay all windows in this frame. */
2021 ++windows_or_buffers_changed;
2023 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2025 /* Don't resize the tool-bar to more than we have room for. */
2026 root_window = FRAME_ROOT_WINDOW (f);
2027 root_height = XINT (XWINDOW (root_window)->height);
2028 if (root_height - delta < 1)
2030 delta = root_height - 1;
2031 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2034 FRAME_TOOL_BAR_LINES (f) = nlines;
2035 x_change_window_heights (root_window, delta);
2036 adjust_glyphs (f);
2038 /* We also have to make sure that the internal border at the top of
2039 the frame, below the menu bar or tool bar, is redrawn when the
2040 tool bar disappears. This is so because the internal border is
2041 below the tool bar if one is displayed, but is below the menu bar
2042 if there isn't a tool bar. The tool bar draws into the area
2043 below the menu bar. */
2044 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2046 updating_frame = f;
2047 clear_frame ();
2048 updating_frame = NULL;
2053 /* Set the foreground color for scroll bars on frame F to VALUE.
2054 VALUE should be a string, a color name. If it isn't a string or
2055 isn't a valid color name, do nothing. OLDVAL is the old value of
2056 the frame parameter. */
2058 void
2059 x_set_scroll_bar_foreground (f, value, oldval)
2060 struct frame *f;
2061 Lisp_Object value, oldval;
2063 unsigned long pixel;
2065 if (STRINGP (value))
2066 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2067 else
2068 pixel = -1;
2070 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2071 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2073 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2074 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2076 /* Remove all scroll bars because they have wrong colors. */
2077 if (condemn_scroll_bars_hook)
2078 (*condemn_scroll_bars_hook) (f);
2079 if (judge_scroll_bars_hook)
2080 (*judge_scroll_bars_hook) (f);
2082 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2083 redraw_frame (f);
2088 /* Set the background color for scroll bars on frame F to VALUE VALUE
2089 should be a string, a color name. If it isn't a string or isn't a
2090 valid color name, do nothing. OLDVAL is the old value of the frame
2091 parameter. */
2093 void
2094 x_set_scroll_bar_background (f, value, oldval)
2095 struct frame *f;
2096 Lisp_Object value, oldval;
2098 unsigned long pixel;
2100 if (STRINGP (value))
2101 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2102 else
2103 pixel = -1;
2105 if (f->output_data.x->scroll_bar_background_pixel != -1)
2106 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2108 f->output_data.x->scroll_bar_background_pixel = pixel;
2109 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2111 /* Remove all scroll bars because they have wrong colors. */
2112 if (condemn_scroll_bars_hook)
2113 (*condemn_scroll_bars_hook) (f);
2114 if (judge_scroll_bars_hook)
2115 (*judge_scroll_bars_hook) (f);
2117 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2118 redraw_frame (f);
2123 /* Encode Lisp string STRING as a text in a format appropriate for
2124 XICCC (X Inter Client Communication Conventions).
2126 If STRING contains only ASCII characters, do no conversion and
2127 return the string data of STRING. Otherwise, encode the text by
2128 CODING_SYSTEM, and return a newly allocated memory area which
2129 should be freed by `xfree' by a caller.
2131 Store the byte length of resulting text in *TEXT_BYTES.
2133 If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
2134 which means that the `encoding' of the result can be `STRING'.
2135 Otherwise store 0 in *STRINGP, which means that the `encoding' of
2136 the result should be `COMPOUND_TEXT'. */
2138 unsigned char *
2139 x_encode_text (string, coding_system, text_bytes, stringp)
2140 Lisp_Object string, coding_system;
2141 int *text_bytes, *stringp;
2143 unsigned char *str = XSTRING (string)->data;
2144 int chars = XSTRING (string)->size;
2145 int bytes = STRING_BYTES (XSTRING (string));
2146 int charset_info;
2147 int bufsize;
2148 unsigned char *buf;
2149 struct coding_system coding;
2151 charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
2152 if (charset_info == 0)
2154 /* No multibyte character in OBJ. We need not encode it. */
2155 *text_bytes = bytes;
2156 *stringp = 1;
2157 return str;
2160 setup_coding_system (coding_system, &coding);
2161 coding.src_multibyte = 1;
2162 coding.dst_multibyte = 0;
2163 coding.mode |= CODING_MODE_LAST_BLOCK;
2164 if (coding.type == coding_type_iso2022)
2165 coding.flags |= CODING_FLAG_ISO_SAFE;
2166 bufsize = encoding_buffer_size (&coding, bytes);
2167 buf = (unsigned char *) xmalloc (bufsize);
2168 encode_coding (&coding, str, buf, bytes, bufsize);
2169 *text_bytes = coding.produced;
2170 *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
2171 return buf;
2175 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2176 x_id_name.
2178 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2179 name; if NAME is a string, set F's name to NAME and set
2180 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2182 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2183 suggesting a new name, which lisp code should override; if
2184 F->explicit_name is set, ignore the new name; otherwise, set it. */
2186 void
2187 x_set_name (f, name, explicit)
2188 struct frame *f;
2189 Lisp_Object name;
2190 int explicit;
2192 /* Make sure that requests from lisp code override requests from
2193 Emacs redisplay code. */
2194 if (explicit)
2196 /* If we're switching from explicit to implicit, we had better
2197 update the mode lines and thereby update the title. */
2198 if (f->explicit_name && NILP (name))
2199 update_mode_lines = 1;
2201 f->explicit_name = ! NILP (name);
2203 else if (f->explicit_name)
2204 return;
2206 /* If NAME is nil, set the name to the x_id_name. */
2207 if (NILP (name))
2209 /* Check for no change needed in this very common case
2210 before we do any consing. */
2211 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
2212 XSTRING (f->name)->data))
2213 return;
2214 name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
2216 else
2217 CHECK_STRING (name, 0);
2219 /* Don't change the name if it's already NAME. */
2220 if (! NILP (Fstring_equal (name, f->name)))
2221 return;
2223 f->name = name;
2225 /* For setting the frame title, the title parameter should override
2226 the name parameter. */
2227 if (! NILP (f->title))
2228 name = f->title;
2230 if (FRAME_X_WINDOW (f))
2232 BLOCK_INPUT;
2233 #ifdef HAVE_X11R4
2235 XTextProperty text, icon;
2236 int bytes, stringp;
2237 Lisp_Object coding_system;
2239 coding_system = Vlocale_coding_system;
2240 if (NILP (coding_system))
2241 coding_system = Qcompound_text;
2242 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2243 text.encoding = (stringp ? XA_STRING
2244 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2245 text.format = 8;
2246 text.nitems = bytes;
2248 if (NILP (f->icon_name))
2250 icon = text;
2252 else
2254 icon.value = x_encode_text (f->icon_name, coding_system,
2255 &bytes, &stringp);
2256 icon.encoding = (stringp ? XA_STRING
2257 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2258 icon.format = 8;
2259 icon.nitems = bytes;
2261 #ifdef USE_X_TOOLKIT
2262 XSetWMName (FRAME_X_DISPLAY (f),
2263 XtWindow (f->output_data.x->widget), &text);
2264 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2265 &icon);
2266 #else /* not USE_X_TOOLKIT */
2267 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2268 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2269 #endif /* not USE_X_TOOLKIT */
2270 if (!NILP (f->icon_name)
2271 && icon.value != XSTRING (f->icon_name)->data)
2272 xfree (icon.value);
2273 if (text.value != XSTRING (name)->data)
2274 xfree (text.value);
2276 #else /* not HAVE_X11R4 */
2277 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2278 XSTRING (name)->data);
2279 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2280 XSTRING (name)->data);
2281 #endif /* not HAVE_X11R4 */
2282 UNBLOCK_INPUT;
2286 /* This function should be called when the user's lisp code has
2287 specified a name for the frame; the name will override any set by the
2288 redisplay code. */
2289 void
2290 x_explicitly_set_name (f, arg, oldval)
2291 FRAME_PTR f;
2292 Lisp_Object arg, oldval;
2294 x_set_name (f, arg, 1);
2297 /* This function should be called by Emacs redisplay code to set the
2298 name; names set this way will never override names set by the user's
2299 lisp code. */
2300 void
2301 x_implicitly_set_name (f, arg, oldval)
2302 FRAME_PTR f;
2303 Lisp_Object arg, oldval;
2305 x_set_name (f, arg, 0);
2308 /* Change the title of frame F to NAME.
2309 If NAME is nil, use the frame name as the title.
2311 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2312 name; if NAME is a string, set F's name to NAME and set
2313 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2315 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2316 suggesting a new name, which lisp code should override; if
2317 F->explicit_name is set, ignore the new name; otherwise, set it. */
2319 void
2320 x_set_title (f, name, old_name)
2321 struct frame *f;
2322 Lisp_Object name, old_name;
2324 /* Don't change the title if it's already NAME. */
2325 if (EQ (name, f->title))
2326 return;
2328 update_mode_lines = 1;
2330 f->title = name;
2332 if (NILP (name))
2333 name = f->name;
2334 else
2335 CHECK_STRING (name, 0);
2337 if (FRAME_X_WINDOW (f))
2339 BLOCK_INPUT;
2340 #ifdef HAVE_X11R4
2342 XTextProperty text, icon;
2343 int bytes, stringp;
2344 Lisp_Object coding_system;
2346 coding_system = Vlocale_coding_system;
2347 if (NILP (coding_system))
2348 coding_system = Qcompound_text;
2349 text.value = x_encode_text (name, coding_system, &bytes, &stringp);
2350 text.encoding = (stringp ? XA_STRING
2351 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2352 text.format = 8;
2353 text.nitems = bytes;
2355 if (NILP (f->icon_name))
2357 icon = text;
2359 else
2361 icon.value = x_encode_text (f->icon_name, coding_system,
2362 &bytes, &stringp);
2363 icon.encoding = (stringp ? XA_STRING
2364 : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2365 icon.format = 8;
2366 icon.nitems = bytes;
2368 #ifdef USE_X_TOOLKIT
2369 XSetWMName (FRAME_X_DISPLAY (f),
2370 XtWindow (f->output_data.x->widget), &text);
2371 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
2372 &icon);
2373 #else /* not USE_X_TOOLKIT */
2374 XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
2375 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
2376 #endif /* not USE_X_TOOLKIT */
2377 if (!NILP (f->icon_name)
2378 && icon.value != XSTRING (f->icon_name)->data)
2379 xfree (icon.value);
2380 if (text.value != XSTRING (name)->data)
2381 xfree (text.value);
2383 #else /* not HAVE_X11R4 */
2384 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2385 XSTRING (name)->data);
2386 XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2387 XSTRING (name)->data);
2388 #endif /* not HAVE_X11R4 */
2389 UNBLOCK_INPUT;
2393 void
2394 x_set_autoraise (f, arg, oldval)
2395 struct frame *f;
2396 Lisp_Object arg, oldval;
2398 f->auto_raise = !EQ (Qnil, arg);
2401 void
2402 x_set_autolower (f, arg, oldval)
2403 struct frame *f;
2404 Lisp_Object arg, oldval;
2406 f->auto_lower = !EQ (Qnil, arg);
2409 void
2410 x_set_unsplittable (f, arg, oldval)
2411 struct frame *f;
2412 Lisp_Object arg, oldval;
2414 f->no_split = !NILP (arg);
2417 void
2418 x_set_vertical_scroll_bars (f, arg, oldval)
2419 struct frame *f;
2420 Lisp_Object arg, oldval;
2422 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2423 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
2424 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2425 || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
2427 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
2428 = (NILP (arg)
2429 ? vertical_scroll_bar_none
2430 : EQ (Qright, arg)
2431 ? vertical_scroll_bar_right
2432 : vertical_scroll_bar_left);
2434 /* We set this parameter before creating the X window for the
2435 frame, so we can get the geometry right from the start.
2436 However, if the window hasn't been created yet, we shouldn't
2437 call x_set_window_size. */
2438 if (FRAME_X_WINDOW (f))
2439 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2440 do_pending_window_change (0);
2444 void
2445 x_set_scroll_bar_width (f, arg, oldval)
2446 struct frame *f;
2447 Lisp_Object arg, oldval;
2449 int wid = FONT_WIDTH (f->output_data.x->font);
2451 if (NILP (arg))
2453 #ifdef USE_TOOLKIT_SCROLL_BARS
2454 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2455 int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2456 FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
2457 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
2458 #else
2459 /* Make the actual width at least 14 pixels and a multiple of a
2460 character width. */
2461 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2463 /* Use all of that space (aside from required margins) for the
2464 scroll bar. */
2465 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2466 #endif
2468 if (FRAME_X_WINDOW (f))
2469 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2470 do_pending_window_change (0);
2472 else if (INTEGERP (arg) && XINT (arg) > 0
2473 && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
2475 if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
2476 XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
2478 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
2479 FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
2480 if (FRAME_X_WINDOW (f))
2481 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2484 change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
2485 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
2486 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
2491 /* Subroutines of creating an X frame. */
2493 /* Make sure that Vx_resource_name is set to a reasonable value.
2494 Fix it up, or set it to `emacs' if it is too hopeless. */
2496 static void
2497 validate_x_resource_name ()
2499 int len = 0;
2500 /* Number of valid characters in the resource name. */
2501 int good_count = 0;
2502 /* Number of invalid characters in the resource name. */
2503 int bad_count = 0;
2504 Lisp_Object new;
2505 int i;
2507 if (!STRINGP (Vx_resource_class))
2508 Vx_resource_class = build_string (EMACS_CLASS);
2510 if (STRINGP (Vx_resource_name))
2512 unsigned char *p = XSTRING (Vx_resource_name)->data;
2513 int i;
2515 len = STRING_BYTES (XSTRING (Vx_resource_name));
2517 /* Only letters, digits, - and _ are valid in resource names.
2518 Count the valid characters and count the invalid ones. */
2519 for (i = 0; i < len; i++)
2521 int c = p[i];
2522 if (! ((c >= 'a' && c <= 'z')
2523 || (c >= 'A' && c <= 'Z')
2524 || (c >= '0' && c <= '9')
2525 || c == '-' || c == '_'))
2526 bad_count++;
2527 else
2528 good_count++;
2531 else
2532 /* Not a string => completely invalid. */
2533 bad_count = 5, good_count = 0;
2535 /* If name is valid already, return. */
2536 if (bad_count == 0)
2537 return;
2539 /* If name is entirely invalid, or nearly so, use `emacs'. */
2540 if (good_count == 0
2541 || (good_count == 1 && bad_count > 0))
2543 Vx_resource_name = build_string ("emacs");
2544 return;
2547 /* Name is partly valid. Copy it and replace the invalid characters
2548 with underscores. */
2550 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
2552 for (i = 0; i < len; i++)
2554 int c = XSTRING (new)->data[i];
2555 if (! ((c >= 'a' && c <= 'z')
2556 || (c >= 'A' && c <= 'Z')
2557 || (c >= '0' && c <= '9')
2558 || c == '-' || c == '_'))
2559 XSTRING (new)->data[i] = '_';
2564 extern char *x_get_string_resource ();
2566 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
2567 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2568 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2569 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2570 the name specified by the `-name' or `-rn' command-line arguments.\n\
2572 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2573 class, respectively. You must specify both of them or neither.\n\
2574 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2575 and the class is `Emacs.CLASS.SUBCLASS'.")
2576 (attribute, class, component, subclass)
2577 Lisp_Object attribute, class, component, subclass;
2579 register char *value;
2580 char *name_key;
2581 char *class_key;
2583 check_x ();
2585 CHECK_STRING (attribute, 0);
2586 CHECK_STRING (class, 0);
2588 if (!NILP (component))
2589 CHECK_STRING (component, 1);
2590 if (!NILP (subclass))
2591 CHECK_STRING (subclass, 2);
2592 if (NILP (component) != NILP (subclass))
2593 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2595 validate_x_resource_name ();
2597 /* Allocate space for the components, the dots which separate them,
2598 and the final '\0'. Make them big enough for the worst case. */
2599 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2600 + (STRINGP (component)
2601 ? STRING_BYTES (XSTRING (component)) : 0)
2602 + STRING_BYTES (XSTRING (attribute))
2603 + 3);
2605 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2606 + STRING_BYTES (XSTRING (class))
2607 + (STRINGP (subclass)
2608 ? STRING_BYTES (XSTRING (subclass)) : 0)
2609 + 3);
2611 /* Start with emacs.FRAMENAME for the name (the specific one)
2612 and with `Emacs' for the class key (the general one). */
2613 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2614 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2616 strcat (class_key, ".");
2617 strcat (class_key, XSTRING (class)->data);
2619 if (!NILP (component))
2621 strcat (class_key, ".");
2622 strcat (class_key, XSTRING (subclass)->data);
2624 strcat (name_key, ".");
2625 strcat (name_key, XSTRING (component)->data);
2628 strcat (name_key, ".");
2629 strcat (name_key, XSTRING (attribute)->data);
2631 value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
2632 name_key, class_key);
2634 if (value != (char *) 0)
2635 return build_string (value);
2636 else
2637 return Qnil;
2640 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
2642 Lisp_Object
2643 display_x_get_resource (dpyinfo, attribute, class, component, subclass)
2644 struct x_display_info *dpyinfo;
2645 Lisp_Object attribute, class, component, subclass;
2647 register char *value;
2648 char *name_key;
2649 char *class_key;
2651 CHECK_STRING (attribute, 0);
2652 CHECK_STRING (class, 0);
2654 if (!NILP (component))
2655 CHECK_STRING (component, 1);
2656 if (!NILP (subclass))
2657 CHECK_STRING (subclass, 2);
2658 if (NILP (component) != NILP (subclass))
2659 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2661 validate_x_resource_name ();
2663 /* Allocate space for the components, the dots which separate them,
2664 and the final '\0'. Make them big enough for the worst case. */
2665 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
2666 + (STRINGP (component)
2667 ? STRING_BYTES (XSTRING (component)) : 0)
2668 + STRING_BYTES (XSTRING (attribute))
2669 + 3);
2671 class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
2672 + STRING_BYTES (XSTRING (class))
2673 + (STRINGP (subclass)
2674 ? STRING_BYTES (XSTRING (subclass)) : 0)
2675 + 3);
2677 /* Start with emacs.FRAMENAME for the name (the specific one)
2678 and with `Emacs' for the class key (the general one). */
2679 strcpy (name_key, XSTRING (Vx_resource_name)->data);
2680 strcpy (class_key, XSTRING (Vx_resource_class)->data);
2682 strcat (class_key, ".");
2683 strcat (class_key, XSTRING (class)->data);
2685 if (!NILP (component))
2687 strcat (class_key, ".");
2688 strcat (class_key, XSTRING (subclass)->data);
2690 strcat (name_key, ".");
2691 strcat (name_key, XSTRING (component)->data);
2694 strcat (name_key, ".");
2695 strcat (name_key, XSTRING (attribute)->data);
2697 value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
2699 if (value != (char *) 0)
2700 return build_string (value);
2701 else
2702 return Qnil;
2705 /* Used when C code wants a resource value. */
2707 char *
2708 x_get_resource_string (attribute, class)
2709 char *attribute, *class;
2711 char *name_key;
2712 char *class_key;
2713 struct frame *sf = SELECTED_FRAME ();
2715 /* Allocate space for the components, the dots which separate them,
2716 and the final '\0'. */
2717 name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
2718 + strlen (attribute) + 2);
2719 class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
2720 + strlen (class) + 2);
2722 sprintf (name_key, "%s.%s",
2723 XSTRING (Vinvocation_name)->data,
2724 attribute);
2725 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
2727 return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
2728 name_key, class_key);
2731 /* Types we might convert a resource string into. */
2732 enum resource_types
2734 RES_TYPE_NUMBER,
2735 RES_TYPE_FLOAT,
2736 RES_TYPE_BOOLEAN,
2737 RES_TYPE_STRING,
2738 RES_TYPE_SYMBOL
2741 /* Return the value of parameter PARAM.
2743 First search ALIST, then Vdefault_frame_alist, then the X defaults
2744 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2746 Convert the resource to the type specified by desired_type.
2748 If no default is specified, return Qunbound. If you call
2749 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2750 and don't let it get stored in any Lisp-visible variables! */
2752 static Lisp_Object
2753 x_get_arg (dpyinfo, alist, param, attribute, class, type)
2754 struct x_display_info *dpyinfo;
2755 Lisp_Object alist, param;
2756 char *attribute;
2757 char *class;
2758 enum resource_types type;
2760 register Lisp_Object tem;
2762 tem = Fassq (param, alist);
2763 if (EQ (tem, Qnil))
2764 tem = Fassq (param, Vdefault_frame_alist);
2765 if (EQ (tem, Qnil))
2768 if (attribute)
2770 tem = display_x_get_resource (dpyinfo,
2771 build_string (attribute),
2772 build_string (class),
2773 Qnil, Qnil);
2775 if (NILP (tem))
2776 return Qunbound;
2778 switch (type)
2780 case RES_TYPE_NUMBER:
2781 return make_number (atoi (XSTRING (tem)->data));
2783 case RES_TYPE_FLOAT:
2784 return make_float (atof (XSTRING (tem)->data));
2786 case RES_TYPE_BOOLEAN:
2787 tem = Fdowncase (tem);
2788 if (!strcmp (XSTRING (tem)->data, "on")
2789 || !strcmp (XSTRING (tem)->data, "true"))
2790 return Qt;
2791 else
2792 return Qnil;
2794 case RES_TYPE_STRING:
2795 return tem;
2797 case RES_TYPE_SYMBOL:
2798 /* As a special case, we map the values `true' and `on'
2799 to Qt, and `false' and `off' to Qnil. */
2801 Lisp_Object lower;
2802 lower = Fdowncase (tem);
2803 if (!strcmp (XSTRING (lower)->data, "on")
2804 || !strcmp (XSTRING (lower)->data, "true"))
2805 return Qt;
2806 else if (!strcmp (XSTRING (lower)->data, "off")
2807 || !strcmp (XSTRING (lower)->data, "false"))
2808 return Qnil;
2809 else
2810 return Fintern (tem, Qnil);
2813 default:
2814 abort ();
2817 else
2818 return Qunbound;
2820 return Fcdr (tem);
2823 /* Like x_get_arg, but also record the value in f->param_alist. */
2825 static Lisp_Object
2826 x_get_and_record_arg (f, alist, param, attribute, class, type)
2827 struct frame *f;
2828 Lisp_Object alist, param;
2829 char *attribute;
2830 char *class;
2831 enum resource_types type;
2833 Lisp_Object value;
2835 value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
2836 attribute, class, type);
2837 if (! NILP (value))
2838 store_frame_param (f, param, value);
2840 return value;
2843 /* Record in frame F the specified or default value according to ALIST
2844 of the parameter named PROP (a Lisp symbol).
2845 If no value is specified for PROP, look for an X default for XPROP
2846 on the frame named NAME.
2847 If that is not found either, use the value DEFLT. */
2849 static Lisp_Object
2850 x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
2851 struct frame *f;
2852 Lisp_Object alist;
2853 Lisp_Object prop;
2854 Lisp_Object deflt;
2855 char *xprop;
2856 char *xclass;
2857 enum resource_types type;
2859 Lisp_Object tem;
2861 tem = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, prop, xprop, xclass, type);
2862 if (EQ (tem, Qunbound))
2863 tem = deflt;
2864 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2865 return tem;
2869 /* Record in frame F the specified or default value according to ALIST
2870 of the parameter named PROP (a Lisp symbol). If no value is
2871 specified for PROP, look for an X default for XPROP on the frame
2872 named NAME. If that is not found either, use the value DEFLT. */
2874 static Lisp_Object
2875 x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
2876 foreground_p)
2877 struct frame *f;
2878 Lisp_Object alist;
2879 Lisp_Object prop;
2880 char *xprop;
2881 char *xclass;
2882 int foreground_p;
2884 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2885 Lisp_Object tem;
2887 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2888 if (EQ (tem, Qunbound))
2890 #ifdef USE_TOOLKIT_SCROLL_BARS
2892 /* See if an X resource for the scroll bar color has been
2893 specified. */
2894 tem = display_x_get_resource (dpyinfo,
2895 build_string (foreground_p
2896 ? "foreground"
2897 : "background"),
2898 build_string (""),
2899 build_string ("verticalScrollBar"),
2900 build_string (""));
2901 if (!STRINGP (tem))
2903 /* If nothing has been specified, scroll bars will use a
2904 toolkit-dependent default. Because these defaults are
2905 difficult to get at without actually creating a scroll
2906 bar, use nil to indicate that no color has been
2907 specified. */
2908 tem = Qnil;
2911 #else /* not USE_TOOLKIT_SCROLL_BARS */
2913 tem = Qnil;
2915 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2918 x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
2919 return tem;
2924 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
2925 "Parse an X-style geometry string STRING.\n\
2926 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2927 The properties returned may include `top', `left', `height', and `width'.\n\
2928 The value of `left' or `top' may be an integer,\n\
2929 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2930 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2931 (string)
2932 Lisp_Object string;
2934 int geometry, x, y;
2935 unsigned int width, height;
2936 Lisp_Object result;
2938 CHECK_STRING (string, 0);
2940 geometry = XParseGeometry ((char *) XSTRING (string)->data,
2941 &x, &y, &width, &height);
2943 #if 0
2944 if (!!(geometry & XValue) != !!(geometry & YValue))
2945 error ("Must specify both x and y position, or neither");
2946 #endif
2948 result = Qnil;
2949 if (geometry & XValue)
2951 Lisp_Object element;
2953 if (x >= 0 && (geometry & XNegative))
2954 element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
2955 else if (x < 0 && ! (geometry & XNegative))
2956 element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
2957 else
2958 element = Fcons (Qleft, make_number (x));
2959 result = Fcons (element, result);
2962 if (geometry & YValue)
2964 Lisp_Object element;
2966 if (y >= 0 && (geometry & YNegative))
2967 element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
2968 else if (y < 0 && ! (geometry & YNegative))
2969 element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
2970 else
2971 element = Fcons (Qtop, make_number (y));
2972 result = Fcons (element, result);
2975 if (geometry & WidthValue)
2976 result = Fcons (Fcons (Qwidth, make_number (width)), result);
2977 if (geometry & HeightValue)
2978 result = Fcons (Fcons (Qheight, make_number (height)), result);
2980 return result;
2983 /* Calculate the desired size and position of this window,
2984 and return the flags saying which aspects were specified.
2986 This function does not make the coordinates positive. */
2988 #define DEFAULT_ROWS 40
2989 #define DEFAULT_COLS 80
2991 static int
2992 x_figure_window_size (f, parms)
2993 struct frame *f;
2994 Lisp_Object parms;
2996 register Lisp_Object tem0, tem1, tem2;
2997 long window_prompting = 0;
2998 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3000 /* Default values if we fall through.
3001 Actually, if that happens we should get
3002 window manager prompting. */
3003 SET_FRAME_WIDTH (f, DEFAULT_COLS);
3004 f->height = DEFAULT_ROWS;
3005 /* Window managers expect that if program-specified
3006 positions are not (0,0), they're intentional, not defaults. */
3007 f->output_data.x->top_pos = 0;
3008 f->output_data.x->left_pos = 0;
3010 tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
3011 tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
3012 tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
3013 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3015 if (!EQ (tem0, Qunbound))
3017 CHECK_NUMBER (tem0, 0);
3018 f->height = XINT (tem0);
3020 if (!EQ (tem1, Qunbound))
3022 CHECK_NUMBER (tem1, 0);
3023 SET_FRAME_WIDTH (f, XINT (tem1));
3025 if (!NILP (tem2) && !EQ (tem2, Qunbound))
3026 window_prompting |= USSize;
3027 else
3028 window_prompting |= PSize;
3031 f->output_data.x->vertical_scroll_bar_extra
3032 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3034 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
3035 f->output_data.x->flags_areas_extra
3036 = FRAME_FLAGS_AREA_WIDTH (f);
3037 f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
3038 f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
3040 tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
3041 tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
3042 tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
3043 if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
3045 if (EQ (tem0, Qminus))
3047 f->output_data.x->top_pos = 0;
3048 window_prompting |= YNegative;
3050 else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
3051 && CONSP (XCDR (tem0))
3052 && INTEGERP (XCAR (XCDR (tem0))))
3054 f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
3055 window_prompting |= YNegative;
3057 else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
3058 && CONSP (XCDR (tem0))
3059 && INTEGERP (XCAR (XCDR (tem0))))
3061 f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
3063 else if (EQ (tem0, Qunbound))
3064 f->output_data.x->top_pos = 0;
3065 else
3067 CHECK_NUMBER (tem0, 0);
3068 f->output_data.x->top_pos = XINT (tem0);
3069 if (f->output_data.x->top_pos < 0)
3070 window_prompting |= YNegative;
3073 if (EQ (tem1, Qminus))
3075 f->output_data.x->left_pos = 0;
3076 window_prompting |= XNegative;
3078 else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
3079 && CONSP (XCDR (tem1))
3080 && INTEGERP (XCAR (XCDR (tem1))))
3082 f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
3083 window_prompting |= XNegative;
3085 else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
3086 && CONSP (XCDR (tem1))
3087 && INTEGERP (XCAR (XCDR (tem1))))
3089 f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
3091 else if (EQ (tem1, Qunbound))
3092 f->output_data.x->left_pos = 0;
3093 else
3095 CHECK_NUMBER (tem1, 0);
3096 f->output_data.x->left_pos = XINT (tem1);
3097 if (f->output_data.x->left_pos < 0)
3098 window_prompting |= XNegative;
3101 if (!NILP (tem2) && ! EQ (tem2, Qunbound))
3102 window_prompting |= USPosition;
3103 else
3104 window_prompting |= PPosition;
3107 return window_prompting;
3110 #if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
3112 Status
3113 XSetWMProtocols (dpy, w, protocols, count)
3114 Display *dpy;
3115 Window w;
3116 Atom *protocols;
3117 int count;
3119 Atom prop;
3120 prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
3121 if (prop == None) return False;
3122 XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
3123 (unsigned char *) protocols, count);
3124 return True;
3126 #endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
3128 #ifdef USE_X_TOOLKIT
3130 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
3131 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
3132 already be present because of the toolkit (Motif adds some of them,
3133 for example, but Xt doesn't). */
3135 static void
3136 hack_wm_protocols (f, widget)
3137 FRAME_PTR f;
3138 Widget widget;
3140 Display *dpy = XtDisplay (widget);
3141 Window w = XtWindow (widget);
3142 int need_delete = 1;
3143 int need_focus = 1;
3144 int need_save = 1;
3146 BLOCK_INPUT;
3148 Atom type, *atoms = 0;
3149 int format = 0;
3150 unsigned long nitems = 0;
3151 unsigned long bytes_after;
3153 if ((XGetWindowProperty (dpy, w,
3154 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3155 (long)0, (long)100, False, XA_ATOM,
3156 &type, &format, &nitems, &bytes_after,
3157 (unsigned char **) &atoms)
3158 == Success)
3159 && format == 32 && type == XA_ATOM)
3160 while (nitems > 0)
3162 nitems--;
3163 if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
3164 need_delete = 0;
3165 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
3166 need_focus = 0;
3167 else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
3168 need_save = 0;
3170 if (atoms) XFree ((char *) atoms);
3173 Atom props [10];
3174 int count = 0;
3175 if (need_delete)
3176 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3177 if (need_focus)
3178 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
3179 if (need_save)
3180 props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3181 if (count)
3182 XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3183 XA_ATOM, 32, PropModeAppend,
3184 (unsigned char *) props, count);
3186 UNBLOCK_INPUT;
3188 #endif
3192 /* Support routines for XIC (X Input Context). */
3194 #ifdef HAVE_X_I18N
3196 static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
3197 static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
3200 /* Supported XIM styles, ordered by preferenc. */
3202 static XIMStyle supported_xim_styles[] =
3204 XIMPreeditPosition | XIMStatusArea,
3205 XIMPreeditPosition | XIMStatusNothing,
3206 XIMPreeditPosition | XIMStatusNone,
3207 XIMPreeditNothing | XIMStatusArea,
3208 XIMPreeditNothing | XIMStatusNothing,
3209 XIMPreeditNothing | XIMStatusNone,
3210 XIMPreeditNone | XIMStatusArea,
3211 XIMPreeditNone | XIMStatusNothing,
3212 XIMPreeditNone | XIMStatusNone,
3217 /* Create an X fontset on frame F with base font name
3218 BASE_FONTNAME.. */
3220 static XFontSet
3221 xic_create_xfontset (f, base_fontname)
3222 struct frame *f;
3223 char *base_fontname;
3225 XFontSet xfs;
3226 char **missing_list;
3227 int missing_count;
3228 char *def_string;
3230 xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
3231 base_fontname, &missing_list,
3232 &missing_count, &def_string);
3233 if (missing_list)
3234 XFreeStringList (missing_list);
3236 /* No need to free def_string. */
3237 return xfs;
3241 /* Value is the best input style, given user preferences USER (already
3242 checked to be supported by Emacs), and styles supported by the
3243 input method XIM. */
3245 static XIMStyle
3246 best_xim_style (user, xim)
3247 XIMStyles *user;
3248 XIMStyles *xim;
3250 int i, j;
3252 for (i = 0; i < user->count_styles; ++i)
3253 for (j = 0; j < xim->count_styles; ++j)
3254 if (user->supported_styles[i] == xim->supported_styles[j])
3255 return user->supported_styles[i];
3257 /* Return the default style. */
3258 return XIMPreeditNothing | XIMStatusNothing;
3261 /* Create XIC for frame F. */
3263 void
3264 create_frame_xic (f)
3265 struct frame *f;
3267 XIM xim;
3268 XIC xic = NULL;
3269 XFontSet xfs = NULL;
3270 static XIMStyle xic_style;
3272 if (FRAME_XIC (f))
3273 return;
3275 xim = FRAME_X_XIM (f);
3276 if (xim)
3278 XRectangle s_area;
3279 XPoint spot;
3280 XVaNestedList preedit_attr;
3281 XVaNestedList status_attr;
3282 char *base_fontname;
3283 int fontset;
3285 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3286 spot.x = 0; spot.y = 1;
3287 /* Create X fontset. */
3288 fontset = FRAME_FONTSET (f);
3289 if (fontset < 0)
3290 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3291 else
3293 /* Determine the base fontname from the ASCII font name of
3294 FONTSET. */
3295 char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
3296 char *p = ascii_font;
3297 int i;
3299 for (i = 0; *p; p++)
3300 if (*p == '-') i++;
3301 if (i != 14)
3302 /* As the font name doesn't conform to XLFD, we can't
3303 modify it to get a suitable base fontname for the
3304 frame. */
3305 base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
3306 else
3308 int len = strlen (ascii_font) + 1;
3309 char *p1 = NULL;
3311 for (i = 0, p = ascii_font; i < 8; p++)
3313 if (*p == '-')
3315 i++;
3316 if (i == 3)
3317 p1 = p + 1;
3320 base_fontname = (char *) alloca (len);
3321 bzero (base_fontname, len);
3322 strcpy (base_fontname, "-*-*-");
3323 bcopy (p1, base_fontname + 5, p - p1);
3324 strcat (base_fontname, "*-*-*-*-*-*-*");
3327 xfs = xic_create_xfontset (f, base_fontname);
3329 /* Determine XIC style. */
3330 if (xic_style == 0)
3332 XIMStyles supported_list;
3333 supported_list.count_styles = (sizeof supported_xim_styles
3334 / sizeof supported_xim_styles[0]);
3335 supported_list.supported_styles = supported_xim_styles;
3336 xic_style = best_xim_style (&supported_list,
3337 FRAME_X_XIM_STYLES (f));
3340 preedit_attr = XVaCreateNestedList (0,
3341 XNFontSet, xfs,
3342 XNForeground,
3343 FRAME_FOREGROUND_PIXEL (f),
3344 XNBackground,
3345 FRAME_BACKGROUND_PIXEL (f),
3346 (xic_style & XIMPreeditPosition
3347 ? XNSpotLocation
3348 : NULL),
3349 &spot,
3350 NULL);
3351 status_attr = XVaCreateNestedList (0,
3352 XNArea,
3353 &s_area,
3354 XNFontSet,
3355 xfs,
3356 XNForeground,
3357 FRAME_FOREGROUND_PIXEL (f),
3358 XNBackground,
3359 FRAME_BACKGROUND_PIXEL (f),
3360 NULL);
3362 xic = XCreateIC (xim,
3363 XNInputStyle, xic_style,
3364 XNClientWindow, FRAME_X_WINDOW(f),
3365 XNFocusWindow, FRAME_X_WINDOW(f),
3366 XNStatusAttributes, status_attr,
3367 XNPreeditAttributes, preedit_attr,
3368 NULL);
3369 XFree (preedit_attr);
3370 XFree (status_attr);
3373 FRAME_XIC (f) = xic;
3374 FRAME_XIC_STYLE (f) = xic_style;
3375 FRAME_XIC_FONTSET (f) = xfs;
3379 /* Destroy XIC and free XIC fontset of frame F, if any. */
3381 void
3382 free_frame_xic (f)
3383 struct frame *f;
3385 if (FRAME_XIC (f) == NULL)
3386 return;
3388 XDestroyIC (FRAME_XIC (f));
3389 if (FRAME_XIC_FONTSET (f))
3390 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3392 FRAME_XIC (f) = NULL;
3393 FRAME_XIC_FONTSET (f) = NULL;
3397 /* Place preedit area for XIC of window W's frame to specified
3398 pixel position X/Y. X and Y are relative to window W. */
3400 void
3401 xic_set_preeditarea (w, x, y)
3402 struct window *w;
3403 int x, y;
3405 struct frame *f = XFRAME (w->frame);
3406 XVaNestedList attr;
3407 XPoint spot;
3409 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
3410 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
3411 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3412 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3413 XFree (attr);
3417 /* Place status area for XIC in bottom right corner of frame F.. */
3419 void
3420 xic_set_statusarea (f)
3421 struct frame *f;
3423 XIC xic = FRAME_XIC (f);
3424 XVaNestedList attr;
3425 XRectangle area;
3426 XRectangle *needed;
3428 /* Negotiate geometry of status area. If input method has existing
3429 status area, use its current size. */
3430 area.x = area.y = area.width = area.height = 0;
3431 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3432 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3433 XFree (attr);
3435 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3436 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3437 XFree (attr);
3439 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
3441 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3442 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3443 XFree (attr);
3446 area.width = needed->width;
3447 area.height = needed->height;
3448 area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3449 area.y = (PIXEL_HEIGHT (f) - area.height
3450 - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
3451 XFree (needed);
3453 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3454 XSetICValues(xic, XNStatusAttributes, attr, NULL);
3455 XFree (attr);
3459 /* Set X fontset for XIC of frame F, using base font name
3460 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
3462 void
3463 xic_set_xfontset (f, base_fontname)
3464 struct frame *f;
3465 char *base_fontname;
3467 XVaNestedList attr;
3468 XFontSet xfs;
3470 xfs = xic_create_xfontset (f, base_fontname);
3472 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3473 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3474 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3475 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3476 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3477 XFree (attr);
3479 if (FRAME_XIC_FONTSET (f))
3480 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3481 FRAME_XIC_FONTSET (f) = xfs;
3484 #endif /* HAVE_X_I18N */
3488 #ifdef USE_X_TOOLKIT
3490 /* Create and set up the X widget for frame F. */
3492 static void
3493 x_window (f, window_prompting, minibuffer_only)
3494 struct frame *f;
3495 long window_prompting;
3496 int minibuffer_only;
3498 XClassHint class_hints;
3499 XSetWindowAttributes attributes;
3500 unsigned long attribute_mask;
3501 Widget shell_widget;
3502 Widget pane_widget;
3503 Widget frame_widget;
3504 Arg al [25];
3505 int ac;
3507 BLOCK_INPUT;
3509 /* Use the resource name as the top-level widget name
3510 for looking up resources. Make a non-Lisp copy
3511 for the window manager, so GC relocation won't bother it.
3513 Elsewhere we specify the window name for the window manager. */
3516 char *str = (char *) XSTRING (Vx_resource_name)->data;
3517 f->namebuf = (char *) xmalloc (strlen (str) + 1);
3518 strcpy (f->namebuf, str);
3521 ac = 0;
3522 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
3523 XtSetArg (al[ac], XtNinput, 1); ac++;
3524 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3525 XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
3526 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3527 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3528 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3529 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
3530 applicationShellWidgetClass,
3531 FRAME_X_DISPLAY (f), al, ac);
3533 f->output_data.x->widget = shell_widget;
3534 /* maybe_set_screen_title_format (shell_widget); */
3536 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
3537 (widget_value *) NULL,
3538 shell_widget, False,
3539 (lw_callback) NULL,
3540 (lw_callback) NULL,
3541 (lw_callback) NULL,
3542 (lw_callback) NULL);
3544 ac = 0;
3545 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3546 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3547 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3548 XtSetValues (pane_widget, al, ac);
3549 f->output_data.x->column_widget = pane_widget;
3551 /* mappedWhenManaged to false tells to the paned window to not map/unmap
3552 the emacs screen when changing menubar. This reduces flickering. */
3554 ac = 0;
3555 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
3556 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
3557 XtSetArg (al[ac], XtNallowResize, 1); ac++;
3558 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
3559 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
3560 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3561 XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
3562 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3563 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
3564 al, ac);
3566 f->output_data.x->edit_widget = frame_widget;
3568 XtManageChild (frame_widget);
3570 /* Do some needed geometry management. */
3572 int len;
3573 char *tem, shell_position[32];
3574 Arg al[2];
3575 int ac = 0;
3576 int extra_borders = 0;
3577 int menubar_size
3578 = (f->output_data.x->menubar_widget
3579 ? (f->output_data.x->menubar_widget->core.height
3580 + f->output_data.x->menubar_widget->core.border_width)
3581 : 0);
3583 #if 0 /* Experimentally, we now get the right results
3584 for -geometry -0-0 without this. 24 Aug 96, rms. */
3585 if (FRAME_EXTERNAL_MENU_BAR (f))
3587 Dimension ibw = 0;
3588 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3589 menubar_size += ibw;
3591 #endif
3593 f->output_data.x->menubar_height = menubar_size;
3595 #ifndef USE_LUCID
3596 /* Motif seems to need this amount added to the sizes
3597 specified for the shell widget. The Athena/Lucid widgets don't.
3598 Both conclusions reached experimentally. -- rms. */
3599 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3600 &extra_borders, NULL);
3601 extra_borders *= 2;
3602 #endif
3604 /* Convert our geometry parameters into a geometry string
3605 and specify it.
3606 Note that we do not specify here whether the position
3607 is a user-specified or program-specified one.
3608 We pass that information later, in x_wm_set_size_hints. */
3610 int left = f->output_data.x->left_pos;
3611 int xneg = window_prompting & XNegative;
3612 int top = f->output_data.x->top_pos;
3613 int yneg = window_prompting & YNegative;
3614 if (xneg)
3615 left = -left;
3616 if (yneg)
3617 top = -top;
3619 if (window_prompting & USPosition)
3620 sprintf (shell_position, "=%dx%d%c%d%c%d",
3621 PIXEL_WIDTH (f) + extra_borders,
3622 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3623 (xneg ? '-' : '+'), left,
3624 (yneg ? '-' : '+'), top);
3625 else
3626 sprintf (shell_position, "=%dx%d",
3627 PIXEL_WIDTH (f) + extra_borders,
3628 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3631 len = strlen (shell_position) + 1;
3632 /* We don't free this because we don't know whether
3633 it is safe to free it while the frame exists.
3634 It isn't worth the trouble of arranging to free it
3635 when the frame is deleted. */
3636 tem = (char *) xmalloc (len);
3637 strncpy (tem, shell_position, len);
3638 XtSetArg (al[ac], XtNgeometry, tem); ac++;
3639 XtSetValues (shell_widget, al, ac);
3642 XtManageChild (pane_widget);
3643 XtRealizeWidget (shell_widget);
3645 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3647 validate_x_resource_name ();
3649 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3650 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3651 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3653 #ifdef HAVE_X_I18N
3654 FRAME_XIC (f) = NULL;
3655 #ifdef USE_XIM
3656 create_frame_xic (f);
3657 #endif
3658 #endif
3660 f->output_data.x->wm_hints.input = True;
3661 f->output_data.x->wm_hints.flags |= InputHint;
3662 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3663 &f->output_data.x->wm_hints);
3665 hack_wm_protocols (f, shell_widget);
3667 #ifdef HACK_EDITRES
3668 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3669 #endif
3671 /* Do a stupid property change to force the server to generate a
3672 PropertyNotify event so that the event_stream server timestamp will
3673 be initialized to something relevant to the time we created the window.
3675 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3676 FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
3677 XA_ATOM, 32, PropModeAppend,
3678 (unsigned char*) NULL, 0);
3680 /* Make all the standard events reach the Emacs frame. */
3681 attributes.event_mask = STANDARD_EVENT_SET;
3683 #ifdef HAVE_X_I18N
3684 if (FRAME_XIC (f))
3686 /* XIM server might require some X events. */
3687 unsigned long fevent = NoEventMask;
3688 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3689 attributes.event_mask |= fevent;
3691 #endif /* HAVE_X_I18N */
3693 attribute_mask = CWEventMask;
3694 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3695 attribute_mask, &attributes);
3697 XtMapWidget (frame_widget);
3699 /* x_set_name normally ignores requests to set the name if the
3700 requested name is the same as the current name. This is the one
3701 place where that assumption isn't correct; f->name is set, but
3702 the X server hasn't been told. */
3704 Lisp_Object name;
3705 int explicit = f->explicit_name;
3707 f->explicit_name = 0;
3708 name = f->name;
3709 f->name = Qnil;
3710 x_set_name (f, name, explicit);
3713 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3714 f->output_data.x->text_cursor);
3716 UNBLOCK_INPUT;
3718 /* This is a no-op, except under Motif. Make sure main areas are
3719 set to something reasonable, in case we get an error later. */
3720 lw_set_main_areas (pane_widget, 0, frame_widget);
3723 #else /* not USE_X_TOOLKIT */
3725 /* Create and set up the X window for frame F. */
3727 void
3728 x_window (f)
3729 struct frame *f;
3732 XClassHint class_hints;
3733 XSetWindowAttributes attributes;
3734 unsigned long attribute_mask;
3736 attributes.background_pixel = f->output_data.x->background_pixel;
3737 attributes.border_pixel = f->output_data.x->border_pixel;
3738 attributes.bit_gravity = StaticGravity;
3739 attributes.backing_store = NotUseful;
3740 attributes.save_under = True;
3741 attributes.event_mask = STANDARD_EVENT_SET;
3742 attributes.colormap = FRAME_X_COLORMAP (f);
3743 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3744 | CWColormap);
3746 BLOCK_INPUT;
3747 FRAME_X_WINDOW (f)
3748 = XCreateWindow (FRAME_X_DISPLAY (f),
3749 f->output_data.x->parent_desc,
3750 f->output_data.x->left_pos,
3751 f->output_data.x->top_pos,
3752 PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
3753 f->output_data.x->border_width,
3754 CopyFromParent, /* depth */
3755 InputOutput, /* class */
3756 FRAME_X_VISUAL (f),
3757 attribute_mask, &attributes);
3759 #ifdef HAVE_X_I18N
3760 #ifdef USE_XIM
3761 create_frame_xic (f);
3762 if (FRAME_XIC (f))
3764 /* XIM server might require some X events. */
3765 unsigned long fevent = NoEventMask;
3766 XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3767 attributes.event_mask |= fevent;
3768 attribute_mask = CWEventMask;
3769 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3770 attribute_mask, &attributes);
3772 #endif
3773 #endif /* HAVE_X_I18N */
3775 validate_x_resource_name ();
3777 class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
3778 class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
3779 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3781 /* The menubar is part of the ordinary display;
3782 it does not count in addition to the height of the window. */
3783 f->output_data.x->menubar_height = 0;
3785 /* This indicates that we use the "Passive Input" input model.
3786 Unless we do this, we don't get the Focus{In,Out} events that we
3787 need to draw the cursor correctly. Accursed bureaucrats.
3788 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3790 f->output_data.x->wm_hints.input = True;
3791 f->output_data.x->wm_hints.flags |= InputHint;
3792 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3793 &f->output_data.x->wm_hints);
3794 f->output_data.x->wm_hints.icon_pixmap = None;
3796 /* Request "save yourself" and "delete window" commands from wm. */
3798 Atom protocols[2];
3799 protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3800 protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3801 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3804 /* x_set_name normally ignores requests to set the name if the
3805 requested name is the same as the current name. This is the one
3806 place where that assumption isn't correct; f->name is set, but
3807 the X server hasn't been told. */
3809 Lisp_Object name;
3810 int explicit = f->explicit_name;
3812 f->explicit_name = 0;
3813 name = f->name;
3814 f->name = Qnil;
3815 x_set_name (f, name, explicit);
3818 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3819 f->output_data.x->text_cursor);
3821 UNBLOCK_INPUT;
3823 if (FRAME_X_WINDOW (f) == 0)
3824 error ("Unable to create window");
3827 #endif /* not USE_X_TOOLKIT */
3829 /* Handle the icon stuff for this window. Perhaps later we might
3830 want an x_set_icon_position which can be called interactively as
3831 well. */
3833 static void
3834 x_icon (f, parms)
3835 struct frame *f;
3836 Lisp_Object parms;
3838 Lisp_Object icon_x, icon_y;
3839 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3841 /* Set the position of the icon. Note that twm groups all
3842 icons in an icon window. */
3843 icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3844 icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3845 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3847 CHECK_NUMBER (icon_x, 0);
3848 CHECK_NUMBER (icon_y, 0);
3850 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3851 error ("Both left and top icon corners of icon must be specified");
3853 BLOCK_INPUT;
3855 if (! EQ (icon_x, Qunbound))
3856 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3858 /* Start up iconic or window? */
3859 x_wm_set_window_state
3860 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3861 Qicon)
3862 ? IconicState
3863 : NormalState));
3865 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
3866 ? f->icon_name
3867 : f->name))->data);
3869 UNBLOCK_INPUT;
3872 /* Make the GCs needed for this window, setting the
3873 background, border and mouse colors; also create the
3874 mouse cursor and the gray border tile. */
3876 static char cursor_bits[] =
3878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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
3884 static void
3885 x_make_gc (f)
3886 struct frame *f;
3888 XGCValues gc_values;
3890 BLOCK_INPUT;
3892 /* Create the GCs of this frame.
3893 Note that many default values are used. */
3895 /* Normal video */
3896 gc_values.font = f->output_data.x->font->fid;
3897 gc_values.foreground = f->output_data.x->foreground_pixel;
3898 gc_values.background = f->output_data.x->background_pixel;
3899 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3900 f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
3901 FRAME_X_WINDOW (f),
3902 GCLineWidth | GCFont
3903 | GCForeground | GCBackground,
3904 &gc_values);
3906 /* Reverse video style. */
3907 gc_values.foreground = f->output_data.x->background_pixel;
3908 gc_values.background = f->output_data.x->foreground_pixel;
3909 f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
3910 FRAME_X_WINDOW (f),
3911 GCFont | GCForeground | GCBackground
3912 | GCLineWidth,
3913 &gc_values);
3915 /* Cursor has cursor-color background, background-color foreground. */
3916 gc_values.foreground = f->output_data.x->background_pixel;
3917 gc_values.background = f->output_data.x->cursor_pixel;
3918 gc_values.fill_style = FillOpaqueStippled;
3919 gc_values.stipple
3920 = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
3921 FRAME_X_DISPLAY_INFO (f)->root_window,
3922 cursor_bits, 16, 16);
3923 f->output_data.x->cursor_gc
3924 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3925 (GCFont | GCForeground | GCBackground
3926 | GCFillStyle /* | GCStipple */ | GCLineWidth),
3927 &gc_values);
3929 /* Reliefs. */
3930 f->output_data.x->white_relief.gc = 0;
3931 f->output_data.x->black_relief.gc = 0;
3933 /* Create the gray border tile used when the pointer is not in
3934 the frame. Since this depends on the frame's pixel values,
3935 this must be done on a per-frame basis. */
3936 f->output_data.x->border_tile
3937 = (XCreatePixmapFromBitmapData
3938 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
3939 gray_bits, gray_width, gray_height,
3940 f->output_data.x->foreground_pixel,
3941 f->output_data.x->background_pixel,
3942 DefaultDepth (FRAME_X_DISPLAY (f),
3943 XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
3945 UNBLOCK_INPUT;
3948 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3949 1, 1, 0,
3950 "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
3951 Returns an Emacs frame object.\n\
3952 ALIST is an alist of frame parameters.\n\
3953 If the parameters specify that the frame should not have a minibuffer,\n\
3954 and do not specify a specific minibuffer window to use,\n\
3955 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
3956 be shared by the new frame.\n\
3958 This function is an internal primitive--use `make-frame' instead.")
3959 (parms)
3960 Lisp_Object parms;
3962 struct frame *f;
3963 Lisp_Object frame, tem;
3964 Lisp_Object name;
3965 int minibuffer_only = 0;
3966 long window_prompting = 0;
3967 int width, height;
3968 int count = specpdl_ptr - specpdl;
3969 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3970 Lisp_Object display;
3971 struct x_display_info *dpyinfo = NULL;
3972 Lisp_Object parent;
3973 struct kboard *kb;
3975 check_x ();
3977 /* Use this general default value to start with
3978 until we know if this frame has a specified name. */
3979 Vx_resource_name = Vinvocation_name;
3981 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3982 if (EQ (display, Qunbound))
3983 display = Qnil;
3984 dpyinfo = check_x_display_info (display);
3985 #ifdef MULTI_KBOARD
3986 kb = dpyinfo->kboard;
3987 #else
3988 kb = &the_only_kboard;
3989 #endif
3991 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3992 if (!STRINGP (name)
3993 && ! EQ (name, Qunbound)
3994 && ! NILP (name))
3995 error ("Invalid frame name--not a string or nil");
3997 if (STRINGP (name))
3998 Vx_resource_name = name;
4000 /* See if parent window is specified. */
4001 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4002 if (EQ (parent, Qunbound))
4003 parent = Qnil;
4004 if (! NILP (parent))
4005 CHECK_NUMBER (parent, 0);
4007 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4008 /* No need to protect DISPLAY because that's not used after passing
4009 it to make_frame_without_minibuffer. */
4010 frame = Qnil;
4011 GCPRO4 (parms, parent, name, frame);
4012 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
4013 RES_TYPE_SYMBOL);
4014 if (EQ (tem, Qnone) || NILP (tem))
4015 f = make_frame_without_minibuffer (Qnil, kb, display);
4016 else if (EQ (tem, Qonly))
4018 f = make_minibuffer_frame ();
4019 minibuffer_only = 1;
4021 else if (WINDOWP (tem))
4022 f = make_frame_without_minibuffer (tem, kb, display);
4023 else
4024 f = make_frame (1);
4026 XSETFRAME (frame, f);
4028 /* Note that X Windows does support scroll bars. */
4029 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4031 f->output_method = output_x_window;
4032 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
4033 bzero (f->output_data.x, sizeof (struct x_output));
4034 f->output_data.x->icon_bitmap = -1;
4035 f->output_data.x->fontset = -1;
4036 f->output_data.x->scroll_bar_foreground_pixel = -1;
4037 f->output_data.x->scroll_bar_background_pixel = -1;
4039 f->icon_name
4040 = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
4041 RES_TYPE_STRING);
4042 if (! STRINGP (f->icon_name))
4043 f->icon_name = Qnil;
4045 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
4046 #ifdef MULTI_KBOARD
4047 FRAME_KBOARD (f) = kb;
4048 #endif
4050 /* These colors will be set anyway later, but it's important
4051 to get the color reference counts right, so initialize them! */
4053 Lisp_Object black;
4054 struct gcpro gcpro1;
4056 black = build_string ("black");
4057 GCPRO1 (black);
4058 f->output_data.x->foreground_pixel
4059 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4060 f->output_data.x->background_pixel
4061 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4062 f->output_data.x->cursor_pixel
4063 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4064 f->output_data.x->cursor_foreground_pixel
4065 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4066 f->output_data.x->border_pixel
4067 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4068 f->output_data.x->mouse_pixel
4069 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4070 UNGCPRO;
4073 /* Specify the parent under which to make this X window. */
4075 if (!NILP (parent))
4077 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
4078 f->output_data.x->explicit_parent = 1;
4080 else
4082 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4083 f->output_data.x->explicit_parent = 0;
4086 /* Set the name; the functions to which we pass f expect the name to
4087 be set. */
4088 if (EQ (name, Qunbound) || NILP (name))
4090 f->name = build_string (dpyinfo->x_id_name);
4091 f->explicit_name = 0;
4093 else
4095 f->name = name;
4096 f->explicit_name = 1;
4097 /* use the frame's title when getting resources for this frame. */
4098 specbind (Qx_resource_name, name);
4101 /* Extract the window parameters from the supplied values
4102 that are needed to determine window geometry. */
4104 Lisp_Object font;
4106 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4108 BLOCK_INPUT;
4109 /* First, try whatever font the caller has specified. */
4110 if (STRINGP (font))
4112 tem = Fquery_fontset (font, Qnil);
4113 if (STRINGP (tem))
4114 font = x_new_fontset (f, XSTRING (tem)->data);
4115 else
4116 font = x_new_font (f, XSTRING (font)->data);
4119 /* Try out a font which we hope has bold and italic variations. */
4120 if (!STRINGP (font))
4121 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
4122 if (!STRINGP (font))
4123 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4124 if (! STRINGP (font))
4125 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
4126 if (! STRINGP (font))
4127 /* This was formerly the first thing tried, but it finds too many fonts
4128 and takes too long. */
4129 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
4130 /* If those didn't work, look for something which will at least work. */
4131 if (! STRINGP (font))
4132 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
4133 UNBLOCK_INPUT;
4134 if (! STRINGP (font))
4135 font = build_string ("fixed");
4137 x_default_parameter (f, parms, Qfont, font,
4138 "font", "Font", RES_TYPE_STRING);
4141 #ifdef USE_LUCID
4142 /* Prevent lwlib/xlwmenu.c from crashing because of a bug
4143 whereby it fails to get any font. */
4144 xlwmenu_default_font = f->output_data.x->font;
4145 #endif
4147 x_default_parameter (f, parms, Qborder_width, make_number (2),
4148 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4150 /* This defaults to 2 in order to match xterm. We recognize either
4151 internalBorderWidth or internalBorder (which is what xterm calls
4152 it). */
4153 if (NILP (Fassq (Qinternal_border_width, parms)))
4155 Lisp_Object value;
4157 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4158 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4159 if (! EQ (value, Qunbound))
4160 parms = Fcons (Fcons (Qinternal_border_width, value),
4161 parms);
4163 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4164 "internalBorderWidth", "internalBorderWidth",
4165 RES_TYPE_NUMBER);
4166 x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
4167 "verticalScrollBars", "ScrollBars",
4168 RES_TYPE_SYMBOL);
4170 /* Also do the stuff which must be set before the window exists. */
4171 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4172 "foreground", "Foreground", RES_TYPE_STRING);
4173 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4174 "background", "Background", RES_TYPE_STRING);
4175 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4176 "pointerColor", "Foreground", RES_TYPE_STRING);
4177 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4178 "cursorColor", "Foreground", RES_TYPE_STRING);
4179 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4180 "borderColor", "BorderColor", RES_TYPE_STRING);
4181 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
4182 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4183 x_default_parameter (f, parms, Qline_spacing, Qnil,
4184 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4186 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
4187 "scrollBarForeground",
4188 "ScrollBarForeground", 1);
4189 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
4190 "scrollBarBackground",
4191 "ScrollBarBackground", 0);
4193 /* Init faces before x_default_parameter is called for scroll-bar
4194 parameters because that function calls x_set_scroll_bar_width,
4195 which calls change_frame_size, which calls Fset_window_buffer,
4196 which runs hooks, which call Fvertical_motion. At the end, we
4197 end up in init_iterator with a null face cache, which should not
4198 happen. */
4199 init_frame_faces (f);
4201 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
4202 "menuBar", "MenuBar", RES_TYPE_NUMBER);
4203 x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
4204 "toolBar", "ToolBar", RES_TYPE_NUMBER);
4205 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4206 "bufferPredicate", "BufferPredicate",
4207 RES_TYPE_SYMBOL);
4208 x_default_parameter (f, parms, Qtitle, Qnil,
4209 "title", "Title", RES_TYPE_STRING);
4211 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4212 window_prompting = x_figure_window_size (f, parms);
4214 if (window_prompting & XNegative)
4216 if (window_prompting & YNegative)
4217 f->output_data.x->win_gravity = SouthEastGravity;
4218 else
4219 f->output_data.x->win_gravity = NorthEastGravity;
4221 else
4223 if (window_prompting & YNegative)
4224 f->output_data.x->win_gravity = SouthWestGravity;
4225 else
4226 f->output_data.x->win_gravity = NorthWestGravity;
4229 f->output_data.x->size_hint_flags = window_prompting;
4231 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4232 f->no_split = minibuffer_only || EQ (tem, Qt);
4234 /* Create the X widget or window. Add the tool-bar height to the
4235 initial frame height so that the user gets a text display area of
4236 the size he specified with -g or via .Xdefaults. Later changes
4237 of the tool-bar height don't change the frame size. This is done
4238 so that users can create tall Emacs frames without having to
4239 guess how tall the tool-bar will get. */
4240 f->height += FRAME_TOOL_BAR_LINES (f);
4242 #ifdef USE_X_TOOLKIT
4243 x_window (f, window_prompting, minibuffer_only);
4244 #else
4245 x_window (f);
4246 #endif
4248 x_icon (f, parms);
4249 x_make_gc (f);
4251 /* Now consider the frame official. */
4252 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4253 Vframe_list = Fcons (frame, Vframe_list);
4255 /* We need to do this after creating the X window, so that the
4256 icon-creation functions can say whose icon they're describing. */
4257 x_default_parameter (f, parms, Qicon_type, Qnil,
4258 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4260 x_default_parameter (f, parms, Qauto_raise, Qnil,
4261 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4262 x_default_parameter (f, parms, Qauto_lower, Qnil,
4263 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4264 x_default_parameter (f, parms, Qcursor_type, Qbox,
4265 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4266 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4267 "scrollBarWidth", "ScrollBarWidth",
4268 RES_TYPE_NUMBER);
4270 /* Dimensions, especially f->height, must be done via change_frame_size.
4271 Change will not be effected unless different from the current
4272 f->height. */
4273 width = f->width;
4274 height = f->height;
4275 f->height = 0;
4276 SET_FRAME_WIDTH (f, 0);
4277 change_frame_size (f, height, width, 1, 0, 0);
4279 #ifdef USE_X_TOOLKIT
4280 /* Create the menu bar. */
4281 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4283 /* If this signals an error, we haven't set size hints for the
4284 frame and we didn't make it visible. */
4285 initialize_frame_menubar (f);
4287 /* This is a no-op, except under Motif where it arranges the
4288 main window for the widgets on it. */
4289 lw_set_main_areas (f->output_data.x->column_widget,
4290 f->output_data.x->menubar_widget,
4291 f->output_data.x->edit_widget);
4293 #endif /* USE_X_TOOLKIT */
4295 /* Tell the server what size and position, etc, we want, and how
4296 badly we want them. This should be done after we have the menu
4297 bar so that its size can be taken into account. */
4298 BLOCK_INPUT;
4299 x_wm_set_size_hint (f, window_prompting, 0);
4300 UNBLOCK_INPUT;
4302 /* Make the window appear on the frame and enable display, unless
4303 the caller says not to. However, with explicit parent, Emacs
4304 cannot control visibility, so don't try. */
4305 if (! f->output_data.x->explicit_parent)
4307 Lisp_Object visibility;
4309 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4310 RES_TYPE_SYMBOL);
4311 if (EQ (visibility, Qunbound))
4312 visibility = Qt;
4314 if (EQ (visibility, Qicon))
4315 x_iconify_frame (f);
4316 else if (! NILP (visibility))
4317 x_make_frame_visible (f);
4318 else
4319 /* Must have been Qnil. */
4323 UNGCPRO;
4324 return unbind_to (count, frame);
4327 /* FRAME is used only to get a handle on the X display. We don't pass the
4328 display info directly because we're called from frame.c, which doesn't
4329 know about that structure. */
4331 Lisp_Object
4332 x_get_focus_frame (frame)
4333 struct frame *frame;
4335 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
4336 Lisp_Object xfocus;
4337 if (! dpyinfo->x_focus_frame)
4338 return Qnil;
4340 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4341 return xfocus;
4345 /* In certain situations, when the window manager follows a
4346 click-to-focus policy, there seems to be no way around calling
4347 XSetInputFocus to give another frame the input focus .
4349 In an ideal world, XSetInputFocus should generally be avoided so
4350 that applications don't interfere with the window manager's focus
4351 policy. But I think it's okay to use when it's clearly done
4352 following a user-command. */
4354 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4355 "Set the input focus to FRAME.\n\
4356 FRAME nil means use the selected frame.")
4357 (frame)
4358 Lisp_Object frame;
4360 struct frame *f = check_x_frame (frame);
4361 Display *dpy = FRAME_X_DISPLAY (f);
4362 int count;
4364 BLOCK_INPUT;
4365 count = x_catch_errors (dpy);
4366 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4367 RevertToParent, CurrentTime);
4368 x_uncatch_errors (dpy, count);
4369 UNBLOCK_INPUT;
4371 return Qnil;
4375 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4376 "Internal function called by `color-defined-p', which see.")
4377 (color, frame)
4378 Lisp_Object color, frame;
4380 XColor foo;
4381 FRAME_PTR f = check_x_frame (frame);
4383 CHECK_STRING (color, 1);
4385 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4386 return Qt;
4387 else
4388 return Qnil;
4391 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4392 "Internal function called by `color-values', which see.")
4393 (color, frame)
4394 Lisp_Object color, frame;
4396 XColor foo;
4397 FRAME_PTR f = check_x_frame (frame);
4399 CHECK_STRING (color, 1);
4401 if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
4403 Lisp_Object rgb[3];
4405 rgb[0] = make_number (foo.red);
4406 rgb[1] = make_number (foo.green);
4407 rgb[2] = make_number (foo.blue);
4408 return Flist (3, rgb);
4410 else
4411 return Qnil;
4414 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4415 "Internal function called by `display-color-p', which see.")
4416 (display)
4417 Lisp_Object display;
4419 struct x_display_info *dpyinfo = check_x_display_info (display);
4421 if (dpyinfo->n_planes <= 2)
4422 return Qnil;
4424 switch (dpyinfo->visual->class)
4426 case StaticColor:
4427 case PseudoColor:
4428 case TrueColor:
4429 case DirectColor:
4430 return Qt;
4432 default:
4433 return Qnil;
4437 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4438 0, 1, 0,
4439 "Return t if the X display supports shades of gray.\n\
4440 Note that color displays do support shades of gray.\n\
4441 The optional argument DISPLAY specifies which display to ask about.\n\
4442 DISPLAY should be either a frame or a display name (a string).\n\
4443 If omitted or nil, that stands for the selected frame's display.")
4444 (display)
4445 Lisp_Object display;
4447 struct x_display_info *dpyinfo = check_x_display_info (display);
4449 if (dpyinfo->n_planes <= 1)
4450 return Qnil;
4452 switch (dpyinfo->visual->class)
4454 case StaticColor:
4455 case PseudoColor:
4456 case TrueColor:
4457 case DirectColor:
4458 case StaticGray:
4459 case GrayScale:
4460 return Qt;
4462 default:
4463 return Qnil;
4467 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4468 0, 1, 0,
4469 "Returns the width in pixels of the X display DISPLAY.\n\
4470 The optional argument DISPLAY specifies which display to ask about.\n\
4471 DISPLAY should be either a frame or a display name (a string).\n\
4472 If omitted or nil, that stands for the selected frame's display.")
4473 (display)
4474 Lisp_Object display;
4476 struct x_display_info *dpyinfo = check_x_display_info (display);
4478 return make_number (dpyinfo->width);
4481 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4482 Sx_display_pixel_height, 0, 1, 0,
4483 "Returns the height in pixels of the X display DISPLAY.\n\
4484 The optional argument DISPLAY specifies which display to ask about.\n\
4485 DISPLAY should be either a frame or a display name (a string).\n\
4486 If omitted or nil, that stands for the selected frame's display.")
4487 (display)
4488 Lisp_Object display;
4490 struct x_display_info *dpyinfo = check_x_display_info (display);
4492 return make_number (dpyinfo->height);
4495 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4496 0, 1, 0,
4497 "Returns the number of bitplanes of the X display DISPLAY.\n\
4498 The optional argument DISPLAY specifies which display to ask about.\n\
4499 DISPLAY should be either a frame or a display name (a string).\n\
4500 If omitted or nil, that stands for the selected frame's display.")
4501 (display)
4502 Lisp_Object display;
4504 struct x_display_info *dpyinfo = check_x_display_info (display);
4506 return make_number (dpyinfo->n_planes);
4509 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4510 0, 1, 0,
4511 "Returns the number of color cells of the X display DISPLAY.\n\
4512 The optional argument DISPLAY specifies which display to ask about.\n\
4513 DISPLAY should be either a frame or a display name (a string).\n\
4514 If omitted or nil, that stands for the selected frame's display.")
4515 (display)
4516 Lisp_Object display;
4518 struct x_display_info *dpyinfo = check_x_display_info (display);
4520 return make_number (DisplayCells (dpyinfo->display,
4521 XScreenNumberOfScreen (dpyinfo->screen)));
4524 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4525 Sx_server_max_request_size,
4526 0, 1, 0,
4527 "Returns the maximum request size of the X server of display DISPLAY.\n\
4528 The optional argument DISPLAY specifies which display to ask about.\n\
4529 DISPLAY should be either a frame or a display name (a string).\n\
4530 If omitted or nil, that stands for the selected frame's display.")
4531 (display)
4532 Lisp_Object display;
4534 struct x_display_info *dpyinfo = check_x_display_info (display);
4536 return make_number (MAXREQUEST (dpyinfo->display));
4539 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4540 "Returns the vendor ID string of the X server of display DISPLAY.\n\
4541 The optional argument DISPLAY specifies which display to ask about.\n\
4542 DISPLAY should be either a frame or a display name (a string).\n\
4543 If omitted or nil, that stands for the selected frame's display.")
4544 (display)
4545 Lisp_Object display;
4547 struct x_display_info *dpyinfo = check_x_display_info (display);
4548 char *vendor = ServerVendor (dpyinfo->display);
4550 if (! vendor) vendor = "";
4551 return build_string (vendor);
4554 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4555 "Returns the version numbers of the X server of display DISPLAY.\n\
4556 The value is a list of three integers: the major and minor\n\
4557 version numbers of the X Protocol in use, and the vendor-specific release\n\
4558 number. See also the function `x-server-vendor'.\n\n\
4559 The optional argument DISPLAY specifies which display to ask about.\n\
4560 DISPLAY should be either a frame or a display name (a string).\n\
4561 If omitted or nil, that stands for the selected frame's display.")
4562 (display)
4563 Lisp_Object display;
4565 struct x_display_info *dpyinfo = check_x_display_info (display);
4566 Display *dpy = dpyinfo->display;
4568 return Fcons (make_number (ProtocolVersion (dpy)),
4569 Fcons (make_number (ProtocolRevision (dpy)),
4570 Fcons (make_number (VendorRelease (dpy)), Qnil)));
4573 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4574 "Returns the number of screens on the X server of display DISPLAY.\n\
4575 The optional argument DISPLAY specifies which display to ask about.\n\
4576 DISPLAY should be either a frame or a display name (a string).\n\
4577 If omitted or nil, that stands for the selected frame's display.")
4578 (display)
4579 Lisp_Object display;
4581 struct x_display_info *dpyinfo = check_x_display_info (display);
4583 return make_number (ScreenCount (dpyinfo->display));
4586 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4587 "Returns the height in millimeters of the X display DISPLAY.\n\
4588 The optional argument DISPLAY specifies which display to ask about.\n\
4589 DISPLAY should be either a frame or a display name (a string).\n\
4590 If omitted or nil, that stands for the selected frame's display.")
4591 (display)
4592 Lisp_Object display;
4594 struct x_display_info *dpyinfo = check_x_display_info (display);
4596 return make_number (HeightMMOfScreen (dpyinfo->screen));
4599 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4600 "Returns the width in millimeters of the X display DISPLAY.\n\
4601 The optional argument DISPLAY specifies which display to ask about.\n\
4602 DISPLAY should be either a frame or a display name (a string).\n\
4603 If omitted or nil, that stands for the selected frame's display.")
4604 (display)
4605 Lisp_Object display;
4607 struct x_display_info *dpyinfo = check_x_display_info (display);
4609 return make_number (WidthMMOfScreen (dpyinfo->screen));
4612 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4613 Sx_display_backing_store, 0, 1, 0,
4614 "Returns an indication of whether X display DISPLAY does backing store.\n\
4615 The value may be `always', `when-mapped', or `not-useful'.\n\
4616 The optional argument DISPLAY specifies which display to ask about.\n\
4617 DISPLAY should be either a frame or a display name (a string).\n\
4618 If omitted or nil, that stands for the selected frame's display.")
4619 (display)
4620 Lisp_Object display;
4622 struct x_display_info *dpyinfo = check_x_display_info (display);
4623 Lisp_Object result;
4625 switch (DoesBackingStore (dpyinfo->screen))
4627 case Always:
4628 result = intern ("always");
4629 break;
4631 case WhenMapped:
4632 result = intern ("when-mapped");
4633 break;
4635 case NotUseful:
4636 result = intern ("not-useful");
4637 break;
4639 default:
4640 error ("Strange value for BackingStore parameter of screen");
4641 result = Qnil;
4644 return result;
4647 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4648 Sx_display_visual_class, 0, 1, 0,
4649 "Returns the visual class of the X display DISPLAY.\n\
4650 The value is one of the symbols `static-gray', `gray-scale',\n\
4651 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
4652 The optional argument DISPLAY specifies which display to ask about.\n\
4653 DISPLAY should be either a frame or a display name (a string).\n\
4654 If omitted or nil, that stands for the selected frame's display.")
4655 (display)
4656 Lisp_Object display;
4658 struct x_display_info *dpyinfo = check_x_display_info (display);
4659 Lisp_Object result;
4661 switch (dpyinfo->visual->class)
4663 case StaticGray:
4664 result = intern ("static-gray");
4665 break;
4666 case GrayScale:
4667 result = intern ("gray-scale");
4668 break;
4669 case StaticColor:
4670 result = intern ("static-color");
4671 break;
4672 case PseudoColor:
4673 result = intern ("pseudo-color");
4674 break;
4675 case TrueColor:
4676 result = intern ("true-color");
4677 break;
4678 case DirectColor:
4679 result = intern ("direct-color");
4680 break;
4681 default:
4682 error ("Display has an unknown visual class");
4683 result = Qnil;
4686 return result;
4689 DEFUN ("x-display-save-under", Fx_display_save_under,
4690 Sx_display_save_under, 0, 1, 0,
4691 "Returns t if the X display DISPLAY supports the save-under feature.\n\
4692 The optional argument DISPLAY specifies which display to ask about.\n\
4693 DISPLAY should be either a frame or a display name (a string).\n\
4694 If omitted or nil, that stands for the selected frame's display.")
4695 (display)
4696 Lisp_Object display;
4698 struct x_display_info *dpyinfo = check_x_display_info (display);
4700 if (DoesSaveUnders (dpyinfo->screen) == True)
4701 return Qt;
4702 else
4703 return Qnil;
4707 x_pixel_width (f)
4708 register struct frame *f;
4710 return PIXEL_WIDTH (f);
4714 x_pixel_height (f)
4715 register struct frame *f;
4717 return PIXEL_HEIGHT (f);
4721 x_char_width (f)
4722 register struct frame *f;
4724 return FONT_WIDTH (f->output_data.x->font);
4728 x_char_height (f)
4729 register struct frame *f;
4731 return f->output_data.x->line_height;
4735 x_screen_planes (f)
4736 register struct frame *f;
4738 return FRAME_X_DISPLAY_INFO (f)->n_planes;
4743 /************************************************************************
4744 X Displays
4745 ************************************************************************/
4748 /* Mapping visual names to visuals. */
4750 static struct visual_class
4752 char *name;
4753 int class;
4755 visual_classes[] =
4757 {"StaticGray", StaticGray},
4758 {"GrayScale", GrayScale},
4759 {"StaticColor", StaticColor},
4760 {"PseudoColor", PseudoColor},
4761 {"TrueColor", TrueColor},
4762 {"DirectColor", DirectColor},
4763 NULL
4767 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4769 /* Value is the screen number of screen SCR. This is a substitute for
4770 the X function with the same name when that doesn't exist. */
4773 XScreenNumberOfScreen (scr)
4774 register Screen *scr;
4776 Display *dpy = scr->display;
4777 int i;
4779 for (i = 0; i < dpy->nscreens; ++i)
4780 if (scr == dpy->screens[i])
4781 break;
4783 return i;
4786 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4789 /* Select the visual that should be used on display DPYINFO. Set
4790 members of DPYINFO appropriately. Called from x_term_init. */
4792 void
4793 select_visual (dpyinfo)
4794 struct x_display_info *dpyinfo;
4796 Display *dpy = dpyinfo->display;
4797 Screen *screen = dpyinfo->screen;
4798 Lisp_Object value;
4800 /* See if a visual is specified. */
4801 value = display_x_get_resource (dpyinfo,
4802 build_string ("visualClass"),
4803 build_string ("VisualClass"),
4804 Qnil, Qnil);
4805 if (STRINGP (value))
4807 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4808 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4809 depth, a decimal number. NAME is compared with case ignored. */
4810 char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
4811 char *dash;
4812 int i, class = -1;
4813 XVisualInfo vinfo;
4815 strcpy (s, XSTRING (value)->data);
4816 dash = index (s, '-');
4817 if (dash)
4819 dpyinfo->n_planes = atoi (dash + 1);
4820 *dash = '\0';
4822 else
4823 /* We won't find a matching visual with depth 0, so that
4824 an error will be printed below. */
4825 dpyinfo->n_planes = 0;
4827 /* Determine the visual class. */
4828 for (i = 0; visual_classes[i].name; ++i)
4829 if (xstricmp (s, visual_classes[i].name) == 0)
4831 class = visual_classes[i].class;
4832 break;
4835 /* Look up a matching visual for the specified class. */
4836 if (class == -1
4837 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4838 dpyinfo->n_planes, class, &vinfo))
4839 fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
4841 dpyinfo->visual = vinfo.visual;
4843 else
4845 int n_visuals;
4846 XVisualInfo *vinfo, vinfo_template;
4848 dpyinfo->visual = DefaultVisualOfScreen (screen);
4850 #ifdef HAVE_X11R4
4851 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
4852 #else
4853 vinfo_template.visualid = dpyinfo->visual->visualid;
4854 #endif
4855 vinfo_template.screen = XScreenNumberOfScreen (screen);
4856 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
4857 &vinfo_template, &n_visuals);
4858 if (n_visuals != 1)
4859 fatal ("Can't get proper X visual info");
4861 dpyinfo->n_planes = vinfo->depth;
4862 XFree ((char *) vinfo);
4867 /* Return the X display structure for the display named NAME.
4868 Open a new connection if necessary. */
4870 struct x_display_info *
4871 x_display_info_for_name (name)
4872 Lisp_Object name;
4874 Lisp_Object names;
4875 struct x_display_info *dpyinfo;
4877 CHECK_STRING (name, 0);
4879 if (! EQ (Vwindow_system, intern ("x")))
4880 error ("Not using X Windows");
4882 for (dpyinfo = x_display_list, names = x_display_name_list;
4883 dpyinfo;
4884 dpyinfo = dpyinfo->next, names = XCDR (names))
4886 Lisp_Object tem;
4887 tem = Fstring_equal (XCAR (XCAR (names)), name);
4888 if (!NILP (tem))
4889 return dpyinfo;
4892 /* Use this general default value to start with. */
4893 Vx_resource_name = Vinvocation_name;
4895 validate_x_resource_name ();
4897 dpyinfo = x_term_init (name, (unsigned char *)0,
4898 (char *) XSTRING (Vx_resource_name)->data);
4900 if (dpyinfo == 0)
4901 error ("Cannot connect to X server %s", XSTRING (name)->data);
4903 x_in_use = 1;
4904 XSETFASTINT (Vwindow_system_version, 11);
4906 return dpyinfo;
4910 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4911 1, 3, 0, "Open a connection to an X server.\n\
4912 DISPLAY is the name of the display to connect to.\n\
4913 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
4914 If the optional third arg MUST-SUCCEED is non-nil,\n\
4915 terminate Emacs if we can't open the connection.")
4916 (display, xrm_string, must_succeed)
4917 Lisp_Object display, xrm_string, must_succeed;
4919 unsigned char *xrm_option;
4920 struct x_display_info *dpyinfo;
4922 CHECK_STRING (display, 0);
4923 if (! NILP (xrm_string))
4924 CHECK_STRING (xrm_string, 1);
4926 if (! EQ (Vwindow_system, intern ("x")))
4927 error ("Not using X Windows");
4929 if (! NILP (xrm_string))
4930 xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
4931 else
4932 xrm_option = (unsigned char *) 0;
4934 validate_x_resource_name ();
4936 /* This is what opens the connection and sets x_current_display.
4937 This also initializes many symbols, such as those used for input. */
4938 dpyinfo = x_term_init (display, xrm_option,
4939 (char *) XSTRING (Vx_resource_name)->data);
4941 if (dpyinfo == 0)
4943 if (!NILP (must_succeed))
4944 fatal ("Cannot connect to X server %s.\n\
4945 Check the DISPLAY environment variable or use `-d'.\n\
4946 Also use the `xhost' program to verify that it is set to permit\n\
4947 connections from your machine.\n",
4948 XSTRING (display)->data);
4949 else
4950 error ("Cannot connect to X server %s", XSTRING (display)->data);
4953 x_in_use = 1;
4955 XSETFASTINT (Vwindow_system_version, 11);
4956 return Qnil;
4959 DEFUN ("x-close-connection", Fx_close_connection,
4960 Sx_close_connection, 1, 1, 0,
4961 "Close the connection to DISPLAY's X server.\n\
4962 For DISPLAY, specify either a frame or a display name (a string).\n\
4963 If DISPLAY is nil, that stands for the selected frame's display.")
4964 (display)
4965 Lisp_Object display;
4967 struct x_display_info *dpyinfo = check_x_display_info (display);
4968 int i;
4970 if (dpyinfo->reference_count > 0)
4971 error ("Display still has frames on it");
4973 BLOCK_INPUT;
4974 /* Free the fonts in the font table. */
4975 for (i = 0; i < dpyinfo->n_fonts; i++)
4976 if (dpyinfo->font_table[i].name)
4978 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
4979 xfree (dpyinfo->font_table[i].full_name);
4980 xfree (dpyinfo->font_table[i].name);
4981 XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
4984 x_destroy_all_bitmaps (dpyinfo);
4985 XSetCloseDownMode (dpyinfo->display, DestroyAll);
4987 #ifdef USE_X_TOOLKIT
4988 XtCloseDisplay (dpyinfo->display);
4989 #else
4990 XCloseDisplay (dpyinfo->display);
4991 #endif
4993 x_delete_display (dpyinfo);
4994 UNBLOCK_INPUT;
4996 return Qnil;
4999 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5000 "Return the list of display names that Emacs has connections to.")
5003 Lisp_Object tail, result;
5005 result = Qnil;
5006 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
5007 result = Fcons (XCAR (XCAR (tail)), result);
5009 return result;
5012 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5013 "If ON is non-nil, report X errors as soon as the erring request is made.\n\
5014 If ON is nil, allow buffering of requests.\n\
5015 Turning on synchronization prohibits the Xlib routines from buffering\n\
5016 requests and seriously degrades performance, but makes debugging much\n\
5017 easier.\n\
5018 The optional second argument DISPLAY specifies which display to act on.\n\
5019 DISPLAY should be either a frame or a display name (a string).\n\
5020 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5021 (on, display)
5022 Lisp_Object display, on;
5024 struct x_display_info *dpyinfo = check_x_display_info (display);
5026 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5028 return Qnil;
5031 /* Wait for responses to all X commands issued so far for frame F. */
5033 void
5034 x_sync (f)
5035 FRAME_PTR f;
5037 BLOCK_INPUT;
5038 XSync (FRAME_X_DISPLAY (f), False);
5039 UNBLOCK_INPUT;
5043 /***********************************************************************
5044 Image types
5045 ***********************************************************************/
5047 /* Value is the number of elements of vector VECTOR. */
5049 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
5051 /* List of supported image types. Use define_image_type to add new
5052 types. Use lookup_image_type to find a type for a given symbol. */
5054 static struct image_type *image_types;
5056 /* The symbol `image' which is the car of the lists used to represent
5057 images in Lisp. */
5059 extern Lisp_Object Qimage;
5061 /* The symbol `xbm' which is used as the type symbol for XBM images. */
5063 Lisp_Object Qxbm;
5065 /* Keywords. */
5067 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
5068 extern Lisp_Object QCdata;
5069 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
5070 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
5071 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
5073 /* Other symbols. */
5075 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
5077 /* Time in seconds after which images should be removed from the cache
5078 if not displayed. */
5080 Lisp_Object Vimage_cache_eviction_delay;
5082 /* Function prototypes. */
5084 static void define_image_type P_ ((struct image_type *type));
5085 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
5086 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
5087 static void x_laplace P_ ((struct frame *, struct image *));
5088 static void x_emboss P_ ((struct frame *, struct image *));
5089 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
5090 Lisp_Object));
5093 /* Define a new image type from TYPE. This adds a copy of TYPE to
5094 image_types and adds the symbol *TYPE->type to Vimage_types. */
5096 static void
5097 define_image_type (type)
5098 struct image_type *type;
5100 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
5101 The initialized data segment is read-only. */
5102 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
5103 bcopy (type, p, sizeof *p);
5104 p->next = image_types;
5105 image_types = p;
5106 Vimage_types = Fcons (*p->type, Vimage_types);
5110 /* Look up image type SYMBOL, and return a pointer to its image_type
5111 structure. Value is null if SYMBOL is not a known image type. */
5113 static INLINE struct image_type *
5114 lookup_image_type (symbol)
5115 Lisp_Object symbol;
5117 struct image_type *type;
5119 for (type = image_types; type; type = type->next)
5120 if (EQ (symbol, *type->type))
5121 break;
5123 return type;
5127 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
5128 valid image specification is a list whose car is the symbol
5129 `image', and whose rest is a property list. The property list must
5130 contain a value for key `:type'. That value must be the name of a
5131 supported image type. The rest of the property list depends on the
5132 image type. */
5135 valid_image_p (object)
5136 Lisp_Object object;
5138 int valid_p = 0;
5140 if (CONSP (object) && EQ (XCAR (object), Qimage))
5142 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
5143 struct image_type *type = lookup_image_type (symbol);
5145 if (type)
5146 valid_p = type->valid_p (object);
5149 return valid_p;
5153 /* Log error message with format string FORMAT and argument ARG.
5154 Signaling an error, e.g. when an image cannot be loaded, is not a
5155 good idea because this would interrupt redisplay, and the error
5156 message display would lead to another redisplay. This function
5157 therefore simply displays a message. */
5159 static void
5160 image_error (format, arg1, arg2)
5161 char *format;
5162 Lisp_Object arg1, arg2;
5164 add_to_log (format, arg1, arg2);
5169 /***********************************************************************
5170 Image specifications
5171 ***********************************************************************/
5173 enum image_value_type
5175 IMAGE_DONT_CHECK_VALUE_TYPE,
5176 IMAGE_STRING_VALUE,
5177 IMAGE_SYMBOL_VALUE,
5178 IMAGE_POSITIVE_INTEGER_VALUE,
5179 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
5180 IMAGE_ASCENT_VALUE,
5181 IMAGE_INTEGER_VALUE,
5182 IMAGE_FUNCTION_VALUE,
5183 IMAGE_NUMBER_VALUE,
5184 IMAGE_BOOL_VALUE
5187 /* Structure used when parsing image specifications. */
5189 struct image_keyword
5191 /* Name of keyword. */
5192 char *name;
5194 /* The type of value allowed. */
5195 enum image_value_type type;
5197 /* Non-zero means key must be present. */
5198 int mandatory_p;
5200 /* Used to recognize duplicate keywords in a property list. */
5201 int count;
5203 /* The value that was found. */
5204 Lisp_Object value;
5208 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
5209 int, Lisp_Object));
5210 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
5213 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
5214 has the format (image KEYWORD VALUE ...). One of the keyword/
5215 value pairs must be `:type TYPE'. KEYWORDS is a vector of
5216 image_keywords structures of size NKEYWORDS describing other
5217 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
5219 static int
5220 parse_image_spec (spec, keywords, nkeywords, type)
5221 Lisp_Object spec;
5222 struct image_keyword *keywords;
5223 int nkeywords;
5224 Lisp_Object type;
5226 int i;
5227 Lisp_Object plist;
5229 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
5230 return 0;
5232 plist = XCDR (spec);
5233 while (CONSP (plist))
5235 Lisp_Object key, value;
5237 /* First element of a pair must be a symbol. */
5238 key = XCAR (plist);
5239 plist = XCDR (plist);
5240 if (!SYMBOLP (key))
5241 return 0;
5243 /* There must follow a value. */
5244 if (!CONSP (plist))
5245 return 0;
5246 value = XCAR (plist);
5247 plist = XCDR (plist);
5249 /* Find key in KEYWORDS. Error if not found. */
5250 for (i = 0; i < nkeywords; ++i)
5251 if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
5252 break;
5254 if (i == nkeywords)
5255 continue;
5257 /* Record that we recognized the keyword. If a keywords
5258 was found more than once, it's an error. */
5259 keywords[i].value = value;
5260 ++keywords[i].count;
5262 if (keywords[i].count > 1)
5263 return 0;
5265 /* Check type of value against allowed type. */
5266 switch (keywords[i].type)
5268 case IMAGE_STRING_VALUE:
5269 if (!STRINGP (value))
5270 return 0;
5271 break;
5273 case IMAGE_SYMBOL_VALUE:
5274 if (!SYMBOLP (value))
5275 return 0;
5276 break;
5278 case IMAGE_POSITIVE_INTEGER_VALUE:
5279 if (!INTEGERP (value) || XINT (value) <= 0)
5280 return 0;
5281 break;
5283 case IMAGE_ASCENT_VALUE:
5284 if (SYMBOLP (value) && EQ (value, Qcenter))
5285 break;
5286 else if (INTEGERP (value)
5287 && XINT (value) >= 0
5288 && XINT (value) <= 100)
5289 break;
5290 return 0;
5292 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
5293 if (!INTEGERP (value) || XINT (value) < 0)
5294 return 0;
5295 break;
5297 case IMAGE_DONT_CHECK_VALUE_TYPE:
5298 break;
5300 case IMAGE_FUNCTION_VALUE:
5301 value = indirect_function (value);
5302 if (SUBRP (value)
5303 || COMPILEDP (value)
5304 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
5305 break;
5306 return 0;
5308 case IMAGE_NUMBER_VALUE:
5309 if (!INTEGERP (value) && !FLOATP (value))
5310 return 0;
5311 break;
5313 case IMAGE_INTEGER_VALUE:
5314 if (!INTEGERP (value))
5315 return 0;
5316 break;
5318 case IMAGE_BOOL_VALUE:
5319 if (!NILP (value) && !EQ (value, Qt))
5320 return 0;
5321 break;
5323 default:
5324 abort ();
5325 break;
5328 if (EQ (key, QCtype) && !EQ (type, value))
5329 return 0;
5332 /* Check that all mandatory fields are present. */
5333 for (i = 0; i < nkeywords; ++i)
5334 if (keywords[i].mandatory_p && keywords[i].count == 0)
5335 return 0;
5337 return NILP (plist);
5341 /* Return the value of KEY in image specification SPEC. Value is nil
5342 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
5343 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
5345 static Lisp_Object
5346 image_spec_value (spec, key, found)
5347 Lisp_Object spec, key;
5348 int *found;
5350 Lisp_Object tail;
5352 xassert (valid_image_p (spec));
5354 for (tail = XCDR (spec);
5355 CONSP (tail) && CONSP (XCDR (tail));
5356 tail = XCDR (XCDR (tail)))
5358 if (EQ (XCAR (tail), key))
5360 if (found)
5361 *found = 1;
5362 return XCAR (XCDR (tail));
5366 if (found)
5367 *found = 0;
5368 return Qnil;
5372 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
5373 "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
5374 PIXELS non-nil means return the size in pixels, otherwise return the\n\
5375 size in canonical character units.\n\
5376 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5377 or omitted means use the selected frame.")
5378 (spec, pixels, frame)
5379 Lisp_Object spec, pixels, frame;
5381 Lisp_Object size;
5383 size = Qnil;
5384 if (valid_image_p (spec))
5386 struct frame *f = check_x_frame (frame);
5387 int id = lookup_image (f, spec);
5388 struct image *img = IMAGE_FROM_ID (f, id);
5389 int width = img->width + 2 * img->margin;
5390 int height = img->height + 2 * img->margin;
5392 if (NILP (pixels))
5393 size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
5394 make_float ((double) height / CANON_Y_UNIT (f)));
5395 else
5396 size = Fcons (make_number (width), make_number (height));
5398 else
5399 error ("Invalid image specification");
5401 return size;
5405 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
5406 "Return t if image SPEC has a mask bitmap.\n\
5407 FRAME is the frame on which the image will be displayed. FRAME nil\n\
5408 or omitted means use the selected frame.")
5409 (spec, frame)
5410 Lisp_Object spec, frame;
5412 Lisp_Object mask;
5414 mask = Qnil;
5415 if (valid_image_p (spec))
5417 struct frame *f = check_x_frame (frame);
5418 int id = lookup_image (f, spec);
5419 struct image *img = IMAGE_FROM_ID (f, id);
5420 if (img->mask)
5421 mask = Qt;
5423 else
5424 error ("Invalid image specification");
5426 return mask;
5431 /***********************************************************************
5432 Image type independent image structures
5433 ***********************************************************************/
5435 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
5436 static void free_image P_ ((struct frame *f, struct image *img));
5439 /* Allocate and return a new image structure for image specification
5440 SPEC. SPEC has a hash value of HASH. */
5442 static struct image *
5443 make_image (spec, hash)
5444 Lisp_Object spec;
5445 unsigned hash;
5447 struct image *img = (struct image *) xmalloc (sizeof *img);
5449 xassert (valid_image_p (spec));
5450 bzero (img, sizeof *img);
5451 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
5452 xassert (img->type != NULL);
5453 img->spec = spec;
5454 img->data.lisp_val = Qnil;
5455 img->ascent = DEFAULT_IMAGE_ASCENT;
5456 img->hash = hash;
5457 return img;
5461 /* Free image IMG which was used on frame F, including its resources. */
5463 static void
5464 free_image (f, img)
5465 struct frame *f;
5466 struct image *img;
5468 if (img)
5470 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5472 /* Remove IMG from the hash table of its cache. */
5473 if (img->prev)
5474 img->prev->next = img->next;
5475 else
5476 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
5478 if (img->next)
5479 img->next->prev = img->prev;
5481 c->images[img->id] = NULL;
5483 /* Free resources, then free IMG. */
5484 img->type->free (f, img);
5485 xfree (img);
5490 /* Prepare image IMG for display on frame F. Must be called before
5491 drawing an image. */
5493 void
5494 prepare_image_for_display (f, img)
5495 struct frame *f;
5496 struct image *img;
5498 EMACS_TIME t;
5500 /* We're about to display IMG, so set its timestamp to `now'. */
5501 EMACS_GET_TIME (t);
5502 img->timestamp = EMACS_SECS (t);
5504 /* If IMG doesn't have a pixmap yet, load it now, using the image
5505 type dependent loader function. */
5506 if (img->pixmap == None && !img->load_failed_p)
5507 img->load_failed_p = img->type->load (f, img) == 0;
5511 /* Value is the number of pixels for the ascent of image IMG when
5512 drawn in face FACE. */
5515 image_ascent (img, face)
5516 struct image *img;
5517 struct face *face;
5519 int height = img->height + img->margin;
5520 int ascent;
5522 if (img->ascent == CENTERED_IMAGE_ASCENT)
5524 if (face->font)
5525 /* This expression is arranged so that if the image can't be
5526 exactly centered, it will be moved slightly up. This is
5527 because a typical font is `top-heavy' (due to the presence
5528 uppercase letters), so the image placement should err towards
5529 being top-heavy too. It also just generally looks better. */
5530 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
5531 else
5532 ascent = height / 2;
5534 else
5535 ascent = height * img->ascent / 100.0;
5537 return ascent;
5542 /***********************************************************************
5543 Helper functions for X image types
5544 ***********************************************************************/
5546 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
5547 int, int));
5548 static void x_clear_image P_ ((struct frame *f, struct image *img));
5549 static unsigned long x_alloc_image_color P_ ((struct frame *f,
5550 struct image *img,
5551 Lisp_Object color_name,
5552 unsigned long dflt));
5555 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
5556 free the pixmap if any. MASK_P non-zero means clear the mask
5557 pixmap if any. COLORS_P non-zero means free colors allocated for
5558 the image, if any. */
5560 static void
5561 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
5562 struct frame *f;
5563 struct image *img;
5564 int pixmap_p, mask_p, colors_p;
5566 if (pixmap_p && img->pixmap)
5568 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
5569 img->pixmap = None;
5572 if (mask_p && img->mask)
5574 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5575 img->mask = None;
5578 if (colors_p && img->ncolors)
5580 x_free_colors (f, img->colors, img->ncolors);
5581 xfree (img->colors);
5582 img->colors = NULL;
5583 img->ncolors = 0;
5587 /* Free X resources of image IMG which is used on frame F. */
5589 static void
5590 x_clear_image (f, img)
5591 struct frame *f;
5592 struct image *img;
5594 BLOCK_INPUT;
5595 x_clear_image_1 (f, img, 1, 1, 1);
5596 UNBLOCK_INPUT;
5600 /* Allocate color COLOR_NAME for image IMG on frame F. If color
5601 cannot be allocated, use DFLT. Add a newly allocated color to
5602 IMG->colors, so that it can be freed again. Value is the pixel
5603 color. */
5605 static unsigned long
5606 x_alloc_image_color (f, img, color_name, dflt)
5607 struct frame *f;
5608 struct image *img;
5609 Lisp_Object color_name;
5610 unsigned long dflt;
5612 XColor color;
5613 unsigned long result;
5615 xassert (STRINGP (color_name));
5617 if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
5619 /* This isn't called frequently so we get away with simply
5620 reallocating the color vector to the needed size, here. */
5621 ++img->ncolors;
5622 img->colors =
5623 (unsigned long *) xrealloc (img->colors,
5624 img->ncolors * sizeof *img->colors);
5625 img->colors[img->ncolors - 1] = color.pixel;
5626 result = color.pixel;
5628 else
5629 result = dflt;
5631 return result;
5636 /***********************************************************************
5637 Image Cache
5638 ***********************************************************************/
5640 static void cache_image P_ ((struct frame *f, struct image *img));
5643 /* Return a new, initialized image cache that is allocated from the
5644 heap. Call free_image_cache to free an image cache. */
5646 struct image_cache *
5647 make_image_cache ()
5649 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
5650 int size;
5652 bzero (c, sizeof *c);
5653 c->size = 50;
5654 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
5655 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
5656 c->buckets = (struct image **) xmalloc (size);
5657 bzero (c->buckets, size);
5658 return c;
5662 /* Free image cache of frame F. Be aware that X frames share images
5663 caches. */
5665 void
5666 free_image_cache (f)
5667 struct frame *f;
5669 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5670 if (c)
5672 int i;
5674 /* Cache should not be referenced by any frame when freed. */
5675 xassert (c->refcount == 0);
5677 for (i = 0; i < c->used; ++i)
5678 free_image (f, c->images[i]);
5679 xfree (c->images);
5680 xfree (c->buckets);
5681 xfree (c);
5682 FRAME_X_IMAGE_CACHE (f) = NULL;
5687 /* Clear image cache of frame F. FORCE_P non-zero means free all
5688 images. FORCE_P zero means clear only images that haven't been
5689 displayed for some time. Should be called from time to time to
5690 reduce the number of loaded images. If image-eviction-seconds is
5691 non-nil, this frees images in the cache which weren't displayed for
5692 at least that many seconds. */
5694 void
5695 clear_image_cache (f, force_p)
5696 struct frame *f;
5697 int force_p;
5699 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5701 if (c && INTEGERP (Vimage_cache_eviction_delay))
5703 EMACS_TIME t;
5704 unsigned long old;
5705 int i, nfreed;
5707 EMACS_GET_TIME (t);
5708 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
5710 /* Block input so that we won't be interrupted by a SIGIO
5711 while being in an inconsistent state. */
5712 BLOCK_INPUT;
5714 for (i = nfreed = 0; i < c->used; ++i)
5716 struct image *img = c->images[i];
5717 if (img != NULL
5718 && (force_p || img->timestamp < old))
5720 free_image (f, img);
5721 ++nfreed;
5725 /* We may be clearing the image cache because, for example,
5726 Emacs was iconified for a longer period of time. In that
5727 case, current matrices may still contain references to
5728 images freed above. So, clear these matrices. */
5729 if (nfreed)
5731 Lisp_Object tail, frame;
5733 FOR_EACH_FRAME (tail, frame)
5735 struct frame *f = XFRAME (frame);
5736 if (FRAME_X_P (f)
5737 && FRAME_X_IMAGE_CACHE (f) == c)
5738 clear_current_matrices (f);
5741 ++windows_or_buffers_changed;
5744 UNBLOCK_INPUT;
5749 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
5750 0, 1, 0,
5751 "Clear the image cache of FRAME.\n\
5752 FRAME nil or omitted means use the selected frame.\n\
5753 FRAME t means clear the image caches of all frames.")
5754 (frame)
5755 Lisp_Object frame;
5757 if (EQ (frame, Qt))
5759 Lisp_Object tail;
5761 FOR_EACH_FRAME (tail, frame)
5762 if (FRAME_X_P (XFRAME (frame)))
5763 clear_image_cache (XFRAME (frame), 1);
5765 else
5766 clear_image_cache (check_x_frame (frame), 1);
5768 return Qnil;
5772 /* Return the id of image with Lisp specification SPEC on frame F.
5773 SPEC must be a valid Lisp image specification (see valid_image_p). */
5776 lookup_image (f, spec)
5777 struct frame *f;
5778 Lisp_Object spec;
5780 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5781 struct image *img;
5782 int i;
5783 unsigned hash;
5784 struct gcpro gcpro1;
5785 EMACS_TIME now;
5787 /* F must be a window-system frame, and SPEC must be a valid image
5788 specification. */
5789 xassert (FRAME_WINDOW_P (f));
5790 xassert (valid_image_p (spec));
5792 GCPRO1 (spec);
5794 /* Look up SPEC in the hash table of the image cache. */
5795 hash = sxhash (spec, 0);
5796 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
5798 for (img = c->buckets[i]; img; img = img->next)
5799 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
5800 break;
5802 /* If not found, create a new image and cache it. */
5803 if (img == NULL)
5805 BLOCK_INPUT;
5806 img = make_image (spec, hash);
5807 cache_image (f, img);
5808 img->load_failed_p = img->type->load (f, img) == 0;
5810 /* If we can't load the image, and we don't have a width and
5811 height, use some arbitrary width and height so that we can
5812 draw a rectangle for it. */
5813 if (img->load_failed_p)
5815 Lisp_Object value;
5817 value = image_spec_value (spec, QCwidth, NULL);
5818 img->width = (INTEGERP (value)
5819 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
5820 value = image_spec_value (spec, QCheight, NULL);
5821 img->height = (INTEGERP (value)
5822 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
5824 else
5826 /* Handle image type independent image attributes
5827 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
5828 Lisp_Object ascent, margin, relief;
5829 Lisp_Object file;
5831 ascent = image_spec_value (spec, QCascent, NULL);
5832 if (INTEGERP (ascent))
5833 img->ascent = XFASTINT (ascent);
5834 else if (EQ (ascent, Qcenter))
5835 img->ascent = CENTERED_IMAGE_ASCENT;
5837 margin = image_spec_value (spec, QCmargin, NULL);
5838 if (INTEGERP (margin) && XINT (margin) >= 0)
5839 img->margin = XFASTINT (margin);
5841 relief = image_spec_value (spec, QCrelief, NULL);
5842 if (INTEGERP (relief))
5844 img->relief = XINT (relief);
5845 img->margin += abs (img->relief);
5848 /* Manipulation of the image's mask. */
5849 if (img->pixmap)
5851 /* `:heuristic-mask t'
5852 `:mask heuristic'
5853 means build a mask heuristically.
5854 `:heuristic-mask (R G B)'
5855 `:mask (heuristic (R G B))'
5856 means build a mask from color (R G B) in the
5857 image.
5858 `:mask nil'
5859 means remove a mask, if any. */
5861 Lisp_Object mask;
5863 mask = image_spec_value (spec, QCheuristic_mask, NULL);
5864 if (!NILP (mask))
5865 x_build_heuristic_mask (f, img, mask);
5866 else
5868 int found_p;
5870 mask = image_spec_value (spec, QCmask, &found_p);
5872 if (EQ (mask, Qheuristic))
5873 x_build_heuristic_mask (f, img, Qt);
5874 else if (CONSP (mask)
5875 && EQ (XCAR (mask), Qheuristic))
5877 if (CONSP (XCDR (mask)))
5878 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
5879 else
5880 x_build_heuristic_mask (f, img, XCDR (mask));
5882 else if (NILP (mask) && found_p && img->mask)
5884 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
5885 img->mask = None;
5890 /* Should we apply an image transformation algorithm? */
5891 if (img->pixmap)
5893 Lisp_Object algorithm;
5895 algorithm = image_spec_value (spec, QCalgorithm, NULL);
5896 if (EQ (algorithm, Qdisabled))
5897 x_disable_image (f, img);
5898 else if (EQ (algorithm, Qlaplace))
5899 x_laplace (f, img);
5900 else if (EQ (algorithm, Qemboss))
5901 x_emboss (f, img);
5902 else if (CONSP (algorithm)
5903 && EQ (XCAR (algorithm), Qedge_detection))
5905 Lisp_Object tem;
5906 tem = XCDR (algorithm);
5907 if (CONSP (tem))
5908 x_edge_detection (f, img,
5909 Fplist_get (tem, QCmatrix),
5910 Fplist_get (tem, QCcolor_adjustment));
5915 UNBLOCK_INPUT;
5916 xassert (!interrupt_input_blocked);
5919 /* We're using IMG, so set its timestamp to `now'. */
5920 EMACS_GET_TIME (now);
5921 img->timestamp = EMACS_SECS (now);
5923 UNGCPRO;
5925 /* Value is the image id. */
5926 return img->id;
5930 /* Cache image IMG in the image cache of frame F. */
5932 static void
5933 cache_image (f, img)
5934 struct frame *f;
5935 struct image *img;
5937 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5938 int i;
5940 /* Find a free slot in c->images. */
5941 for (i = 0; i < c->used; ++i)
5942 if (c->images[i] == NULL)
5943 break;
5945 /* If no free slot found, maybe enlarge c->images. */
5946 if (i == c->used && c->used == c->size)
5948 c->size *= 2;
5949 c->images = (struct image **) xrealloc (c->images,
5950 c->size * sizeof *c->images);
5953 /* Add IMG to c->images, and assign IMG an id. */
5954 c->images[i] = img;
5955 img->id = i;
5956 if (i == c->used)
5957 ++c->used;
5959 /* Add IMG to the cache's hash table. */
5960 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
5961 img->next = c->buckets[i];
5962 if (img->next)
5963 img->next->prev = img;
5964 img->prev = NULL;
5965 c->buckets[i] = img;
5969 /* Call FN on every image in the image cache of frame F. Used to mark
5970 Lisp Objects in the image cache. */
5972 void
5973 forall_images_in_image_cache (f, fn)
5974 struct frame *f;
5975 void (*fn) P_ ((struct image *img));
5977 if (FRAME_LIVE_P (f) && FRAME_X_P (f))
5979 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
5980 if (c)
5982 int i;
5983 for (i = 0; i < c->used; ++i)
5984 if (c->images[i])
5985 fn (c->images[i]);
5992 /***********************************************************************
5993 X support code
5994 ***********************************************************************/
5996 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
5997 XImage **, Pixmap *));
5998 static void x_destroy_x_image P_ ((XImage *));
5999 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
6002 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
6003 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
6004 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
6005 via xmalloc. Print error messages via image_error if an error
6006 occurs. Value is non-zero if successful. */
6008 static int
6009 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
6010 struct frame *f;
6011 int width, height, depth;
6012 XImage **ximg;
6013 Pixmap *pixmap;
6015 Display *display = FRAME_X_DISPLAY (f);
6016 Screen *screen = FRAME_X_SCREEN (f);
6017 Window window = FRAME_X_WINDOW (f);
6019 xassert (interrupt_input_blocked);
6021 if (depth <= 0)
6022 depth = DefaultDepthOfScreen (screen);
6023 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
6024 depth, ZPixmap, 0, NULL, width, height,
6025 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
6026 if (*ximg == NULL)
6028 image_error ("Unable to allocate X image", Qnil, Qnil);
6029 return 0;
6032 /* Allocate image raster. */
6033 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
6035 /* Allocate a pixmap of the same size. */
6036 *pixmap = XCreatePixmap (display, window, width, height, depth);
6037 if (*pixmap == None)
6039 x_destroy_x_image (*ximg);
6040 *ximg = NULL;
6041 image_error ("Unable to create X pixmap", Qnil, Qnil);
6042 return 0;
6045 return 1;
6049 /* Destroy XImage XIMG. Free XIMG->data. */
6051 static void
6052 x_destroy_x_image (ximg)
6053 XImage *ximg;
6055 xassert (interrupt_input_blocked);
6056 if (ximg)
6058 xfree (ximg->data);
6059 ximg->data = NULL;
6060 XDestroyImage (ximg);
6065 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
6066 are width and height of both the image and pixmap. */
6068 static void
6069 x_put_x_image (f, ximg, pixmap, width, height)
6070 struct frame *f;
6071 XImage *ximg;
6072 Pixmap pixmap;
6074 GC gc;
6076 xassert (interrupt_input_blocked);
6077 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
6078 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
6079 XFreeGC (FRAME_X_DISPLAY (f), gc);
6084 /***********************************************************************
6085 File Handling
6086 ***********************************************************************/
6088 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
6089 static char *slurp_file P_ ((char *, int *));
6092 /* Find image file FILE. Look in data-directory, then
6093 x-bitmap-file-path. Value is the full name of the file found, or
6094 nil if not found. */
6096 static Lisp_Object
6097 x_find_image_file (file)
6098 Lisp_Object file;
6100 Lisp_Object file_found, search_path;
6101 struct gcpro gcpro1, gcpro2;
6102 int fd;
6104 file_found = Qnil;
6105 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
6106 GCPRO2 (file_found, search_path);
6108 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
6109 fd = openp (search_path, file, "", &file_found, 0);
6111 if (fd < 0)
6112 file_found = Qnil;
6113 else
6114 close (fd);
6116 UNGCPRO;
6117 return file_found;
6121 /* Read FILE into memory. Value is a pointer to a buffer allocated
6122 with xmalloc holding FILE's contents. Value is null if an error
6123 occurred. *SIZE is set to the size of the file. */
6125 static char *
6126 slurp_file (file, size)
6127 char *file;
6128 int *size;
6130 FILE *fp = NULL;
6131 char *buf = NULL;
6132 struct stat st;
6134 if (stat (file, &st) == 0
6135 && (fp = fopen (file, "r")) != NULL
6136 && (buf = (char *) xmalloc (st.st_size),
6137 fread (buf, 1, st.st_size, fp) == st.st_size))
6139 *size = st.st_size;
6140 fclose (fp);
6142 else
6144 if (fp)
6145 fclose (fp);
6146 if (buf)
6148 xfree (buf);
6149 buf = NULL;
6153 return buf;
6158 /***********************************************************************
6159 XBM images
6160 ***********************************************************************/
6162 static int xbm_scan P_ ((char **, char *, char *, int *));
6163 static int xbm_load P_ ((struct frame *f, struct image *img));
6164 static int xbm_load_image P_ ((struct frame *f, struct image *img,
6165 char *, char *));
6166 static int xbm_image_p P_ ((Lisp_Object object));
6167 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
6168 unsigned char **));
6169 static int xbm_file_p P_ ((Lisp_Object));
6172 /* Indices of image specification fields in xbm_format, below. */
6174 enum xbm_keyword_index
6176 XBM_TYPE,
6177 XBM_FILE,
6178 XBM_WIDTH,
6179 XBM_HEIGHT,
6180 XBM_DATA,
6181 XBM_FOREGROUND,
6182 XBM_BACKGROUND,
6183 XBM_ASCENT,
6184 XBM_MARGIN,
6185 XBM_RELIEF,
6186 XBM_ALGORITHM,
6187 XBM_HEURISTIC_MASK,
6188 XBM_MASK,
6189 XBM_LAST
6192 /* Vector of image_keyword structures describing the format
6193 of valid XBM image specifications. */
6195 static struct image_keyword xbm_format[XBM_LAST] =
6197 {":type", IMAGE_SYMBOL_VALUE, 1},
6198 {":file", IMAGE_STRING_VALUE, 0},
6199 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6200 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6201 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6202 {":foreground", IMAGE_STRING_VALUE, 0},
6203 {":background", IMAGE_STRING_VALUE, 0},
6204 {":ascent", IMAGE_ASCENT_VALUE, 0},
6205 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6206 {":relief", IMAGE_INTEGER_VALUE, 0},
6207 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6208 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6209 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6212 /* Structure describing the image type XBM. */
6214 static struct image_type xbm_type =
6216 &Qxbm,
6217 xbm_image_p,
6218 xbm_load,
6219 x_clear_image,
6220 NULL
6223 /* Tokens returned from xbm_scan. */
6225 enum xbm_token
6227 XBM_TK_IDENT = 256,
6228 XBM_TK_NUMBER
6232 /* Return non-zero if OBJECT is a valid XBM-type image specification.
6233 A valid specification is a list starting with the symbol `image'
6234 The rest of the list is a property list which must contain an
6235 entry `:type xbm..
6237 If the specification specifies a file to load, it must contain
6238 an entry `:file FILENAME' where FILENAME is a string.
6240 If the specification is for a bitmap loaded from memory it must
6241 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
6242 WIDTH and HEIGHT are integers > 0. DATA may be:
6244 1. a string large enough to hold the bitmap data, i.e. it must
6245 have a size >= (WIDTH + 7) / 8 * HEIGHT
6247 2. a bool-vector of size >= WIDTH * HEIGHT
6249 3. a vector of strings or bool-vectors, one for each line of the
6250 bitmap.
6252 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
6253 may not be specified in this case because they are defined in the
6254 XBM file.
6256 Both the file and data forms may contain the additional entries
6257 `:background COLOR' and `:foreground COLOR'. If not present,
6258 foreground and background of the frame on which the image is
6259 displayed is used. */
6261 static int
6262 xbm_image_p (object)
6263 Lisp_Object object;
6265 struct image_keyword kw[XBM_LAST];
6267 bcopy (xbm_format, kw, sizeof kw);
6268 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
6269 return 0;
6271 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
6273 if (kw[XBM_FILE].count)
6275 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
6276 return 0;
6278 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
6280 /* In-memory XBM file. */
6281 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
6282 return 0;
6284 else
6286 Lisp_Object data;
6287 int width, height;
6289 /* Entries for `:width', `:height' and `:data' must be present. */
6290 if (!kw[XBM_WIDTH].count
6291 || !kw[XBM_HEIGHT].count
6292 || !kw[XBM_DATA].count)
6293 return 0;
6295 data = kw[XBM_DATA].value;
6296 width = XFASTINT (kw[XBM_WIDTH].value);
6297 height = XFASTINT (kw[XBM_HEIGHT].value);
6299 /* Check type of data, and width and height against contents of
6300 data. */
6301 if (VECTORP (data))
6303 int i;
6305 /* Number of elements of the vector must be >= height. */
6306 if (XVECTOR (data)->size < height)
6307 return 0;
6309 /* Each string or bool-vector in data must be large enough
6310 for one line of the image. */
6311 for (i = 0; i < height; ++i)
6313 Lisp_Object elt = XVECTOR (data)->contents[i];
6315 if (STRINGP (elt))
6317 if (XSTRING (elt)->size
6318 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
6319 return 0;
6321 else if (BOOL_VECTOR_P (elt))
6323 if (XBOOL_VECTOR (elt)->size < width)
6324 return 0;
6326 else
6327 return 0;
6330 else if (STRINGP (data))
6332 if (XSTRING (data)->size
6333 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
6334 return 0;
6336 else if (BOOL_VECTOR_P (data))
6338 if (XBOOL_VECTOR (data)->size < width * height)
6339 return 0;
6341 else
6342 return 0;
6345 return 1;
6349 /* Scan a bitmap file. FP is the stream to read from. Value is
6350 either an enumerator from enum xbm_token, or a character for a
6351 single-character token, or 0 at end of file. If scanning an
6352 identifier, store the lexeme of the identifier in SVAL. If
6353 scanning a number, store its value in *IVAL. */
6355 static int
6356 xbm_scan (s, end, sval, ival)
6357 char **s, *end;
6358 char *sval;
6359 int *ival;
6361 int c;
6363 loop:
6365 /* Skip white space. */
6366 while (*s < end && (c = *(*s)++, isspace (c)))
6369 if (*s >= end)
6370 c = 0;
6371 else if (isdigit (c))
6373 int value = 0, digit;
6375 if (c == '0' && *s < end)
6377 c = *(*s)++;
6378 if (c == 'x' || c == 'X')
6380 while (*s < end)
6382 c = *(*s)++;
6383 if (isdigit (c))
6384 digit = c - '0';
6385 else if (c >= 'a' && c <= 'f')
6386 digit = c - 'a' + 10;
6387 else if (c >= 'A' && c <= 'F')
6388 digit = c - 'A' + 10;
6389 else
6390 break;
6391 value = 16 * value + digit;
6394 else if (isdigit (c))
6396 value = c - '0';
6397 while (*s < end
6398 && (c = *(*s)++, isdigit (c)))
6399 value = 8 * value + c - '0';
6402 else
6404 value = c - '0';
6405 while (*s < end
6406 && (c = *(*s)++, isdigit (c)))
6407 value = 10 * value + c - '0';
6410 if (*s < end)
6411 *s = *s - 1;
6412 *ival = value;
6413 c = XBM_TK_NUMBER;
6415 else if (isalpha (c) || c == '_')
6417 *sval++ = c;
6418 while (*s < end
6419 && (c = *(*s)++, (isalnum (c) || c == '_')))
6420 *sval++ = c;
6421 *sval = 0;
6422 if (*s < end)
6423 *s = *s - 1;
6424 c = XBM_TK_IDENT;
6426 else if (c == '/' && **s == '*')
6428 /* C-style comment. */
6429 ++*s;
6430 while (**s && (**s != '*' || *(*s + 1) != '/'))
6431 ++*s;
6432 if (**s)
6434 *s += 2;
6435 goto loop;
6439 return c;
6443 /* Replacement for XReadBitmapFileData which isn't available under old
6444 X versions. CONTENTS is a pointer to a buffer to parse; END is the
6445 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
6446 the image. Return in *DATA the bitmap data allocated with xmalloc.
6447 Value is non-zero if successful. DATA null means just test if
6448 CONTENTS looks like an in-memory XBM file. */
6450 static int
6451 xbm_read_bitmap_data (contents, end, width, height, data)
6452 char *contents, *end;
6453 int *width, *height;
6454 unsigned char **data;
6456 char *s = contents;
6457 char buffer[BUFSIZ];
6458 int padding_p = 0;
6459 int v10 = 0;
6460 int bytes_per_line, i, nbytes;
6461 unsigned char *p;
6462 int value;
6463 int LA1;
6465 #define match() \
6466 LA1 = xbm_scan (&s, end, buffer, &value)
6468 #define expect(TOKEN) \
6469 if (LA1 != (TOKEN)) \
6470 goto failure; \
6471 else \
6472 match ()
6474 #define expect_ident(IDENT) \
6475 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
6476 match (); \
6477 else \
6478 goto failure
6480 *width = *height = -1;
6481 if (data)
6482 *data = NULL;
6483 LA1 = xbm_scan (&s, end, buffer, &value);
6485 /* Parse defines for width, height and hot-spots. */
6486 while (LA1 == '#')
6488 match ();
6489 expect_ident ("define");
6490 expect (XBM_TK_IDENT);
6492 if (LA1 == XBM_TK_NUMBER);
6494 char *p = strrchr (buffer, '_');
6495 p = p ? p + 1 : buffer;
6496 if (strcmp (p, "width") == 0)
6497 *width = value;
6498 else if (strcmp (p, "height") == 0)
6499 *height = value;
6501 expect (XBM_TK_NUMBER);
6504 if (*width < 0 || *height < 0)
6505 goto failure;
6506 else if (data == NULL)
6507 goto success;
6509 /* Parse bits. Must start with `static'. */
6510 expect_ident ("static");
6511 if (LA1 == XBM_TK_IDENT)
6513 if (strcmp (buffer, "unsigned") == 0)
6515 match ();
6516 expect_ident ("char");
6518 else if (strcmp (buffer, "short") == 0)
6520 match ();
6521 v10 = 1;
6522 if (*width % 16 && *width % 16 < 9)
6523 padding_p = 1;
6525 else if (strcmp (buffer, "char") == 0)
6526 match ();
6527 else
6528 goto failure;
6530 else
6531 goto failure;
6533 expect (XBM_TK_IDENT);
6534 expect ('[');
6535 expect (']');
6536 expect ('=');
6537 expect ('{');
6539 bytes_per_line = (*width + 7) / 8 + padding_p;
6540 nbytes = bytes_per_line * *height;
6541 p = *data = (char *) xmalloc (nbytes);
6543 if (v10)
6545 for (i = 0; i < nbytes; i += 2)
6547 int val = value;
6548 expect (XBM_TK_NUMBER);
6550 *p++ = val;
6551 if (!padding_p || ((i + 2) % bytes_per_line))
6552 *p++ = value >> 8;
6554 if (LA1 == ',' || LA1 == '}')
6555 match ();
6556 else
6557 goto failure;
6560 else
6562 for (i = 0; i < nbytes; ++i)
6564 int val = value;
6565 expect (XBM_TK_NUMBER);
6567 *p++ = val;
6569 if (LA1 == ',' || LA1 == '}')
6570 match ();
6571 else
6572 goto failure;
6576 success:
6577 return 1;
6579 failure:
6581 if (data && *data)
6583 xfree (*data);
6584 *data = NULL;
6586 return 0;
6588 #undef match
6589 #undef expect
6590 #undef expect_ident
6594 /* Load XBM image IMG which will be displayed on frame F from buffer
6595 CONTENTS. END is the end of the buffer. Value is non-zero if
6596 successful. */
6598 static int
6599 xbm_load_image (f, img, contents, end)
6600 struct frame *f;
6601 struct image *img;
6602 char *contents, *end;
6604 int rc;
6605 unsigned char *data;
6606 int success_p = 0;
6608 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
6609 if (rc)
6611 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6612 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6613 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6614 Lisp_Object value;
6616 xassert (img->width > 0 && img->height > 0);
6618 /* Get foreground and background colors, maybe allocate colors. */
6619 value = image_spec_value (img->spec, QCforeground, NULL);
6620 if (!NILP (value))
6621 foreground = x_alloc_image_color (f, img, value, foreground);
6623 value = image_spec_value (img->spec, QCbackground, NULL);
6624 if (!NILP (value))
6625 background = x_alloc_image_color (f, img, value, background);
6627 img->pixmap
6628 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6629 FRAME_X_WINDOW (f),
6630 data,
6631 img->width, img->height,
6632 foreground, background,
6633 depth);
6634 xfree (data);
6636 if (img->pixmap == None)
6638 x_clear_image (f, img);
6639 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
6641 else
6642 success_p = 1;
6644 else
6645 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6647 return success_p;
6651 /* Value is non-zero if DATA looks like an in-memory XBM file. */
6653 static int
6654 xbm_file_p (data)
6655 Lisp_Object data;
6657 int w, h;
6658 return (STRINGP (data)
6659 && xbm_read_bitmap_data (XSTRING (data)->data,
6660 (XSTRING (data)->data
6661 + STRING_BYTES (XSTRING (data))),
6662 &w, &h, NULL));
6666 /* Fill image IMG which is used on frame F with pixmap data. Value is
6667 non-zero if successful. */
6669 static int
6670 xbm_load (f, img)
6671 struct frame *f;
6672 struct image *img;
6674 int success_p = 0;
6675 Lisp_Object file_name;
6677 xassert (xbm_image_p (img->spec));
6679 /* If IMG->spec specifies a file name, create a non-file spec from it. */
6680 file_name = image_spec_value (img->spec, QCfile, NULL);
6681 if (STRINGP (file_name))
6683 Lisp_Object file;
6684 char *contents;
6685 int size;
6686 struct gcpro gcpro1;
6688 file = x_find_image_file (file_name);
6689 GCPRO1 (file);
6690 if (!STRINGP (file))
6692 image_error ("Cannot find image file `%s'", file_name, Qnil);
6693 UNGCPRO;
6694 return 0;
6697 contents = slurp_file (XSTRING (file)->data, &size);
6698 if (contents == NULL)
6700 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
6701 UNGCPRO;
6702 return 0;
6705 success_p = xbm_load_image (f, img, contents, contents + size);
6706 UNGCPRO;
6708 else
6710 struct image_keyword fmt[XBM_LAST];
6711 Lisp_Object data;
6712 unsigned char *bitmap_data;
6713 int depth;
6714 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
6715 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
6716 char *bits;
6717 int parsed_p, height, width;
6718 int in_memory_file_p = 0;
6720 /* See if data looks like an in-memory XBM file. */
6721 data = image_spec_value (img->spec, QCdata, NULL);
6722 in_memory_file_p = xbm_file_p (data);
6724 /* Parse the image specification. */
6725 bcopy (xbm_format, fmt, sizeof fmt);
6726 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
6727 xassert (parsed_p);
6729 /* Get specified width, and height. */
6730 if (!in_memory_file_p)
6732 img->width = XFASTINT (fmt[XBM_WIDTH].value);
6733 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
6734 xassert (img->width > 0 && img->height > 0);
6737 /* Get foreground and background colors, maybe allocate colors. */
6738 if (fmt[XBM_FOREGROUND].count)
6739 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
6740 foreground);
6741 if (fmt[XBM_BACKGROUND].count)
6742 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
6743 background);
6745 if (in_memory_file_p)
6746 success_p = xbm_load_image (f, img, XSTRING (data)->data,
6747 (XSTRING (data)->data
6748 + STRING_BYTES (XSTRING (data))));
6749 else
6751 if (VECTORP (data))
6753 int i;
6754 char *p;
6755 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
6757 p = bits = (char *) alloca (nbytes * img->height);
6758 for (i = 0; i < img->height; ++i, p += nbytes)
6760 Lisp_Object line = XVECTOR (data)->contents[i];
6761 if (STRINGP (line))
6762 bcopy (XSTRING (line)->data, p, nbytes);
6763 else
6764 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
6767 else if (STRINGP (data))
6768 bits = XSTRING (data)->data;
6769 else
6770 bits = XBOOL_VECTOR (data)->data;
6772 /* Create the pixmap. */
6773 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
6774 img->pixmap
6775 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
6776 FRAME_X_WINDOW (f),
6777 bits,
6778 img->width, img->height,
6779 foreground, background,
6780 depth);
6781 if (img->pixmap)
6782 success_p = 1;
6783 else
6785 image_error ("Unable to create pixmap for XBM image `%s'",
6786 img->spec, Qnil);
6787 x_clear_image (f, img);
6792 return success_p;
6797 /***********************************************************************
6798 XPM images
6799 ***********************************************************************/
6801 #if HAVE_XPM
6803 static int xpm_image_p P_ ((Lisp_Object object));
6804 static int xpm_load P_ ((struct frame *f, struct image *img));
6805 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
6807 #include "X11/xpm.h"
6809 /* The symbol `xpm' identifying XPM-format images. */
6811 Lisp_Object Qxpm;
6813 /* Indices of image specification fields in xpm_format, below. */
6815 enum xpm_keyword_index
6817 XPM_TYPE,
6818 XPM_FILE,
6819 XPM_DATA,
6820 XPM_ASCENT,
6821 XPM_MARGIN,
6822 XPM_RELIEF,
6823 XPM_ALGORITHM,
6824 XPM_HEURISTIC_MASK,
6825 XPM_MASK,
6826 XPM_COLOR_SYMBOLS,
6827 XPM_LAST
6830 /* Vector of image_keyword structures describing the format
6831 of valid XPM image specifications. */
6833 static struct image_keyword xpm_format[XPM_LAST] =
6835 {":type", IMAGE_SYMBOL_VALUE, 1},
6836 {":file", IMAGE_STRING_VALUE, 0},
6837 {":data", IMAGE_STRING_VALUE, 0},
6838 {":ascent", IMAGE_ASCENT_VALUE, 0},
6839 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
6840 {":relief", IMAGE_INTEGER_VALUE, 0},
6841 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6842 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6843 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6844 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6847 /* Structure describing the image type XBM. */
6849 static struct image_type xpm_type =
6851 &Qxpm,
6852 xpm_image_p,
6853 xpm_load,
6854 x_clear_image,
6855 NULL
6859 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
6860 functions for allocating image colors. Our own functions handle
6861 color allocation failures more gracefully than the ones on the XPM
6862 lib. */
6864 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
6865 #define ALLOC_XPM_COLORS
6866 #endif
6868 #ifdef ALLOC_XPM_COLORS
6870 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
6871 static void xpm_free_color_cache P_ ((void));
6872 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
6873 static int xpm_color_bucket P_ ((char *));
6874 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
6875 XColor *, int));
6877 /* An entry in a hash table used to cache color definitions of named
6878 colors. This cache is necessary to speed up XPM image loading in
6879 case we do color allocations ourselves. Without it, we would need
6880 a call to XParseColor per pixel in the image. */
6882 struct xpm_cached_color
6884 /* Next in collision chain. */
6885 struct xpm_cached_color *next;
6887 /* Color definition (RGB and pixel color). */
6888 XColor color;
6890 /* Color name. */
6891 char name[1];
6894 /* The hash table used for the color cache, and its bucket vector
6895 size. */
6897 #define XPM_COLOR_CACHE_BUCKETS 1001
6898 struct xpm_cached_color **xpm_color_cache;
6900 /* Initialize the color cache. */
6902 static void
6903 xpm_init_color_cache (f, attrs)
6904 struct frame *f;
6905 XpmAttributes *attrs;
6907 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
6908 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
6909 memset (xpm_color_cache, 0, nbytes);
6910 init_color_table ();
6912 if (attrs->valuemask & XpmColorSymbols)
6914 int i;
6915 XColor color;
6917 for (i = 0; i < attrs->numsymbols; ++i)
6918 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
6919 attrs->colorsymbols[i].value, &color))
6921 color.pixel = lookup_rgb_color (f, color.red, color.green,
6922 color.blue);
6923 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
6929 /* Free the color cache. */
6931 static void
6932 xpm_free_color_cache ()
6934 struct xpm_cached_color *p, *next;
6935 int i;
6937 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
6938 for (p = xpm_color_cache[i]; p; p = next)
6940 next = p->next;
6941 xfree (p);
6944 xfree (xpm_color_cache);
6945 xpm_color_cache = NULL;
6946 free_color_table ();
6950 /* Return the bucket index for color named COLOR_NAME in the color
6951 cache. */
6953 static int
6954 xpm_color_bucket (color_name)
6955 char *color_name;
6957 unsigned h = 0;
6958 char *s;
6960 for (s = color_name; *s; ++s)
6961 h = (h << 2) ^ *s;
6962 return h %= XPM_COLOR_CACHE_BUCKETS;
6966 /* On frame F, cache values COLOR for color with name COLOR_NAME.
6967 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
6968 entry added. */
6970 static struct xpm_cached_color *
6971 xpm_cache_color (f, color_name, color, bucket)
6972 struct frame *f;
6973 char *color_name;
6974 XColor *color;
6975 int bucket;
6977 size_t nbytes;
6978 struct xpm_cached_color *p;
6980 if (bucket < 0)
6981 bucket = xpm_color_bucket (color_name);
6983 nbytes = sizeof *p + strlen (color_name);
6984 p = (struct xpm_cached_color *) xmalloc (nbytes);
6985 strcpy (p->name, color_name);
6986 p->color = *color;
6987 p->next = xpm_color_cache[bucket];
6988 xpm_color_cache[bucket] = p;
6989 return p;
6993 /* Look up color COLOR_NAME for frame F in the color cache. If found,
6994 return the cached definition in *COLOR. Otherwise, make a new
6995 entry in the cache and allocate the color. Value is zero if color
6996 allocation failed. */
6998 static int
6999 xpm_lookup_color (f, color_name, color)
7000 struct frame *f;
7001 char *color_name;
7002 XColor *color;
7004 struct xpm_cached_color *p;
7005 int h = xpm_color_bucket (color_name);
7007 for (p = xpm_color_cache[h]; p; p = p->next)
7008 if (strcmp (p->name, color_name) == 0)
7009 break;
7011 if (p != NULL)
7012 *color = p->color;
7013 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
7014 color_name, color))
7016 color->pixel = lookup_rgb_color (f, color->red, color->green,
7017 color->blue);
7018 p = xpm_cache_color (f, color_name, color, h);
7021 return p != NULL;
7025 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
7026 CLOSURE is a pointer to the frame on which we allocate the
7027 color. Return in *COLOR the allocated color. Value is non-zero
7028 if successful. */
7030 static int
7031 xpm_alloc_color (dpy, cmap, color_name, color, closure)
7032 Display *dpy;
7033 Colormap cmap;
7034 char *color_name;
7035 XColor *color;
7036 void *closure;
7038 return xpm_lookup_color ((struct frame *) closure, color_name, color);
7042 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
7043 is a pointer to the frame on which we allocate the color. Value is
7044 non-zero if successful. */
7046 static int
7047 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
7048 Display *dpy;
7049 Colormap cmap;
7050 Pixel *pixels;
7051 int npixels;
7052 void *closure;
7054 return 1;
7057 #endif /* ALLOC_XPM_COLORS */
7060 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
7061 for XPM images. Such a list must consist of conses whose car and
7062 cdr are strings. */
7064 static int
7065 xpm_valid_color_symbols_p (color_symbols)
7066 Lisp_Object color_symbols;
7068 while (CONSP (color_symbols))
7070 Lisp_Object sym = XCAR (color_symbols);
7071 if (!CONSP (sym)
7072 || !STRINGP (XCAR (sym))
7073 || !STRINGP (XCDR (sym)))
7074 break;
7075 color_symbols = XCDR (color_symbols);
7078 return NILP (color_symbols);
7082 /* Value is non-zero if OBJECT is a valid XPM image specification. */
7084 static int
7085 xpm_image_p (object)
7086 Lisp_Object object;
7088 struct image_keyword fmt[XPM_LAST];
7089 bcopy (xpm_format, fmt, sizeof fmt);
7090 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
7091 /* Either `:file' or `:data' must be present. */
7092 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
7093 /* Either no `:color-symbols' or it's a list of conses
7094 whose car and cdr are strings. */
7095 && (fmt[XPM_COLOR_SYMBOLS].count == 0
7096 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
7100 /* Load image IMG which will be displayed on frame F. Value is
7101 non-zero if successful. */
7103 static int
7104 xpm_load (f, img)
7105 struct frame *f;
7106 struct image *img;
7108 int rc, i;
7109 XpmAttributes attrs;
7110 Lisp_Object specified_file, color_symbols;
7112 /* Configure the XPM lib. Use the visual of frame F. Allocate
7113 close colors. Return colors allocated. */
7114 bzero (&attrs, sizeof attrs);
7115 attrs.visual = FRAME_X_VISUAL (f);
7116 attrs.colormap = FRAME_X_COLORMAP (f);
7117 attrs.valuemask |= XpmVisual;
7118 attrs.valuemask |= XpmColormap;
7120 #ifdef ALLOC_XPM_COLORS
7121 /* Allocate colors with our own functions which handle
7122 failing color allocation more gracefully. */
7123 attrs.color_closure = f;
7124 attrs.alloc_color = xpm_alloc_color;
7125 attrs.free_colors = xpm_free_colors;
7126 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
7127 #else /* not ALLOC_XPM_COLORS */
7128 /* Let the XPM lib allocate colors. */
7129 attrs.valuemask |= XpmReturnAllocPixels;
7130 #ifdef XpmAllocCloseColors
7131 attrs.alloc_close_colors = 1;
7132 attrs.valuemask |= XpmAllocCloseColors;
7133 #else /* not XpmAllocCloseColors */
7134 attrs.closeness = 600;
7135 attrs.valuemask |= XpmCloseness;
7136 #endif /* not XpmAllocCloseColors */
7137 #endif /* ALLOC_XPM_COLORS */
7139 /* If image specification contains symbolic color definitions, add
7140 these to `attrs'. */
7141 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
7142 if (CONSP (color_symbols))
7144 Lisp_Object tail;
7145 XpmColorSymbol *xpm_syms;
7146 int i, size;
7148 attrs.valuemask |= XpmColorSymbols;
7150 /* Count number of symbols. */
7151 attrs.numsymbols = 0;
7152 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
7153 ++attrs.numsymbols;
7155 /* Allocate an XpmColorSymbol array. */
7156 size = attrs.numsymbols * sizeof *xpm_syms;
7157 xpm_syms = (XpmColorSymbol *) alloca (size);
7158 bzero (xpm_syms, size);
7159 attrs.colorsymbols = xpm_syms;
7161 /* Fill the color symbol array. */
7162 for (tail = color_symbols, i = 0;
7163 CONSP (tail);
7164 ++i, tail = XCDR (tail))
7166 Lisp_Object name = XCAR (XCAR (tail));
7167 Lisp_Object color = XCDR (XCAR (tail));
7168 xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
7169 strcpy (xpm_syms[i].name, XSTRING (name)->data);
7170 xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
7171 strcpy (xpm_syms[i].value, XSTRING (color)->data);
7175 /* Create a pixmap for the image, either from a file, or from a
7176 string buffer containing data in the same format as an XPM file. */
7177 #ifdef ALLOC_XPM_COLORS
7178 xpm_init_color_cache (f, &attrs);
7179 #endif
7181 specified_file = image_spec_value (img->spec, QCfile, NULL);
7182 if (STRINGP (specified_file))
7184 Lisp_Object file = x_find_image_file (specified_file);
7185 if (!STRINGP (file))
7187 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7188 return 0;
7191 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7192 XSTRING (file)->data, &img->pixmap, &img->mask,
7193 &attrs);
7195 else
7197 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7198 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7199 XSTRING (buffer)->data,
7200 &img->pixmap, &img->mask,
7201 &attrs);
7204 if (rc == XpmSuccess)
7206 #ifdef ALLOC_XPM_COLORS
7207 img->colors = colors_in_color_table (&img->ncolors);
7208 #else /* not ALLOC_XPM_COLORS */
7209 img->ncolors = attrs.nalloc_pixels;
7210 img->colors = (unsigned long *) xmalloc (img->ncolors
7211 * sizeof *img->colors);
7212 for (i = 0; i < attrs.nalloc_pixels; ++i)
7214 img->colors[i] = attrs.alloc_pixels[i];
7215 #ifdef DEBUG_X_COLORS
7216 register_color (img->colors[i]);
7217 #endif
7219 #endif /* not ALLOC_XPM_COLORS */
7221 img->width = attrs.width;
7222 img->height = attrs.height;
7223 xassert (img->width > 0 && img->height > 0);
7225 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
7226 XpmFreeAttributes (&attrs);
7228 else
7230 switch (rc)
7232 case XpmOpenFailed:
7233 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
7234 break;
7236 case XpmFileInvalid:
7237 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
7238 break;
7240 case XpmNoMemory:
7241 image_error ("Out of memory (%s)", img->spec, Qnil);
7242 break;
7244 case XpmColorFailed:
7245 image_error ("Color allocation error (%s)", img->spec, Qnil);
7246 break;
7248 default:
7249 image_error ("Unknown error (%s)", img->spec, Qnil);
7250 break;
7254 #ifdef ALLOC_XPM_COLORS
7255 xpm_free_color_cache ();
7256 #endif
7257 return rc == XpmSuccess;
7260 #endif /* HAVE_XPM != 0 */
7263 /***********************************************************************
7264 Color table
7265 ***********************************************************************/
7267 /* An entry in the color table mapping an RGB color to a pixel color. */
7269 struct ct_color
7271 int r, g, b;
7272 unsigned long pixel;
7274 /* Next in color table collision list. */
7275 struct ct_color *next;
7278 /* The bucket vector size to use. Must be prime. */
7280 #define CT_SIZE 101
7282 /* Value is a hash of the RGB color given by R, G, and B. */
7284 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
7286 /* The color hash table. */
7288 struct ct_color **ct_table;
7290 /* Number of entries in the color table. */
7292 int ct_colors_allocated;
7294 /* Initialize the color table. */
7296 static void
7297 init_color_table ()
7299 int size = CT_SIZE * sizeof (*ct_table);
7300 ct_table = (struct ct_color **) xmalloc (size);
7301 bzero (ct_table, size);
7302 ct_colors_allocated = 0;
7306 /* Free memory associated with the color table. */
7308 static void
7309 free_color_table ()
7311 int i;
7312 struct ct_color *p, *next;
7314 for (i = 0; i < CT_SIZE; ++i)
7315 for (p = ct_table[i]; p; p = next)
7317 next = p->next;
7318 xfree (p);
7321 xfree (ct_table);
7322 ct_table = NULL;
7326 /* Value is a pixel color for RGB color R, G, B on frame F. If an
7327 entry for that color already is in the color table, return the
7328 pixel color of that entry. Otherwise, allocate a new color for R,
7329 G, B, and make an entry in the color table. */
7331 static unsigned long
7332 lookup_rgb_color (f, r, g, b)
7333 struct frame *f;
7334 int r, g, b;
7336 unsigned hash = CT_HASH_RGB (r, g, b);
7337 int i = hash % CT_SIZE;
7338 struct ct_color *p;
7340 for (p = ct_table[i]; p; p = p->next)
7341 if (p->r == r && p->g == g && p->b == b)
7342 break;
7344 if (p == NULL)
7346 XColor color;
7347 Colormap cmap;
7348 int rc;
7350 color.red = r;
7351 color.green = g;
7352 color.blue = b;
7354 cmap = FRAME_X_COLORMAP (f);
7355 rc = x_alloc_nearest_color (f, cmap, &color);
7357 if (rc)
7359 ++ct_colors_allocated;
7361 p = (struct ct_color *) xmalloc (sizeof *p);
7362 p->r = r;
7363 p->g = g;
7364 p->b = b;
7365 p->pixel = color.pixel;
7366 p->next = ct_table[i];
7367 ct_table[i] = p;
7369 else
7370 return FRAME_FOREGROUND_PIXEL (f);
7373 return p->pixel;
7377 /* Look up pixel color PIXEL which is used on frame F in the color
7378 table. If not already present, allocate it. Value is PIXEL. */
7380 static unsigned long
7381 lookup_pixel_color (f, pixel)
7382 struct frame *f;
7383 unsigned long pixel;
7385 int i = pixel % CT_SIZE;
7386 struct ct_color *p;
7388 for (p = ct_table[i]; p; p = p->next)
7389 if (p->pixel == pixel)
7390 break;
7392 if (p == NULL)
7394 XColor color;
7395 Colormap cmap;
7396 int rc;
7398 cmap = FRAME_X_COLORMAP (f);
7399 color.pixel = pixel;
7400 x_query_color (f, &color);
7401 rc = x_alloc_nearest_color (f, cmap, &color);
7403 if (rc)
7405 ++ct_colors_allocated;
7407 p = (struct ct_color *) xmalloc (sizeof *p);
7408 p->r = color.red;
7409 p->g = color.green;
7410 p->b = color.blue;
7411 p->pixel = pixel;
7412 p->next = ct_table[i];
7413 ct_table[i] = p;
7415 else
7416 return FRAME_FOREGROUND_PIXEL (f);
7419 return p->pixel;
7423 /* Value is a vector of all pixel colors contained in the color table,
7424 allocated via xmalloc. Set *N to the number of colors. */
7426 static unsigned long *
7427 colors_in_color_table (n)
7428 int *n;
7430 int i, j;
7431 struct ct_color *p;
7432 unsigned long *colors;
7434 if (ct_colors_allocated == 0)
7436 *n = 0;
7437 colors = NULL;
7439 else
7441 colors = (unsigned long *) xmalloc (ct_colors_allocated
7442 * sizeof *colors);
7443 *n = ct_colors_allocated;
7445 for (i = j = 0; i < CT_SIZE; ++i)
7446 for (p = ct_table[i]; p; p = p->next)
7447 colors[j++] = p->pixel;
7450 return colors;
7455 /***********************************************************************
7456 Algorithms
7457 ***********************************************************************/
7459 static void x_laplace_write_row P_ ((struct frame *, long *,
7460 int, XImage *, int));
7461 static void x_laplace_read_row P_ ((struct frame *, Colormap,
7462 XColor *, int, XImage *, int));
7463 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
7464 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
7465 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
7467 /* Non-zero means draw a cross on images having `:algorithm
7468 disabled'. */
7470 int cross_disabled_images;
7472 /* Edge detection matrices for different edge-detection
7473 strategies. */
7475 static int emboss_matrix[9] = {
7476 /* x - 1 x x + 1 */
7477 2, -1, 0, /* y - 1 */
7478 -1, 0, 1, /* y */
7479 0, 1, -2 /* y + 1 */
7482 static int laplace_matrix[9] = {
7483 /* x - 1 x x + 1 */
7484 1, 0, 0, /* y - 1 */
7485 0, 0, 0, /* y */
7486 0, 0, -1 /* y + 1 */
7489 /* Value is the intensity of the color whose red/green/blue values
7490 are R, G, and B. */
7492 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
7495 /* On frame F, return an array of XColor structures describing image
7496 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
7497 non-zero means also fill the red/green/blue members of the XColor
7498 structures. Value is a pointer to the array of XColors structures,
7499 allocated with xmalloc; it must be freed by the caller. */
7501 static XColor *
7502 x_to_xcolors (f, img, rgb_p)
7503 struct frame *f;
7504 struct image *img;
7505 int rgb_p;
7507 int x, y;
7508 XColor *colors, *p;
7509 XImage *ximg;
7511 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
7513 /* Get the X image IMG->pixmap. */
7514 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7515 0, 0, img->width, img->height, ~0, ZPixmap);
7517 /* Fill the `pixel' members of the XColor array. I wished there
7518 were an easy and portable way to circumvent XGetPixel. */
7519 p = colors;
7520 for (y = 0; y < img->height; ++y)
7522 XColor *row = p;
7524 for (x = 0; x < img->width; ++x, ++p)
7525 p->pixel = XGetPixel (ximg, x, y);
7527 if (rgb_p)
7528 x_query_colors (f, row, img->width);
7531 XDestroyImage (ximg);
7532 return colors;
7536 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
7537 RGB members are set. F is the frame on which this all happens.
7538 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
7540 static void
7541 x_from_xcolors (f, img, colors)
7542 struct frame *f;
7543 struct image *img;
7544 XColor *colors;
7546 int x, y;
7547 XImage *oimg;
7548 Pixmap pixmap;
7549 XColor *p;
7551 init_color_table ();
7553 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
7554 &oimg, &pixmap);
7555 p = colors;
7556 for (y = 0; y < img->height; ++y)
7557 for (x = 0; x < img->width; ++x, ++p)
7559 unsigned long pixel;
7560 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
7561 XPutPixel (oimg, x, y, pixel);
7564 xfree (colors);
7565 x_clear_image_1 (f, img, 1, 0, 1);
7567 x_put_x_image (f, oimg, pixmap, img->width, img->height);
7568 x_destroy_x_image (oimg);
7569 img->pixmap = pixmap;
7570 img->colors = colors_in_color_table (&img->ncolors);
7571 free_color_table ();
7575 /* On frame F, perform edge-detection on image IMG.
7577 MATRIX is a nine-element array specifying the transformation
7578 matrix. See emboss_matrix for an example.
7580 COLOR_ADJUST is a color adjustment added to each pixel of the
7581 outgoing image. */
7583 static void
7584 x_detect_edges (f, img, matrix, color_adjust)
7585 struct frame *f;
7586 struct image *img;
7587 int matrix[9], color_adjust;
7589 XColor *colors = x_to_xcolors (f, img, 1);
7590 XColor *new, *p;
7591 int x, y, i, sum;
7593 for (i = sum = 0; i < 9; ++i)
7594 sum += abs (matrix[i]);
7596 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
7598 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
7600 for (y = 0; y < img->height; ++y)
7602 p = COLOR (new, 0, y);
7603 p->red = p->green = p->blue = 0xffff/2;
7604 p = COLOR (new, img->width - 1, y);
7605 p->red = p->green = p->blue = 0xffff/2;
7608 for (x = 1; x < img->width - 1; ++x)
7610 p = COLOR (new, x, 0);
7611 p->red = p->green = p->blue = 0xffff/2;
7612 p = COLOR (new, x, img->height - 1);
7613 p->red = p->green = p->blue = 0xffff/2;
7616 for (y = 1; y < img->height - 1; ++y)
7618 p = COLOR (new, 1, y);
7620 for (x = 1; x < img->width - 1; ++x, ++p)
7622 int r, g, b, y1, x1;
7624 r = g = b = i = 0;
7625 for (y1 = y - 1; y1 < y + 2; ++y1)
7626 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
7627 if (matrix[i])
7629 XColor *t = COLOR (colors, x1, y1);
7630 r += matrix[i] * t->red;
7631 g += matrix[i] * t->green;
7632 b += matrix[i] * t->blue;
7635 r = (r / sum + color_adjust) & 0xffff;
7636 g = (g / sum + color_adjust) & 0xffff;
7637 b = (b / sum + color_adjust) & 0xffff;
7638 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
7642 xfree (colors);
7643 x_from_xcolors (f, img, new);
7645 #undef COLOR
7649 /* Perform the pre-defined `emboss' edge-detection on image IMG
7650 on frame F. */
7652 static void
7653 x_emboss (f, img)
7654 struct frame *f;
7655 struct image *img;
7657 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
7661 /* Perform the pre-defined `laplace' edge-detection on image IMG
7662 on frame F. */
7664 static void
7665 x_laplace (f, img)
7666 struct frame *f;
7667 struct image *img;
7669 x_detect_edges (f, img, laplace_matrix, 45000);
7673 /* Perform edge-detection on image IMG on frame F, with specified
7674 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
7676 MATRIX must be either
7678 - a list of at least 9 numbers in row-major form
7679 - a vector of at least 9 numbers
7681 COLOR_ADJUST nil means use a default; otherwise it must be a
7682 number. */
7684 static void
7685 x_edge_detection (f, img, matrix, color_adjust)
7686 struct frame *f;
7687 struct image *img;
7688 Lisp_Object matrix, color_adjust;
7690 int i = 0;
7691 int trans[9];
7693 if (CONSP (matrix))
7695 for (i = 0;
7696 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
7697 ++i, matrix = XCDR (matrix))
7698 trans[i] = XFLOATINT (XCAR (matrix));
7700 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
7702 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
7703 trans[i] = XFLOATINT (AREF (matrix, i));
7706 if (NILP (color_adjust))
7707 color_adjust = make_number (0xffff / 2);
7709 if (i == 9 && NUMBERP (color_adjust))
7710 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
7714 /* Transform image IMG on frame F so that it looks disabled. */
7716 static void
7717 x_disable_image (f, img)
7718 struct frame *f;
7719 struct image *img;
7721 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7723 if (dpyinfo->n_planes >= 2)
7725 /* Color (or grayscale). Convert to gray, and equalize. Just
7726 drawing such images with a stipple can look very odd, so
7727 we're using this method instead. */
7728 XColor *colors = x_to_xcolors (f, img, 1);
7729 XColor *p, *end;
7730 const int h = 15000;
7731 const int l = 30000;
7733 for (p = colors, end = colors + img->width * img->height;
7734 p < end;
7735 ++p)
7737 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
7738 int i2 = (0xffff - h - l) * i / 0xffff + l;
7739 p->red = p->green = p->blue = i2;
7742 x_from_xcolors (f, img, colors);
7745 /* Draw a cross over the disabled image, if we must or if we
7746 should. */
7747 if (dpyinfo->n_planes < 2 || cross_disabled_images)
7749 Display *dpy = FRAME_X_DISPLAY (f);
7750 GC gc;
7752 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
7753 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
7754 XDrawLine (dpy, img->pixmap, gc, 0, 0,
7755 img->width - 1, img->height - 1);
7756 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
7757 img->width - 1, 0);
7758 XFreeGC (dpy, gc);
7760 if (img->mask)
7762 gc = XCreateGC (dpy, img->mask, 0, NULL);
7763 XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
7764 XDrawLine (dpy, img->mask, gc, 0, 0,
7765 img->width - 1, img->height - 1);
7766 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
7767 img->width - 1, 0);
7768 XFreeGC (dpy, gc);
7774 /* Build a mask for image IMG which is used on frame F. FILE is the
7775 name of an image file, for error messages. HOW determines how to
7776 determine the background color of IMG. If it is a list '(R G B)',
7777 with R, G, and B being integers >= 0, take that as the color of the
7778 background. Otherwise, determine the background color of IMG
7779 heuristically. Value is non-zero if successful. */
7781 static int
7782 x_build_heuristic_mask (f, img, how)
7783 struct frame *f;
7784 struct image *img;
7785 Lisp_Object how;
7787 Display *dpy = FRAME_X_DISPLAY (f);
7788 XImage *ximg, *mask_img;
7789 int x, y, rc, look_at_corners_p;
7790 unsigned long bg = 0;
7792 if (img->mask)
7794 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
7795 img->mask = None;
7798 /* Create an image and pixmap serving as mask. */
7799 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
7800 &mask_img, &img->mask);
7801 if (!rc)
7802 return 0;
7804 /* Get the X image of IMG->pixmap. */
7805 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
7806 ~0, ZPixmap);
7808 /* Determine the background color of ximg. If HOW is `(R G B)'
7809 take that as color. Otherwise, try to determine the color
7810 heuristically. */
7811 look_at_corners_p = 1;
7813 if (CONSP (how))
7815 int rgb[3], i = 0;
7817 while (i < 3
7818 && CONSP (how)
7819 && NATNUMP (XCAR (how)))
7821 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
7822 how = XCDR (how);
7825 if (i == 3 && NILP (how))
7827 char color_name[30];
7828 XColor exact, color;
7829 Colormap cmap;
7831 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
7833 cmap = FRAME_X_COLORMAP (f);
7834 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
7836 bg = color.pixel;
7837 look_at_corners_p = 0;
7842 if (look_at_corners_p)
7844 unsigned long corners[4];
7845 int i, best_count;
7847 /* Get the colors at the corners of ximg. */
7848 corners[0] = XGetPixel (ximg, 0, 0);
7849 corners[1] = XGetPixel (ximg, img->width - 1, 0);
7850 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
7851 corners[3] = XGetPixel (ximg, 0, img->height - 1);
7853 /* Choose the most frequently found color as background. */
7854 for (i = best_count = 0; i < 4; ++i)
7856 int j, n;
7858 for (j = n = 0; j < 4; ++j)
7859 if (corners[i] == corners[j])
7860 ++n;
7862 if (n > best_count)
7863 bg = corners[i], best_count = n;
7867 /* Set all bits in mask_img to 1 whose color in ximg is different
7868 from the background color bg. */
7869 for (y = 0; y < img->height; ++y)
7870 for (x = 0; x < img->width; ++x)
7871 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
7873 /* Put mask_img into img->mask. */
7874 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7875 x_destroy_x_image (mask_img);
7876 XDestroyImage (ximg);
7878 return 1;
7883 /***********************************************************************
7884 PBM (mono, gray, color)
7885 ***********************************************************************/
7887 static int pbm_image_p P_ ((Lisp_Object object));
7888 static int pbm_load P_ ((struct frame *f, struct image *img));
7889 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7891 /* The symbol `pbm' identifying images of this type. */
7893 Lisp_Object Qpbm;
7895 /* Indices of image specification fields in gs_format, below. */
7897 enum pbm_keyword_index
7899 PBM_TYPE,
7900 PBM_FILE,
7901 PBM_DATA,
7902 PBM_ASCENT,
7903 PBM_MARGIN,
7904 PBM_RELIEF,
7905 PBM_ALGORITHM,
7906 PBM_HEURISTIC_MASK,
7907 PBM_MASK,
7908 PBM_FOREGROUND,
7909 PBM_BACKGROUND,
7910 PBM_LAST
7913 /* Vector of image_keyword structures describing the format
7914 of valid user-defined image specifications. */
7916 static struct image_keyword pbm_format[PBM_LAST] =
7918 {":type", IMAGE_SYMBOL_VALUE, 1},
7919 {":file", IMAGE_STRING_VALUE, 0},
7920 {":data", IMAGE_STRING_VALUE, 0},
7921 {":ascent", IMAGE_ASCENT_VALUE, 0},
7922 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7923 {":relief", IMAGE_INTEGER_VALUE, 0},
7924 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7925 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7926 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7927 {":foreground", IMAGE_STRING_VALUE, 0},
7928 {":background", IMAGE_STRING_VALUE, 0}
7931 /* Structure describing the image type `pbm'. */
7933 static struct image_type pbm_type =
7935 &Qpbm,
7936 pbm_image_p,
7937 pbm_load,
7938 x_clear_image,
7939 NULL
7943 /* Return non-zero if OBJECT is a valid PBM image specification. */
7945 static int
7946 pbm_image_p (object)
7947 Lisp_Object object;
7949 struct image_keyword fmt[PBM_LAST];
7951 bcopy (pbm_format, fmt, sizeof fmt);
7953 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
7954 return 0;
7956 /* Must specify either :data or :file. */
7957 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7961 /* Scan a decimal number from *S and return it. Advance *S while
7962 reading the number. END is the end of the string. Value is -1 at
7963 end of input. */
7965 static int
7966 pbm_scan_number (s, end)
7967 unsigned char **s, *end;
7969 int c = 0, val = -1;
7971 while (*s < end)
7973 /* Skip white-space. */
7974 while (*s < end && (c = *(*s)++, isspace (c)))
7977 if (c == '#')
7979 /* Skip comment to end of line. */
7980 while (*s < end && (c = *(*s)++, c != '\n'))
7983 else if (isdigit (c))
7985 /* Read decimal number. */
7986 val = c - '0';
7987 while (*s < end && (c = *(*s)++, isdigit (c)))
7988 val = 10 * val + c - '0';
7989 break;
7991 else
7992 break;
7995 return val;
7999 /* Load PBM image IMG for use on frame F. */
8001 static int
8002 pbm_load (f, img)
8003 struct frame *f;
8004 struct image *img;
8006 int raw_p, x, y;
8007 int width, height, max_color_idx = 0;
8008 XImage *ximg;
8009 Lisp_Object file, specified_file;
8010 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
8011 struct gcpro gcpro1;
8012 unsigned char *contents = NULL;
8013 unsigned char *end, *p;
8014 int size;
8016 specified_file = image_spec_value (img->spec, QCfile, NULL);
8017 file = Qnil;
8018 GCPRO1 (file);
8020 if (STRINGP (specified_file))
8022 file = x_find_image_file (specified_file);
8023 if (!STRINGP (file))
8025 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8026 UNGCPRO;
8027 return 0;
8030 contents = slurp_file (XSTRING (file)->data, &size);
8031 if (contents == NULL)
8033 image_error ("Error reading `%s'", file, Qnil);
8034 UNGCPRO;
8035 return 0;
8038 p = contents;
8039 end = contents + size;
8041 else
8043 Lisp_Object data;
8044 data = image_spec_value (img->spec, QCdata, NULL);
8045 p = XSTRING (data)->data;
8046 end = p + STRING_BYTES (XSTRING (data));
8049 /* Check magic number. */
8050 if (end - p < 2 || *p++ != 'P')
8052 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8053 error:
8054 xfree (contents);
8055 UNGCPRO;
8056 return 0;
8059 switch (*p++)
8061 case '1':
8062 raw_p = 0, type = PBM_MONO;
8063 break;
8065 case '2':
8066 raw_p = 0, type = PBM_GRAY;
8067 break;
8069 case '3':
8070 raw_p = 0, type = PBM_COLOR;
8071 break;
8073 case '4':
8074 raw_p = 1, type = PBM_MONO;
8075 break;
8077 case '5':
8078 raw_p = 1, type = PBM_GRAY;
8079 break;
8081 case '6':
8082 raw_p = 1, type = PBM_COLOR;
8083 break;
8085 default:
8086 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
8087 goto error;
8090 /* Read width, height, maximum color-component. Characters
8091 starting with `#' up to the end of a line are ignored. */
8092 width = pbm_scan_number (&p, end);
8093 height = pbm_scan_number (&p, end);
8095 if (type != PBM_MONO)
8097 max_color_idx = pbm_scan_number (&p, end);
8098 if (raw_p && max_color_idx > 255)
8099 max_color_idx = 255;
8102 if (width < 0
8103 || height < 0
8104 || (type != PBM_MONO && max_color_idx < 0))
8105 goto error;
8107 if (!x_create_x_image_and_pixmap (f, width, height, 0,
8108 &ximg, &img->pixmap))
8109 goto error;
8111 /* Initialize the color hash table. */
8112 init_color_table ();
8114 if (type == PBM_MONO)
8116 int c = 0, g;
8117 struct image_keyword fmt[PBM_LAST];
8118 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
8119 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
8121 /* Parse the image specification. */
8122 bcopy (pbm_format, fmt, sizeof fmt);
8123 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
8125 /* Get foreground and background colors, maybe allocate colors. */
8126 if (fmt[PBM_FOREGROUND].count)
8127 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
8128 if (fmt[PBM_BACKGROUND].count)
8129 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
8131 for (y = 0; y < height; ++y)
8132 for (x = 0; x < width; ++x)
8134 if (raw_p)
8136 if ((x & 7) == 0)
8137 c = *p++;
8138 g = c & 0x80;
8139 c <<= 1;
8141 else
8142 g = pbm_scan_number (&p, end);
8144 XPutPixel (ximg, x, y, g ? fg : bg);
8147 else
8149 for (y = 0; y < height; ++y)
8150 for (x = 0; x < width; ++x)
8152 int r, g, b;
8154 if (type == PBM_GRAY)
8155 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
8156 else if (raw_p)
8158 r = *p++;
8159 g = *p++;
8160 b = *p++;
8162 else
8164 r = pbm_scan_number (&p, end);
8165 g = pbm_scan_number (&p, end);
8166 b = pbm_scan_number (&p, end);
8169 if (r < 0 || g < 0 || b < 0)
8171 xfree (ximg->data);
8172 ximg->data = NULL;
8173 XDestroyImage (ximg);
8174 image_error ("Invalid pixel value in image `%s'",
8175 img->spec, Qnil);
8176 goto error;
8179 /* RGB values are now in the range 0..max_color_idx.
8180 Scale this to the range 0..0xffff supported by X. */
8181 r = (double) r * 65535 / max_color_idx;
8182 g = (double) g * 65535 / max_color_idx;
8183 b = (double) b * 65535 / max_color_idx;
8184 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8188 /* Store in IMG->colors the colors allocated for the image, and
8189 free the color table. */
8190 img->colors = colors_in_color_table (&img->ncolors);
8191 free_color_table ();
8193 /* Put the image into a pixmap. */
8194 x_put_x_image (f, ximg, img->pixmap, width, height);
8195 x_destroy_x_image (ximg);
8197 img->width = width;
8198 img->height = height;
8200 UNGCPRO;
8201 xfree (contents);
8202 return 1;
8207 /***********************************************************************
8209 ***********************************************************************/
8211 #if HAVE_PNG
8213 #include <png.h>
8215 /* Function prototypes. */
8217 static int png_image_p P_ ((Lisp_Object object));
8218 static int png_load P_ ((struct frame *f, struct image *img));
8220 /* The symbol `png' identifying images of this type. */
8222 Lisp_Object Qpng;
8224 /* Indices of image specification fields in png_format, below. */
8226 enum png_keyword_index
8228 PNG_TYPE,
8229 PNG_DATA,
8230 PNG_FILE,
8231 PNG_ASCENT,
8232 PNG_MARGIN,
8233 PNG_RELIEF,
8234 PNG_ALGORITHM,
8235 PNG_HEURISTIC_MASK,
8236 PNG_MASK,
8237 PNG_LAST
8240 /* Vector of image_keyword structures describing the format
8241 of valid user-defined image specifications. */
8243 static struct image_keyword png_format[PNG_LAST] =
8245 {":type", IMAGE_SYMBOL_VALUE, 1},
8246 {":data", IMAGE_STRING_VALUE, 0},
8247 {":file", IMAGE_STRING_VALUE, 0},
8248 {":ascent", IMAGE_ASCENT_VALUE, 0},
8249 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8250 {":relief", IMAGE_INTEGER_VALUE, 0},
8251 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8252 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8253 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8256 /* Structure describing the image type `png'. */
8258 static struct image_type png_type =
8260 &Qpng,
8261 png_image_p,
8262 png_load,
8263 x_clear_image,
8264 NULL
8268 /* Return non-zero if OBJECT is a valid PNG image specification. */
8270 static int
8271 png_image_p (object)
8272 Lisp_Object object;
8274 struct image_keyword fmt[PNG_LAST];
8275 bcopy (png_format, fmt, sizeof fmt);
8277 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
8278 return 0;
8280 /* Must specify either the :data or :file keyword. */
8281 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
8285 /* Error and warning handlers installed when the PNG library
8286 is initialized. */
8288 static void
8289 my_png_error (png_ptr, msg)
8290 png_struct *png_ptr;
8291 char *msg;
8293 xassert (png_ptr != NULL);
8294 image_error ("PNG error: %s", build_string (msg), Qnil);
8295 longjmp (png_ptr->jmpbuf, 1);
8299 static void
8300 my_png_warning (png_ptr, msg)
8301 png_struct *png_ptr;
8302 char *msg;
8304 xassert (png_ptr != NULL);
8305 image_error ("PNG warning: %s", build_string (msg), Qnil);
8308 /* Memory source for PNG decoding. */
8310 struct png_memory_storage
8312 unsigned char *bytes; /* The data */
8313 size_t len; /* How big is it? */
8314 int index; /* Where are we? */
8318 /* Function set as reader function when reading PNG image from memory.
8319 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8320 bytes from the input to DATA. */
8322 static void
8323 png_read_from_memory (png_ptr, data, length)
8324 png_structp png_ptr;
8325 png_bytep data;
8326 png_size_t length;
8328 struct png_memory_storage *tbr
8329 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8331 if (length > tbr->len - tbr->index)
8332 png_error (png_ptr, "Read error");
8334 bcopy (tbr->bytes + tbr->index, data, length);
8335 tbr->index = tbr->index + length;
8338 /* Load PNG image IMG for use on frame F. Value is non-zero if
8339 successful. */
8341 static int
8342 png_load (f, img)
8343 struct frame *f;
8344 struct image *img;
8346 Lisp_Object file, specified_file;
8347 Lisp_Object specified_data;
8348 int x, y, i;
8349 XImage *ximg, *mask_img = NULL;
8350 struct gcpro gcpro1;
8351 png_struct *png_ptr = NULL;
8352 png_info *info_ptr = NULL, *end_info = NULL;
8353 FILE *volatile fp = NULL;
8354 png_byte sig[8];
8355 png_byte * volatile pixels = NULL;
8356 png_byte ** volatile rows = NULL;
8357 png_uint_32 width, height;
8358 int bit_depth, color_type, interlace_type;
8359 png_byte channels;
8360 png_uint_32 row_bytes;
8361 int transparent_p;
8362 char *gamma_str;
8363 double screen_gamma, image_gamma;
8364 int intent;
8365 struct png_memory_storage tbr; /* Data to be read */
8367 /* Find out what file to load. */
8368 specified_file = image_spec_value (img->spec, QCfile, NULL);
8369 specified_data = image_spec_value (img->spec, QCdata, NULL);
8370 file = Qnil;
8371 GCPRO1 (file);
8373 if (NILP (specified_data))
8375 file = x_find_image_file (specified_file);
8376 if (!STRINGP (file))
8378 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8379 UNGCPRO;
8380 return 0;
8383 /* Open the image file. */
8384 fp = fopen (XSTRING (file)->data, "rb");
8385 if (!fp)
8387 image_error ("Cannot open image file `%s'", file, Qnil);
8388 UNGCPRO;
8389 fclose (fp);
8390 return 0;
8393 /* Check PNG signature. */
8394 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8395 || !png_check_sig (sig, sizeof sig))
8397 image_error ("Not a PNG file: `%s'", file, Qnil);
8398 UNGCPRO;
8399 fclose (fp);
8400 return 0;
8403 else
8405 /* Read from memory. */
8406 tbr.bytes = XSTRING (specified_data)->data;
8407 tbr.len = STRING_BYTES (XSTRING (specified_data));
8408 tbr.index = 0;
8410 /* Check PNG signature. */
8411 if (tbr.len < sizeof sig
8412 || !png_check_sig (tbr.bytes, sizeof sig))
8414 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
8415 UNGCPRO;
8416 return 0;
8419 /* Need to skip past the signature. */
8420 tbr.bytes += sizeof (sig);
8423 /* Initialize read and info structs for PNG lib. */
8424 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8425 my_png_error, my_png_warning);
8426 if (!png_ptr)
8428 if (fp) fclose (fp);
8429 UNGCPRO;
8430 return 0;
8433 info_ptr = png_create_info_struct (png_ptr);
8434 if (!info_ptr)
8436 png_destroy_read_struct (&png_ptr, NULL, NULL);
8437 if (fp) fclose (fp);
8438 UNGCPRO;
8439 return 0;
8442 end_info = png_create_info_struct (png_ptr);
8443 if (!end_info)
8445 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
8446 if (fp) fclose (fp);
8447 UNGCPRO;
8448 return 0;
8451 /* Set error jump-back. We come back here when the PNG library
8452 detects an error. */
8453 if (setjmp (png_ptr->jmpbuf))
8455 error:
8456 if (png_ptr)
8457 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8458 xfree (pixels);
8459 xfree (rows);
8460 if (fp) fclose (fp);
8461 UNGCPRO;
8462 return 0;
8465 /* Read image info. */
8466 if (!NILP (specified_data))
8467 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8468 else
8469 png_init_io (png_ptr, fp);
8471 png_set_sig_bytes (png_ptr, sizeof sig);
8472 png_read_info (png_ptr, info_ptr);
8473 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
8474 &interlace_type, NULL, NULL);
8476 /* If image contains simply transparency data, we prefer to
8477 construct a clipping mask. */
8478 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
8479 transparent_p = 1;
8480 else
8481 transparent_p = 0;
8483 /* This function is easier to write if we only have to handle
8484 one data format: RGB or RGBA with 8 bits per channel. Let's
8485 transform other formats into that format. */
8487 /* Strip more than 8 bits per channel. */
8488 if (bit_depth == 16)
8489 png_set_strip_16 (png_ptr);
8491 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
8492 if available. */
8493 png_set_expand (png_ptr);
8495 /* Convert grayscale images to RGB. */
8496 if (color_type == PNG_COLOR_TYPE_GRAY
8497 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8498 png_set_gray_to_rgb (png_ptr);
8500 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
8501 gamma_str = getenv ("SCREEN_GAMMA");
8502 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
8504 /* Tell the PNG lib to handle gamma correction for us. */
8506 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
8507 if (png_get_sRGB (png_ptr, info_ptr, &intent))
8508 /* There is a special chunk in the image specifying the gamma. */
8509 png_set_sRGB (png_ptr, info_ptr, intent);
8510 else
8511 #endif
8512 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
8513 /* Image contains gamma information. */
8514 png_set_gamma (png_ptr, screen_gamma, image_gamma);
8515 else
8516 /* Use a default of 0.5 for the image gamma. */
8517 png_set_gamma (png_ptr, screen_gamma, 0.5);
8519 /* Handle alpha channel by combining the image with a background
8520 color. Do this only if a real alpha channel is supplied. For
8521 simple transparency, we prefer a clipping mask. */
8522 if (!transparent_p)
8524 png_color_16 *image_background;
8526 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
8527 /* Image contains a background color with which to
8528 combine the image. */
8529 png_set_background (png_ptr, image_background,
8530 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
8531 else
8533 /* Image does not contain a background color with which
8534 to combine the image data via an alpha channel. Use
8535 the frame's background instead. */
8536 XColor color;
8537 Colormap cmap;
8538 png_color_16 frame_background;
8540 cmap = FRAME_X_COLORMAP (f);
8541 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8542 x_query_color (f, &color);
8544 bzero (&frame_background, sizeof frame_background);
8545 frame_background.red = color.red;
8546 frame_background.green = color.green;
8547 frame_background.blue = color.blue;
8549 png_set_background (png_ptr, &frame_background,
8550 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
8554 /* Update info structure. */
8555 png_read_update_info (png_ptr, info_ptr);
8557 /* Get number of channels. Valid values are 1 for grayscale images
8558 and images with a palette, 2 for grayscale images with transparency
8559 information (alpha channel), 3 for RGB images, and 4 for RGB
8560 images with alpha channel, i.e. RGBA. If conversions above were
8561 sufficient we should only have 3 or 4 channels here. */
8562 channels = png_get_channels (png_ptr, info_ptr);
8563 xassert (channels == 3 || channels == 4);
8565 /* Number of bytes needed for one row of the image. */
8566 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
8568 /* Allocate memory for the image. */
8569 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
8570 rows = (png_byte **) xmalloc (height * sizeof *rows);
8571 for (i = 0; i < height; ++i)
8572 rows[i] = pixels + i * row_bytes;
8574 /* Read the entire image. */
8575 png_read_image (png_ptr, rows);
8576 png_read_end (png_ptr, info_ptr);
8577 if (fp)
8579 fclose (fp);
8580 fp = NULL;
8583 /* Create the X image and pixmap. */
8584 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
8585 &img->pixmap))
8586 goto error;
8588 /* Create an image and pixmap serving as mask if the PNG image
8589 contains an alpha channel. */
8590 if (channels == 4
8591 && !transparent_p
8592 && !x_create_x_image_and_pixmap (f, width, height, 1,
8593 &mask_img, &img->mask))
8595 x_destroy_x_image (ximg);
8596 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
8597 img->pixmap = None;
8598 goto error;
8601 /* Fill the X image and mask from PNG data. */
8602 init_color_table ();
8604 for (y = 0; y < height; ++y)
8606 png_byte *p = rows[y];
8608 for (x = 0; x < width; ++x)
8610 unsigned r, g, b;
8612 r = *p++ << 8;
8613 g = *p++ << 8;
8614 b = *p++ << 8;
8615 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
8617 /* An alpha channel, aka mask channel, associates variable
8618 transparency with an image. Where other image formats
8619 support binary transparency---fully transparent or fully
8620 opaque---PNG allows up to 254 levels of partial transparency.
8621 The PNG library implements partial transparency by combining
8622 the image with a specified background color.
8624 I'm not sure how to handle this here nicely: because the
8625 background on which the image is displayed may change, for
8626 real alpha channel support, it would be necessary to create
8627 a new image for each possible background.
8629 What I'm doing now is that a mask is created if we have
8630 boolean transparency information. Otherwise I'm using
8631 the frame's background color to combine the image with. */
8633 if (channels == 4)
8635 if (mask_img)
8636 XPutPixel (mask_img, x, y, *p > 0);
8637 ++p;
8642 /* Remember colors allocated for this image. */
8643 img->colors = colors_in_color_table (&img->ncolors);
8644 free_color_table ();
8646 /* Clean up. */
8647 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
8648 xfree (rows);
8649 xfree (pixels);
8651 img->width = width;
8652 img->height = height;
8654 /* Put the image into the pixmap, then free the X image and its buffer. */
8655 x_put_x_image (f, ximg, img->pixmap, width, height);
8656 x_destroy_x_image (ximg);
8658 /* Same for the mask. */
8659 if (mask_img)
8661 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
8662 x_destroy_x_image (mask_img);
8665 UNGCPRO;
8666 return 1;
8669 #endif /* HAVE_PNG != 0 */
8673 /***********************************************************************
8674 JPEG
8675 ***********************************************************************/
8677 #if HAVE_JPEG
8679 /* Work around a warning about HAVE_STDLIB_H being redefined in
8680 jconfig.h. */
8681 #ifdef HAVE_STDLIB_H
8682 #define HAVE_STDLIB_H_1
8683 #undef HAVE_STDLIB_H
8684 #endif /* HAVE_STLIB_H */
8686 #include <jpeglib.h>
8687 #include <jerror.h>
8688 #include <setjmp.h>
8690 #ifdef HAVE_STLIB_H_1
8691 #define HAVE_STDLIB_H 1
8692 #endif
8694 static int jpeg_image_p P_ ((Lisp_Object object));
8695 static int jpeg_load P_ ((struct frame *f, struct image *img));
8697 /* The symbol `jpeg' identifying images of this type. */
8699 Lisp_Object Qjpeg;
8701 /* Indices of image specification fields in gs_format, below. */
8703 enum jpeg_keyword_index
8705 JPEG_TYPE,
8706 JPEG_DATA,
8707 JPEG_FILE,
8708 JPEG_ASCENT,
8709 JPEG_MARGIN,
8710 JPEG_RELIEF,
8711 JPEG_ALGORITHM,
8712 JPEG_HEURISTIC_MASK,
8713 JPEG_MASK,
8714 JPEG_LAST
8717 /* Vector of image_keyword structures describing the format
8718 of valid user-defined image specifications. */
8720 static struct image_keyword jpeg_format[JPEG_LAST] =
8722 {":type", IMAGE_SYMBOL_VALUE, 1},
8723 {":data", IMAGE_STRING_VALUE, 0},
8724 {":file", IMAGE_STRING_VALUE, 0},
8725 {":ascent", IMAGE_ASCENT_VALUE, 0},
8726 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8727 {":relief", IMAGE_INTEGER_VALUE, 0},
8728 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8729 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8730 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8733 /* Structure describing the image type `jpeg'. */
8735 static struct image_type jpeg_type =
8737 &Qjpeg,
8738 jpeg_image_p,
8739 jpeg_load,
8740 x_clear_image,
8741 NULL
8745 /* Return non-zero if OBJECT is a valid JPEG image specification. */
8747 static int
8748 jpeg_image_p (object)
8749 Lisp_Object object;
8751 struct image_keyword fmt[JPEG_LAST];
8753 bcopy (jpeg_format, fmt, sizeof fmt);
8755 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
8756 return 0;
8758 /* Must specify either the :data or :file keyword. */
8759 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8763 struct my_jpeg_error_mgr
8765 struct jpeg_error_mgr pub;
8766 jmp_buf setjmp_buffer;
8770 static void
8771 my_error_exit (cinfo)
8772 j_common_ptr cinfo;
8774 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
8775 longjmp (mgr->setjmp_buffer, 1);
8779 /* Init source method for JPEG data source manager. Called by
8780 jpeg_read_header() before any data is actually read. See
8781 libjpeg.doc from the JPEG lib distribution. */
8783 static void
8784 our_init_source (cinfo)
8785 j_decompress_ptr cinfo;
8790 /* Fill input buffer method for JPEG data source manager. Called
8791 whenever more data is needed. We read the whole image in one step,
8792 so this only adds a fake end of input marker at the end. */
8794 static boolean
8795 our_fill_input_buffer (cinfo)
8796 j_decompress_ptr cinfo;
8798 /* Insert a fake EOI marker. */
8799 struct jpeg_source_mgr *src = cinfo->src;
8800 static JOCTET buffer[2];
8802 buffer[0] = (JOCTET) 0xFF;
8803 buffer[1] = (JOCTET) JPEG_EOI;
8805 src->next_input_byte = buffer;
8806 src->bytes_in_buffer = 2;
8807 return TRUE;
8811 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
8812 is the JPEG data source manager. */
8814 static void
8815 our_skip_input_data (cinfo, num_bytes)
8816 j_decompress_ptr cinfo;
8817 long num_bytes;
8819 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
8821 if (src)
8823 if (num_bytes > src->bytes_in_buffer)
8824 ERREXIT (cinfo, JERR_INPUT_EOF);
8826 src->bytes_in_buffer -= num_bytes;
8827 src->next_input_byte += num_bytes;
8832 /* Method to terminate data source. Called by
8833 jpeg_finish_decompress() after all data has been processed. */
8835 static void
8836 our_term_source (cinfo)
8837 j_decompress_ptr cinfo;
8842 /* Set up the JPEG lib for reading an image from DATA which contains
8843 LEN bytes. CINFO is the decompression info structure created for
8844 reading the image. */
8846 static void
8847 jpeg_memory_src (cinfo, data, len)
8848 j_decompress_ptr cinfo;
8849 JOCTET *data;
8850 unsigned int len;
8852 struct jpeg_source_mgr *src;
8854 if (cinfo->src == NULL)
8856 /* First time for this JPEG object? */
8857 cinfo->src = (struct jpeg_source_mgr *)
8858 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
8859 sizeof (struct jpeg_source_mgr));
8860 src = (struct jpeg_source_mgr *) cinfo->src;
8861 src->next_input_byte = data;
8864 src = (struct jpeg_source_mgr *) cinfo->src;
8865 src->init_source = our_init_source;
8866 src->fill_input_buffer = our_fill_input_buffer;
8867 src->skip_input_data = our_skip_input_data;
8868 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
8869 src->term_source = our_term_source;
8870 src->bytes_in_buffer = len;
8871 src->next_input_byte = data;
8875 /* Load image IMG for use on frame F. Patterned after example.c
8876 from the JPEG lib. */
8878 static int
8879 jpeg_load (f, img)
8880 struct frame *f;
8881 struct image *img;
8883 struct jpeg_decompress_struct cinfo;
8884 struct my_jpeg_error_mgr mgr;
8885 Lisp_Object file, specified_file;
8886 Lisp_Object specified_data;
8887 FILE * volatile fp = NULL;
8888 JSAMPARRAY buffer;
8889 int row_stride, x, y;
8890 XImage *ximg = NULL;
8891 int rc;
8892 unsigned long *colors;
8893 int width, height;
8894 struct gcpro gcpro1;
8896 /* Open the JPEG file. */
8897 specified_file = image_spec_value (img->spec, QCfile, NULL);
8898 specified_data = image_spec_value (img->spec, QCdata, NULL);
8899 file = Qnil;
8900 GCPRO1 (file);
8902 if (NILP (specified_data))
8904 file = x_find_image_file (specified_file);
8905 if (!STRINGP (file))
8907 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8908 UNGCPRO;
8909 return 0;
8912 fp = fopen (XSTRING (file)->data, "r");
8913 if (fp == NULL)
8915 image_error ("Cannot open `%s'", file, Qnil);
8916 UNGCPRO;
8917 return 0;
8921 /* Customize libjpeg's error handling to call my_error_exit when an
8922 error is detected. This function will perform a longjmp. */
8923 cinfo.err = jpeg_std_error (&mgr.pub);
8924 mgr.pub.error_exit = my_error_exit;
8926 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8928 if (rc == 1)
8930 /* Called from my_error_exit. Display a JPEG error. */
8931 char buffer[JMSG_LENGTH_MAX];
8932 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8933 image_error ("Error reading JPEG image `%s': %s", img->spec,
8934 build_string (buffer));
8937 /* Close the input file and destroy the JPEG object. */
8938 if (fp)
8939 fclose ((FILE *) fp);
8940 jpeg_destroy_decompress (&cinfo);
8942 /* If we already have an XImage, free that. */
8943 x_destroy_x_image (ximg);
8945 /* Free pixmap and colors. */
8946 x_clear_image (f, img);
8948 UNGCPRO;
8949 return 0;
8952 /* Create the JPEG decompression object. Let it read from fp.
8953 Read the JPEG image header. */
8954 jpeg_create_decompress (&cinfo);
8956 if (NILP (specified_data))
8957 jpeg_stdio_src (&cinfo, (FILE *) fp);
8958 else
8959 jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
8960 STRING_BYTES (XSTRING (specified_data)));
8962 jpeg_read_header (&cinfo, TRUE);
8964 /* Customize decompression so that color quantization will be used.
8965 Start decompression. */
8966 cinfo.quantize_colors = TRUE;
8967 jpeg_start_decompress (&cinfo);
8968 width = img->width = cinfo.output_width;
8969 height = img->height = cinfo.output_height;
8971 /* Create X image and pixmap. */
8972 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8973 longjmp (mgr.setjmp_buffer, 2);
8975 /* Allocate colors. When color quantization is used,
8976 cinfo.actual_number_of_colors has been set with the number of
8977 colors generated, and cinfo.colormap is a two-dimensional array
8978 of color indices in the range 0..cinfo.actual_number_of_colors.
8979 No more than 255 colors will be generated. */
8981 int i, ir, ig, ib;
8983 if (cinfo.out_color_components > 2)
8984 ir = 0, ig = 1, ib = 2;
8985 else if (cinfo.out_color_components > 1)
8986 ir = 0, ig = 1, ib = 0;
8987 else
8988 ir = 0, ig = 0, ib = 0;
8990 /* Use the color table mechanism because it handles colors that
8991 cannot be allocated nicely. Such colors will be replaced with
8992 a default color, and we don't have to care about which colors
8993 can be freed safely, and which can't. */
8994 init_color_table ();
8995 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8996 * sizeof *colors);
8998 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
9000 /* Multiply RGB values with 255 because X expects RGB values
9001 in the range 0..0xffff. */
9002 int r = cinfo.colormap[ir][i] << 8;
9003 int g = cinfo.colormap[ig][i] << 8;
9004 int b = cinfo.colormap[ib][i] << 8;
9005 colors[i] = lookup_rgb_color (f, r, g, b);
9008 /* Remember those colors actually allocated. */
9009 img->colors = colors_in_color_table (&img->ncolors);
9010 free_color_table ();
9013 /* Read pixels. */
9014 row_stride = width * cinfo.output_components;
9015 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
9016 row_stride, 1);
9017 for (y = 0; y < height; ++y)
9019 jpeg_read_scanlines (&cinfo, buffer, 1);
9020 for (x = 0; x < cinfo.output_width; ++x)
9021 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
9024 /* Clean up. */
9025 jpeg_finish_decompress (&cinfo);
9026 jpeg_destroy_decompress (&cinfo);
9027 if (fp)
9028 fclose ((FILE *) fp);
9030 /* Put the image into the pixmap. */
9031 x_put_x_image (f, ximg, img->pixmap, width, height);
9032 x_destroy_x_image (ximg);
9033 UNGCPRO;
9034 return 1;
9037 #endif /* HAVE_JPEG */
9041 /***********************************************************************
9042 TIFF
9043 ***********************************************************************/
9045 #if HAVE_TIFF
9047 #include <tiffio.h>
9049 static int tiff_image_p P_ ((Lisp_Object object));
9050 static int tiff_load P_ ((struct frame *f, struct image *img));
9052 /* The symbol `tiff' identifying images of this type. */
9054 Lisp_Object Qtiff;
9056 /* Indices of image specification fields in tiff_format, below. */
9058 enum tiff_keyword_index
9060 TIFF_TYPE,
9061 TIFF_DATA,
9062 TIFF_FILE,
9063 TIFF_ASCENT,
9064 TIFF_MARGIN,
9065 TIFF_RELIEF,
9066 TIFF_ALGORITHM,
9067 TIFF_HEURISTIC_MASK,
9068 TIFF_MASK,
9069 TIFF_LAST
9072 /* Vector of image_keyword structures describing the format
9073 of valid user-defined image specifications. */
9075 static struct image_keyword tiff_format[TIFF_LAST] =
9077 {":type", IMAGE_SYMBOL_VALUE, 1},
9078 {":data", IMAGE_STRING_VALUE, 0},
9079 {":file", IMAGE_STRING_VALUE, 0},
9080 {":ascent", IMAGE_ASCENT_VALUE, 0},
9081 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9082 {":relief", IMAGE_INTEGER_VALUE, 0},
9083 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9084 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9085 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9088 /* Structure describing the image type `tiff'. */
9090 static struct image_type tiff_type =
9092 &Qtiff,
9093 tiff_image_p,
9094 tiff_load,
9095 x_clear_image,
9096 NULL
9100 /* Return non-zero if OBJECT is a valid TIFF image specification. */
9102 static int
9103 tiff_image_p (object)
9104 Lisp_Object object;
9106 struct image_keyword fmt[TIFF_LAST];
9107 bcopy (tiff_format, fmt, sizeof fmt);
9109 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
9110 return 0;
9112 /* Must specify either the :data or :file keyword. */
9113 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
9117 /* Reading from a memory buffer for TIFF images Based on the PNG
9118 memory source, but we have to provide a lot of extra functions.
9119 Blah.
9121 We really only need to implement read and seek, but I am not
9122 convinced that the TIFF library is smart enough not to destroy
9123 itself if we only hand it the function pointers we need to
9124 override. */
9126 typedef struct
9128 unsigned char *bytes;
9129 size_t len;
9130 int index;
9132 tiff_memory_source;
9135 static size_t
9136 tiff_read_from_memory (data, buf, size)
9137 thandle_t data;
9138 tdata_t buf;
9139 tsize_t size;
9141 tiff_memory_source *src = (tiff_memory_source *) data;
9143 if (size > src->len - src->index)
9144 return (size_t) -1;
9145 bcopy (src->bytes + src->index, buf, size);
9146 src->index += size;
9147 return size;
9151 static size_t
9152 tiff_write_from_memory (data, buf, size)
9153 thandle_t data;
9154 tdata_t buf;
9155 tsize_t size;
9157 return (size_t) -1;
9161 static toff_t
9162 tiff_seek_in_memory (data, off, whence)
9163 thandle_t data;
9164 toff_t off;
9165 int whence;
9167 tiff_memory_source *src = (tiff_memory_source *) data;
9168 int idx;
9170 switch (whence)
9172 case SEEK_SET: /* Go from beginning of source. */
9173 idx = off;
9174 break;
9176 case SEEK_END: /* Go from end of source. */
9177 idx = src->len + off;
9178 break;
9180 case SEEK_CUR: /* Go from current position. */
9181 idx = src->index + off;
9182 break;
9184 default: /* Invalid `whence'. */
9185 return -1;
9188 if (idx > src->len || idx < 0)
9189 return -1;
9191 src->index = idx;
9192 return src->index;
9196 static int
9197 tiff_close_memory (data)
9198 thandle_t data;
9200 /* NOOP */
9201 return 0;
9205 static int
9206 tiff_mmap_memory (data, pbase, psize)
9207 thandle_t data;
9208 tdata_t *pbase;
9209 toff_t *psize;
9211 /* It is already _IN_ memory. */
9212 return 0;
9216 static void
9217 tiff_unmap_memory (data, base, size)
9218 thandle_t data;
9219 tdata_t base;
9220 toff_t size;
9222 /* We don't need to do this. */
9226 static toff_t
9227 tiff_size_of_memory (data)
9228 thandle_t data;
9230 return ((tiff_memory_source *) data)->len;
9234 /* Load TIFF image IMG for use on frame F. Value is non-zero if
9235 successful. */
9237 static int
9238 tiff_load (f, img)
9239 struct frame *f;
9240 struct image *img;
9242 Lisp_Object file, specified_file;
9243 Lisp_Object specified_data;
9244 TIFF *tiff;
9245 int width, height, x, y;
9246 uint32 *buf;
9247 int rc;
9248 XImage *ximg;
9249 struct gcpro gcpro1;
9250 tiff_memory_source memsrc;
9252 specified_file = image_spec_value (img->spec, QCfile, NULL);
9253 specified_data = image_spec_value (img->spec, QCdata, NULL);
9254 file = Qnil;
9255 GCPRO1 (file);
9257 if (NILP (specified_data))
9259 /* Read from a file */
9260 file = x_find_image_file (specified_file);
9261 if (!STRINGP (file))
9263 image_error ("Cannot find image file `%s'", file, Qnil);
9264 UNGCPRO;
9265 return 0;
9268 /* Try to open the image file. */
9269 tiff = TIFFOpen (XSTRING (file)->data, "r");
9270 if (tiff == NULL)
9272 image_error ("Cannot open `%s'", file, Qnil);
9273 UNGCPRO;
9274 return 0;
9277 else
9279 /* Memory source! */
9280 memsrc.bytes = XSTRING (specified_data)->data;
9281 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9282 memsrc.index = 0;
9284 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9285 (TIFFReadWriteProc) tiff_read_from_memory,
9286 (TIFFReadWriteProc) tiff_write_from_memory,
9287 tiff_seek_in_memory,
9288 tiff_close_memory,
9289 tiff_size_of_memory,
9290 tiff_mmap_memory,
9291 tiff_unmap_memory);
9293 if (!tiff)
9295 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
9296 UNGCPRO;
9297 return 0;
9301 /* Get width and height of the image, and allocate a raster buffer
9302 of width x height 32-bit values. */
9303 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
9304 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
9305 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
9307 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
9308 TIFFClose (tiff);
9309 if (!rc)
9311 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
9312 xfree (buf);
9313 UNGCPRO;
9314 return 0;
9317 /* Create the X image and pixmap. */
9318 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9320 xfree (buf);
9321 UNGCPRO;
9322 return 0;
9325 /* Initialize the color table. */
9326 init_color_table ();
9328 /* Process the pixel raster. Origin is in the lower-left corner. */
9329 for (y = 0; y < height; ++y)
9331 uint32 *row = buf + y * width;
9333 for (x = 0; x < width; ++x)
9335 uint32 abgr = row[x];
9336 int r = TIFFGetR (abgr) << 8;
9337 int g = TIFFGetG (abgr) << 8;
9338 int b = TIFFGetB (abgr) << 8;
9339 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
9343 /* Remember the colors allocated for the image. Free the color table. */
9344 img->colors = colors_in_color_table (&img->ncolors);
9345 free_color_table ();
9347 /* Put the image into the pixmap, then free the X image and its buffer. */
9348 x_put_x_image (f, ximg, img->pixmap, width, height);
9349 x_destroy_x_image (ximg);
9350 xfree (buf);
9352 img->width = width;
9353 img->height = height;
9355 UNGCPRO;
9356 return 1;
9359 #endif /* HAVE_TIFF != 0 */
9363 /***********************************************************************
9365 ***********************************************************************/
9367 #if HAVE_GIF
9369 #include <gif_lib.h>
9371 static int gif_image_p P_ ((Lisp_Object object));
9372 static int gif_load P_ ((struct frame *f, struct image *img));
9374 /* The symbol `gif' identifying images of this type. */
9376 Lisp_Object Qgif;
9378 /* Indices of image specification fields in gif_format, below. */
9380 enum gif_keyword_index
9382 GIF_TYPE,
9383 GIF_DATA,
9384 GIF_FILE,
9385 GIF_ASCENT,
9386 GIF_MARGIN,
9387 GIF_RELIEF,
9388 GIF_ALGORITHM,
9389 GIF_HEURISTIC_MASK,
9390 GIF_MASK,
9391 GIF_IMAGE,
9392 GIF_LAST
9395 /* Vector of image_keyword structures describing the format
9396 of valid user-defined image specifications. */
9398 static struct image_keyword gif_format[GIF_LAST] =
9400 {":type", IMAGE_SYMBOL_VALUE, 1},
9401 {":data", IMAGE_STRING_VALUE, 0},
9402 {":file", IMAGE_STRING_VALUE, 0},
9403 {":ascent", IMAGE_ASCENT_VALUE, 0},
9404 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9405 {":relief", IMAGE_INTEGER_VALUE, 0},
9406 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9407 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9408 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9409 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
9412 /* Structure describing the image type `gif'. */
9414 static struct image_type gif_type =
9416 &Qgif,
9417 gif_image_p,
9418 gif_load,
9419 x_clear_image,
9420 NULL
9424 /* Return non-zero if OBJECT is a valid GIF image specification. */
9426 static int
9427 gif_image_p (object)
9428 Lisp_Object object;
9430 struct image_keyword fmt[GIF_LAST];
9431 bcopy (gif_format, fmt, sizeof fmt);
9433 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
9434 return 0;
9436 /* Must specify either the :data or :file keyword. */
9437 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9441 /* Reading a GIF image from memory
9442 Based on the PNG memory stuff to a certain extent. */
9444 typedef struct
9446 unsigned char *bytes;
9447 size_t len;
9448 int index;
9450 gif_memory_source;
9453 /* Make the current memory source available to gif_read_from_memory.
9454 It's done this way because not all versions of libungif support
9455 a UserData field in the GifFileType structure. */
9456 static gif_memory_source *current_gif_memory_src;
9458 static int
9459 gif_read_from_memory (file, buf, len)
9460 GifFileType *file;
9461 GifByteType *buf;
9462 int len;
9464 gif_memory_source *src = current_gif_memory_src;
9466 if (len > src->len - src->index)
9467 return -1;
9469 bcopy (src->bytes + src->index, buf, len);
9470 src->index += len;
9471 return len;
9475 /* Load GIF image IMG for use on frame F. Value is non-zero if
9476 successful. */
9478 static int
9479 gif_load (f, img)
9480 struct frame *f;
9481 struct image *img;
9483 Lisp_Object file, specified_file;
9484 Lisp_Object specified_data;
9485 int rc, width, height, x, y, i;
9486 XImage *ximg;
9487 ColorMapObject *gif_color_map;
9488 unsigned long pixel_colors[256];
9489 GifFileType *gif;
9490 struct gcpro gcpro1;
9491 Lisp_Object image;
9492 int ino, image_left, image_top, image_width, image_height;
9493 gif_memory_source memsrc;
9494 unsigned char *raster;
9496 specified_file = image_spec_value (img->spec, QCfile, NULL);
9497 specified_data = image_spec_value (img->spec, QCdata, NULL);
9498 file = Qnil;
9499 GCPRO1 (file);
9501 if (NILP (specified_data))
9503 file = x_find_image_file (specified_file);
9504 if (!STRINGP (file))
9506 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9507 UNGCPRO;
9508 return 0;
9511 /* Open the GIF file. */
9512 gif = DGifOpenFileName (XSTRING (file)->data);
9513 if (gif == NULL)
9515 image_error ("Cannot open `%s'", file, Qnil);
9516 UNGCPRO;
9517 return 0;
9520 else
9522 /* Read from memory! */
9523 current_gif_memory_src = &memsrc;
9524 memsrc.bytes = XSTRING (specified_data)->data;
9525 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9526 memsrc.index = 0;
9528 gif = DGifOpen(&memsrc, gif_read_from_memory);
9529 if (!gif)
9531 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
9532 UNGCPRO;
9533 return 0;
9537 /* Read entire contents. */
9538 rc = DGifSlurp (gif);
9539 if (rc == GIF_ERROR)
9541 image_error ("Error reading `%s'", img->spec, Qnil);
9542 DGifCloseFile (gif);
9543 UNGCPRO;
9544 return 0;
9547 image = image_spec_value (img->spec, QCindex, NULL);
9548 ino = INTEGERP (image) ? XFASTINT (image) : 0;
9549 if (ino >= gif->ImageCount)
9551 image_error ("Invalid image number `%s' in image `%s'",
9552 image, img->spec);
9553 DGifCloseFile (gif);
9554 UNGCPRO;
9555 return 0;
9558 width = img->width = gif->SWidth;
9559 height = img->height = gif->SHeight;
9561 /* Create the X image and pixmap. */
9562 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9564 DGifCloseFile (gif);
9565 UNGCPRO;
9566 return 0;
9569 /* Allocate colors. */
9570 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
9571 if (!gif_color_map)
9572 gif_color_map = gif->SColorMap;
9573 init_color_table ();
9574 bzero (pixel_colors, sizeof pixel_colors);
9576 for (i = 0; i < gif_color_map->ColorCount; ++i)
9578 int r = gif_color_map->Colors[i].Red << 8;
9579 int g = gif_color_map->Colors[i].Green << 8;
9580 int b = gif_color_map->Colors[i].Blue << 8;
9581 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
9584 img->colors = colors_in_color_table (&img->ncolors);
9585 free_color_table ();
9587 /* Clear the part of the screen image that are not covered by
9588 the image from the GIF file. Full animated GIF support
9589 requires more than can be done here (see the gif89 spec,
9590 disposal methods). Let's simply assume that the part
9591 not covered by a sub-image is in the frame's background color. */
9592 image_top = gif->SavedImages[ino].ImageDesc.Top;
9593 image_left = gif->SavedImages[ino].ImageDesc.Left;
9594 image_width = gif->SavedImages[ino].ImageDesc.Width;
9595 image_height = gif->SavedImages[ino].ImageDesc.Height;
9597 for (y = 0; y < image_top; ++y)
9598 for (x = 0; x < width; ++x)
9599 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9601 for (y = image_top + image_height; y < height; ++y)
9602 for (x = 0; x < width; ++x)
9603 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9605 for (y = image_top; y < image_top + image_height; ++y)
9607 for (x = 0; x < image_left; ++x)
9608 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9609 for (x = image_left + image_width; x < width; ++x)
9610 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
9613 /* Read the GIF image into the X image. We use a local variable
9614 `raster' here because RasterBits below is a char *, and invites
9615 problems with bytes >= 0x80. */
9616 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
9618 if (gif->SavedImages[ino].ImageDesc.Interlace)
9620 static int interlace_start[] = {0, 4, 2, 1};
9621 static int interlace_increment[] = {8, 8, 4, 2};
9622 int pass, inc;
9623 int row = interlace_start[0];
9625 pass = 0;
9627 for (y = 0; y < image_height; y++)
9629 if (row >= image_height)
9631 row = interlace_start[++pass];
9632 while (row >= image_height)
9633 row = interlace_start[++pass];
9636 for (x = 0; x < image_width; x++)
9638 int i = raster[(y * image_width) + x];
9639 XPutPixel (ximg, x + image_left, row + image_top,
9640 pixel_colors[i]);
9643 row += interlace_increment[pass];
9646 else
9648 for (y = 0; y < image_height; ++y)
9649 for (x = 0; x < image_width; ++x)
9651 int i = raster[y * image_width + x];
9652 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
9656 DGifCloseFile (gif);
9658 /* Put the image into the pixmap, then free the X image and its buffer. */
9659 x_put_x_image (f, ximg, img->pixmap, width, height);
9660 x_destroy_x_image (ximg);
9662 UNGCPRO;
9663 return 1;
9666 #endif /* HAVE_GIF != 0 */
9670 /***********************************************************************
9671 Ghostscript
9672 ***********************************************************************/
9674 static int gs_image_p P_ ((Lisp_Object object));
9675 static int gs_load P_ ((struct frame *f, struct image *img));
9676 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9678 /* The symbol `postscript' identifying images of this type. */
9680 Lisp_Object Qpostscript;
9682 /* Keyword symbols. */
9684 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9686 /* Indices of image specification fields in gs_format, below. */
9688 enum gs_keyword_index
9690 GS_TYPE,
9691 GS_PT_WIDTH,
9692 GS_PT_HEIGHT,
9693 GS_FILE,
9694 GS_LOADER,
9695 GS_BOUNDING_BOX,
9696 GS_ASCENT,
9697 GS_MARGIN,
9698 GS_RELIEF,
9699 GS_ALGORITHM,
9700 GS_HEURISTIC_MASK,
9701 GS_MASK,
9702 GS_LAST
9705 /* Vector of image_keyword structures describing the format
9706 of valid user-defined image specifications. */
9708 static struct image_keyword gs_format[GS_LAST] =
9710 {":type", IMAGE_SYMBOL_VALUE, 1},
9711 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9712 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9713 {":file", IMAGE_STRING_VALUE, 1},
9714 {":loader", IMAGE_FUNCTION_VALUE, 0},
9715 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9716 {":ascent", IMAGE_ASCENT_VALUE, 0},
9717 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
9718 {":relief", IMAGE_INTEGER_VALUE, 0},
9719 {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9720 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9721 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
9724 /* Structure describing the image type `ghostscript'. */
9726 static struct image_type gs_type =
9728 &Qpostscript,
9729 gs_image_p,
9730 gs_load,
9731 gs_clear_image,
9732 NULL
9736 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9738 static void
9739 gs_clear_image (f, img)
9740 struct frame *f;
9741 struct image *img;
9743 /* IMG->data.ptr_val may contain a recorded colormap. */
9744 xfree (img->data.ptr_val);
9745 x_clear_image (f, img);
9749 /* Return non-zero if OBJECT is a valid Ghostscript image
9750 specification. */
9752 static int
9753 gs_image_p (object)
9754 Lisp_Object object;
9756 struct image_keyword fmt[GS_LAST];
9757 Lisp_Object tem;
9758 int i;
9760 bcopy (gs_format, fmt, sizeof fmt);
9762 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9763 return 0;
9765 /* Bounding box must be a list or vector containing 4 integers. */
9766 tem = fmt[GS_BOUNDING_BOX].value;
9767 if (CONSP (tem))
9769 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9770 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9771 return 0;
9772 if (!NILP (tem))
9773 return 0;
9775 else if (VECTORP (tem))
9777 if (XVECTOR (tem)->size != 4)
9778 return 0;
9779 for (i = 0; i < 4; ++i)
9780 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9781 return 0;
9783 else
9784 return 0;
9786 return 1;
9790 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9791 if successful. */
9793 static int
9794 gs_load (f, img)
9795 struct frame *f;
9796 struct image *img;
9798 char buffer[100];
9799 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9800 struct gcpro gcpro1, gcpro2;
9801 Lisp_Object frame;
9802 double in_width, in_height;
9803 Lisp_Object pixel_colors = Qnil;
9805 /* Compute pixel size of pixmap needed from the given size in the
9806 image specification. Sizes in the specification are in pt. 1 pt
9807 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9808 info. */
9809 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9810 in_width = XFASTINT (pt_width) / 72.0;
9811 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9812 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9813 in_height = XFASTINT (pt_height) / 72.0;
9814 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9816 /* Create the pixmap. */
9817 xassert (img->pixmap == None);
9818 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9819 img->width, img->height,
9820 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9822 if (!img->pixmap)
9824 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9825 return 0;
9828 /* Call the loader to fill the pixmap. It returns a process object
9829 if successful. We do not record_unwind_protect here because
9830 other places in redisplay like calling window scroll functions
9831 don't either. Let the Lisp loader use `unwind-protect' instead. */
9832 GCPRO2 (window_and_pixmap_id, pixel_colors);
9834 sprintf (buffer, "%lu %lu",
9835 (unsigned long) FRAME_X_WINDOW (f),
9836 (unsigned long) img->pixmap);
9837 window_and_pixmap_id = build_string (buffer);
9839 sprintf (buffer, "%lu %lu",
9840 FRAME_FOREGROUND_PIXEL (f),
9841 FRAME_BACKGROUND_PIXEL (f));
9842 pixel_colors = build_string (buffer);
9844 XSETFRAME (frame, f);
9845 loader = image_spec_value (img->spec, QCloader, NULL);
9846 if (NILP (loader))
9847 loader = intern ("gs-load-image");
9849 img->data.lisp_val = call6 (loader, frame, img->spec,
9850 make_number (img->width),
9851 make_number (img->height),
9852 window_and_pixmap_id,
9853 pixel_colors);
9854 UNGCPRO;
9855 return PROCESSP (img->data.lisp_val);
9859 /* Kill the Ghostscript process that was started to fill PIXMAP on
9860 frame F. Called from XTread_socket when receiving an event
9861 telling Emacs that Ghostscript has finished drawing. */
9863 void
9864 x_kill_gs_process (pixmap, f)
9865 Pixmap pixmap;
9866 struct frame *f;
9868 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9869 int class, i;
9870 struct image *img;
9872 /* Find the image containing PIXMAP. */
9873 for (i = 0; i < c->used; ++i)
9874 if (c->images[i]->pixmap == pixmap)
9875 break;
9877 /* Kill the GS process. We should have found PIXMAP in the image
9878 cache and its image should contain a process object. */
9879 xassert (i < c->used);
9880 img = c->images[i];
9881 xassert (PROCESSP (img->data.lisp_val));
9882 Fkill_process (img->data.lisp_val, Qnil);
9883 img->data.lisp_val = Qnil;
9885 /* On displays with a mutable colormap, figure out the colors
9886 allocated for the image by looking at the pixels of an XImage for
9887 img->pixmap. */
9888 class = FRAME_X_VISUAL (f)->class;
9889 if (class != StaticColor && class != StaticGray && class != TrueColor)
9891 XImage *ximg;
9893 BLOCK_INPUT;
9895 /* Try to get an XImage for img->pixmep. */
9896 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9897 0, 0, img->width, img->height, ~0, ZPixmap);
9898 if (ximg)
9900 int x, y;
9902 /* Initialize the color table. */
9903 init_color_table ();
9905 /* For each pixel of the image, look its color up in the
9906 color table. After having done so, the color table will
9907 contain an entry for each color used by the image. */
9908 for (y = 0; y < img->height; ++y)
9909 for (x = 0; x < img->width; ++x)
9911 unsigned long pixel = XGetPixel (ximg, x, y);
9912 lookup_pixel_color (f, pixel);
9915 /* Record colors in the image. Free color table and XImage. */
9916 img->colors = colors_in_color_table (&img->ncolors);
9917 free_color_table ();
9918 XDestroyImage (ximg);
9920 #if 0 /* This doesn't seem to be the case. If we free the colors
9921 here, we get a BadAccess later in x_clear_image when
9922 freeing the colors. */
9923 /* We have allocated colors once, but Ghostscript has also
9924 allocated colors on behalf of us. So, to get the
9925 reference counts right, free them once. */
9926 if (img->ncolors)
9927 x_free_colors (f, img->colors, img->ncolors);
9928 #endif
9930 else
9931 image_error ("Cannot get X image of `%s'; colors will not be freed",
9932 img->spec, Qnil);
9934 UNBLOCK_INPUT;
9940 /***********************************************************************
9941 Window properties
9942 ***********************************************************************/
9944 DEFUN ("x-change-window-property", Fx_change_window_property,
9945 Sx_change_window_property, 2, 3, 0,
9946 "Change window property PROP to VALUE on the X window of FRAME.\n\
9947 PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
9948 selected frame. Value is VALUE.")
9949 (prop, value, frame)
9950 Lisp_Object frame, prop, value;
9952 struct frame *f = check_x_frame (frame);
9953 Atom prop_atom;
9955 CHECK_STRING (prop, 1);
9956 CHECK_STRING (value, 2);
9958 BLOCK_INPUT;
9959 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9960 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9961 prop_atom, XA_STRING, 8, PropModeReplace,
9962 XSTRING (value)->data, XSTRING (value)->size);
9964 /* Make sure the property is set when we return. */
9965 XFlush (FRAME_X_DISPLAY (f));
9966 UNBLOCK_INPUT;
9968 return value;
9972 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9973 Sx_delete_window_property, 1, 2, 0,
9974 "Remove window property PROP from X window of FRAME.\n\
9975 FRAME nil or omitted means use the selected frame. Value is PROP.")
9976 (prop, frame)
9977 Lisp_Object prop, frame;
9979 struct frame *f = check_x_frame (frame);
9980 Atom prop_atom;
9982 CHECK_STRING (prop, 1);
9983 BLOCK_INPUT;
9984 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
9985 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
9987 /* Make sure the property is removed when we return. */
9988 XFlush (FRAME_X_DISPLAY (f));
9989 UNBLOCK_INPUT;
9991 return prop;
9995 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9996 1, 2, 0,
9997 "Value is the value of window property PROP on FRAME.\n\
9998 If FRAME is nil or omitted, use the selected frame. Value is nil\n\
9999 if FRAME hasn't a property with name PROP or if PROP has no string\n\
10000 value.")
10001 (prop, frame)
10002 Lisp_Object prop, frame;
10004 struct frame *f = check_x_frame (frame);
10005 Atom prop_atom;
10006 int rc;
10007 Lisp_Object prop_value = Qnil;
10008 char *tmp_data = NULL;
10009 Atom actual_type;
10010 int actual_format;
10011 unsigned long actual_size, bytes_remaining;
10013 CHECK_STRING (prop, 1);
10014 BLOCK_INPUT;
10015 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
10016 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10017 prop_atom, 0, 0, False, XA_STRING,
10018 &actual_type, &actual_format, &actual_size,
10019 &bytes_remaining, (unsigned char **) &tmp_data);
10020 if (rc == Success)
10022 int size = bytes_remaining;
10024 XFree (tmp_data);
10025 tmp_data = NULL;
10027 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10028 prop_atom, 0, bytes_remaining,
10029 False, XA_STRING,
10030 &actual_type, &actual_format,
10031 &actual_size, &bytes_remaining,
10032 (unsigned char **) &tmp_data);
10033 if (rc == Success)
10034 prop_value = make_string (tmp_data, size);
10036 XFree (tmp_data);
10039 UNBLOCK_INPUT;
10040 return prop_value;
10045 /***********************************************************************
10046 Busy cursor
10047 ***********************************************************************/
10049 /* If non-null, an asynchronous timer that, when it expires, displays
10050 a busy cursor on all frames. */
10052 static struct atimer *busy_cursor_atimer;
10054 /* Non-zero means a busy cursor is currently shown. */
10056 static int busy_cursor_shown_p;
10058 /* Number of seconds to wait before displaying a busy cursor. */
10060 static Lisp_Object Vbusy_cursor_delay;
10062 /* Default number of seconds to wait before displaying a busy
10063 cursor. */
10065 #define DEFAULT_BUSY_CURSOR_DELAY 1
10067 /* Function prototypes. */
10069 static void show_busy_cursor P_ ((struct atimer *));
10070 static void hide_busy_cursor P_ ((void));
10073 /* Cancel a currently active busy-cursor timer, and start a new one. */
10075 void
10076 start_busy_cursor ()
10078 EMACS_TIME delay;
10079 int secs, usecs = 0;
10081 cancel_busy_cursor ();
10083 if (INTEGERP (Vbusy_cursor_delay)
10084 && XINT (Vbusy_cursor_delay) > 0)
10085 secs = XFASTINT (Vbusy_cursor_delay);
10086 else if (FLOATP (Vbusy_cursor_delay)
10087 && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
10089 Lisp_Object tem;
10090 tem = Ftruncate (Vbusy_cursor_delay, Qnil);
10091 secs = XFASTINT (tem);
10092 usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
10094 else
10095 secs = DEFAULT_BUSY_CURSOR_DELAY;
10097 EMACS_SET_SECS_USECS (delay, secs, usecs);
10098 busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
10099 show_busy_cursor, NULL);
10103 /* Cancel the busy cursor timer if active, hide a busy cursor if
10104 shown. */
10106 void
10107 cancel_busy_cursor ()
10109 if (busy_cursor_atimer)
10111 cancel_atimer (busy_cursor_atimer);
10112 busy_cursor_atimer = NULL;
10115 if (busy_cursor_shown_p)
10116 hide_busy_cursor ();
10120 /* Timer function of busy_cursor_atimer. TIMER is equal to
10121 busy_cursor_atimer.
10123 Display a busy cursor on all frames by mapping the frames'
10124 busy_window. Set the busy_p flag in the frames' output_data.x
10125 structure to indicate that a busy cursor is shown on the
10126 frames. */
10128 static void
10129 show_busy_cursor (timer)
10130 struct atimer *timer;
10132 /* The timer implementation will cancel this timer automatically
10133 after this function has run. Set busy_cursor_atimer to null
10134 so that we know the timer doesn't have to be canceled. */
10135 busy_cursor_atimer = NULL;
10137 if (!busy_cursor_shown_p)
10139 Lisp_Object rest, frame;
10141 BLOCK_INPUT;
10143 FOR_EACH_FRAME (rest, frame)
10144 if (FRAME_X_P (XFRAME (frame)))
10146 struct frame *f = XFRAME (frame);
10148 f->output_data.x->busy_p = 1;
10150 if (!f->output_data.x->busy_window)
10152 unsigned long mask = CWCursor;
10153 XSetWindowAttributes attrs;
10155 attrs.cursor = f->output_data.x->busy_cursor;
10157 f->output_data.x->busy_window
10158 = XCreateWindow (FRAME_X_DISPLAY (f),
10159 FRAME_OUTER_WINDOW (f),
10160 0, 0, 32000, 32000, 0, 0,
10161 InputOnly,
10162 CopyFromParent,
10163 mask, &attrs);
10166 XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10167 XFlush (FRAME_X_DISPLAY (f));
10170 busy_cursor_shown_p = 1;
10171 UNBLOCK_INPUT;
10176 /* Hide the busy cursor on all frames, if it is currently shown. */
10178 static void
10179 hide_busy_cursor ()
10181 if (busy_cursor_shown_p)
10183 Lisp_Object rest, frame;
10185 BLOCK_INPUT;
10186 FOR_EACH_FRAME (rest, frame)
10188 struct frame *f = XFRAME (frame);
10190 if (FRAME_X_P (f)
10191 /* Watch out for newly created frames. */
10192 && f->output_data.x->busy_window)
10194 XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
10195 /* Sync here because XTread_socket looks at the busy_p flag
10196 that is reset to zero below. */
10197 XSync (FRAME_X_DISPLAY (f), False);
10198 f->output_data.x->busy_p = 0;
10202 busy_cursor_shown_p = 0;
10203 UNBLOCK_INPUT;
10209 /***********************************************************************
10210 Tool tips
10211 ***********************************************************************/
10213 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
10214 Lisp_Object));
10216 /* The frame of a currently visible tooltip, or null. */
10218 struct frame *tip_frame;
10220 /* If non-nil, a timer started that hides the last tooltip when it
10221 fires. */
10223 Lisp_Object tip_timer;
10224 Window tip_window;
10226 /* Create a frame for a tooltip on the display described by DPYINFO.
10227 PARMS is a list of frame parameters. Value is the frame. */
10229 static Lisp_Object
10230 x_create_tip_frame (dpyinfo, parms)
10231 struct x_display_info *dpyinfo;
10232 Lisp_Object parms;
10234 struct frame *f;
10235 Lisp_Object frame, tem;
10236 Lisp_Object name;
10237 long window_prompting = 0;
10238 int width, height;
10239 int count = specpdl_ptr - specpdl;
10240 struct gcpro gcpro1, gcpro2, gcpro3;
10241 struct kboard *kb;
10243 check_x ();
10245 /* Use this general default value to start with until we know if
10246 this frame has a specified name. */
10247 Vx_resource_name = Vinvocation_name;
10249 #ifdef MULTI_KBOARD
10250 kb = dpyinfo->kboard;
10251 #else
10252 kb = &the_only_kboard;
10253 #endif
10255 /* Get the name of the frame to use for resource lookup. */
10256 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
10257 if (!STRINGP (name)
10258 && !EQ (name, Qunbound)
10259 && !NILP (name))
10260 error ("Invalid frame name--not a string or nil");
10261 Vx_resource_name = name;
10263 frame = Qnil;
10264 GCPRO3 (parms, name, frame);
10265 tip_frame = f = make_frame (1);
10266 XSETFRAME (frame, f);
10267 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
10269 f->output_method = output_x_window;
10270 f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
10271 bzero (f->output_data.x, sizeof (struct x_output));
10272 f->output_data.x->icon_bitmap = -1;
10273 f->output_data.x->fontset = -1;
10274 f->output_data.x->scroll_bar_foreground_pixel = -1;
10275 f->output_data.x->scroll_bar_background_pixel = -1;
10276 f->icon_name = Qnil;
10277 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
10278 #ifdef MULTI_KBOARD
10279 FRAME_KBOARD (f) = kb;
10280 #endif
10281 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10282 f->output_data.x->explicit_parent = 0;
10284 /* These colors will be set anyway later, but it's important
10285 to get the color reference counts right, so initialize them! */
10287 Lisp_Object black;
10288 struct gcpro gcpro1;
10290 black = build_string ("black");
10291 GCPRO1 (black);
10292 f->output_data.x->foreground_pixel
10293 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10294 f->output_data.x->background_pixel
10295 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10296 f->output_data.x->cursor_pixel
10297 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10298 f->output_data.x->cursor_foreground_pixel
10299 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10300 f->output_data.x->border_pixel
10301 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10302 f->output_data.x->mouse_pixel
10303 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
10304 UNGCPRO;
10307 /* Set the name; the functions to which we pass f expect the name to
10308 be set. */
10309 if (EQ (name, Qunbound) || NILP (name))
10311 f->name = build_string (dpyinfo->x_id_name);
10312 f->explicit_name = 0;
10314 else
10316 f->name = name;
10317 f->explicit_name = 1;
10318 /* use the frame's title when getting resources for this frame. */
10319 specbind (Qx_resource_name, name);
10322 /* Extract the window parameters from the supplied values
10323 that are needed to determine window geometry. */
10325 Lisp_Object font;
10327 font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
10329 BLOCK_INPUT;
10330 /* First, try whatever font the caller has specified. */
10331 if (STRINGP (font))
10333 tem = Fquery_fontset (font, Qnil);
10334 if (STRINGP (tem))
10335 font = x_new_fontset (f, XSTRING (tem)->data);
10336 else
10337 font = x_new_font (f, XSTRING (font)->data);
10340 /* Try out a font which we hope has bold and italic variations. */
10341 if (!STRINGP (font))
10342 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
10343 if (!STRINGP (font))
10344 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10345 if (! STRINGP (font))
10346 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
10347 if (! STRINGP (font))
10348 /* This was formerly the first thing tried, but it finds too many fonts
10349 and takes too long. */
10350 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
10351 /* If those didn't work, look for something which will at least work. */
10352 if (! STRINGP (font))
10353 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
10354 UNBLOCK_INPUT;
10355 if (! STRINGP (font))
10356 font = build_string ("fixed");
10358 x_default_parameter (f, parms, Qfont, font,
10359 "font", "Font", RES_TYPE_STRING);
10362 x_default_parameter (f, parms, Qborder_width, make_number (2),
10363 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
10365 /* This defaults to 2 in order to match xterm. We recognize either
10366 internalBorderWidth or internalBorder (which is what xterm calls
10367 it). */
10368 if (NILP (Fassq (Qinternal_border_width, parms)))
10370 Lisp_Object value;
10372 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
10373 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
10374 if (! EQ (value, Qunbound))
10375 parms = Fcons (Fcons (Qinternal_border_width, value),
10376 parms);
10379 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
10380 "internalBorderWidth", "internalBorderWidth",
10381 RES_TYPE_NUMBER);
10383 /* Also do the stuff which must be set before the window exists. */
10384 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
10385 "foreground", "Foreground", RES_TYPE_STRING);
10386 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
10387 "background", "Background", RES_TYPE_STRING);
10388 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
10389 "pointerColor", "Foreground", RES_TYPE_STRING);
10390 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
10391 "cursorColor", "Foreground", RES_TYPE_STRING);
10392 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
10393 "borderColor", "BorderColor", RES_TYPE_STRING);
10395 /* Init faces before x_default_parameter is called for scroll-bar
10396 parameters because that function calls x_set_scroll_bar_width,
10397 which calls change_frame_size, which calls Fset_window_buffer,
10398 which runs hooks, which call Fvertical_motion. At the end, we
10399 end up in init_iterator with a null face cache, which should not
10400 happen. */
10401 init_frame_faces (f);
10403 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
10404 window_prompting = x_figure_window_size (f, parms);
10406 if (window_prompting & XNegative)
10408 if (window_prompting & YNegative)
10409 f->output_data.x->win_gravity = SouthEastGravity;
10410 else
10411 f->output_data.x->win_gravity = NorthEastGravity;
10413 else
10415 if (window_prompting & YNegative)
10416 f->output_data.x->win_gravity = SouthWestGravity;
10417 else
10418 f->output_data.x->win_gravity = NorthWestGravity;
10421 f->output_data.x->size_hint_flags = window_prompting;
10423 XSetWindowAttributes attrs;
10424 unsigned long mask;
10426 BLOCK_INPUT;
10427 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
10428 /* Window managers look at the override-redirect flag to determine
10429 whether or net to give windows a decoration (Xlib spec, chapter
10430 3.2.8). */
10431 attrs.override_redirect = True;
10432 attrs.save_under = True;
10433 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
10434 /* Arrange for getting MapNotify and UnmapNotify events. */
10435 attrs.event_mask = StructureNotifyMask;
10436 tip_window
10437 = FRAME_X_WINDOW (f)
10438 = XCreateWindow (FRAME_X_DISPLAY (f),
10439 FRAME_X_DISPLAY_INFO (f)->root_window,
10440 /* x, y, width, height */
10441 0, 0, 1, 1,
10442 /* Border. */
10444 CopyFromParent, InputOutput, CopyFromParent,
10445 mask, &attrs);
10446 UNBLOCK_INPUT;
10449 x_make_gc (f);
10451 x_default_parameter (f, parms, Qauto_raise, Qnil,
10452 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10453 x_default_parameter (f, parms, Qauto_lower, Qnil,
10454 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
10455 x_default_parameter (f, parms, Qcursor_type, Qbox,
10456 "cursorType", "CursorType", RES_TYPE_SYMBOL);
10458 /* Dimensions, especially f->height, must be done via change_frame_size.
10459 Change will not be effected unless different from the current
10460 f->height. */
10461 width = f->width;
10462 height = f->height;
10463 f->height = 0;
10464 SET_FRAME_WIDTH (f, 0);
10465 change_frame_size (f, height, width, 1, 0, 0);
10467 f->no_split = 1;
10469 UNGCPRO;
10471 /* It is now ok to make the frame official even if we get an error
10472 below. And the frame needs to be on Vframe_list or making it
10473 visible won't work. */
10474 Vframe_list = Fcons (frame, Vframe_list);
10476 /* Now that the frame is official, it counts as a reference to
10477 its display. */
10478 FRAME_X_DISPLAY_INFO (f)->reference_count++;
10480 return unbind_to (count, frame);
10484 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
10485 "Show STRING in a \"tooltip\" window on frame FRAME.\n\
10486 A tooltip window is a small X window displaying a string.\n\
10488 FRAME nil or omitted means use the selected frame.\n\
10490 PARMS is an optional list of frame parameters which can be\n\
10491 used to change the tooltip's appearance.\n\
10493 Automatically hide the tooltip after TIMEOUT seconds.\n\
10494 TIMEOUT nil means use the default timeout of 5 seconds.\n\
10496 If the list of frame parameters PARAMS contains a `left' parameters,\n\
10497 the tooltip is displayed at that x-position. Otherwise it is\n\
10498 displayed at the mouse position, with offset DX added (default is 5 if\n\
10499 DX isn't specified). Likewise for the y-position; if a `top' frame\n\
10500 parameter is specified, it determines the y-position of the tooltip\n\
10501 window, otherwise it is displayed at the mouse position, with offset\n\
10502 DY added (default is -5).")
10503 (string, frame, parms, timeout, dx, dy)
10504 Lisp_Object string, frame, parms, timeout, dx, dy;
10506 struct frame *f;
10507 struct window *w;
10508 Window root, child;
10509 Lisp_Object buffer, top, left;
10510 struct buffer *old_buffer;
10511 struct text_pos pos;
10512 int i, width, height;
10513 int root_x, root_y, win_x, win_y;
10514 unsigned pmask;
10515 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10516 int old_windows_or_buffers_changed = windows_or_buffers_changed;
10517 int count = specpdl_ptr - specpdl;
10519 specbind (Qinhibit_redisplay, Qt);
10521 GCPRO4 (string, parms, frame, timeout);
10523 CHECK_STRING (string, 0);
10524 f = check_x_frame (frame);
10525 if (NILP (timeout))
10526 timeout = make_number (5);
10527 else
10528 CHECK_NATNUM (timeout, 2);
10530 if (NILP (dx))
10531 dx = make_number (5);
10532 else
10533 CHECK_NUMBER (dx, 5);
10535 if (NILP (dy))
10536 dy = make_number (-5);
10537 else
10538 CHECK_NUMBER (dy, 6);
10540 /* Hide a previous tip, if any. */
10541 Fx_hide_tip ();
10543 /* Add default values to frame parameters. */
10544 if (NILP (Fassq (Qname, parms)))
10545 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
10546 if (NILP (Fassq (Qinternal_border_width, parms)))
10547 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
10548 if (NILP (Fassq (Qborder_width, parms)))
10549 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
10550 if (NILP (Fassq (Qborder_color, parms)))
10551 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
10552 if (NILP (Fassq (Qbackground_color, parms)))
10553 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
10554 parms);
10556 /* Create a frame for the tooltip, and record it in the global
10557 variable tip_frame. */
10558 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
10559 tip_frame = f = XFRAME (frame);
10561 /* Set up the frame's root window. Currently we use a size of 80
10562 columns x 40 lines. If someone wants to show a larger tip, he
10563 will loose. I don't think this is a realistic case. */
10564 w = XWINDOW (FRAME_ROOT_WINDOW (f));
10565 w->left = w->top = make_number (0);
10566 w->width = make_number (80);
10567 w->height = make_number (40);
10568 adjust_glyphs (f);
10569 w->pseudo_window_p = 1;
10571 /* Display the tooltip text in a temporary buffer. */
10572 buffer = Fget_buffer_create (build_string (" *tip*"));
10573 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
10574 old_buffer = current_buffer;
10575 set_buffer_internal_1 (XBUFFER (buffer));
10576 Ferase_buffer ();
10577 Finsert (1, &string);
10578 clear_glyph_matrix (w->desired_matrix);
10579 clear_glyph_matrix (w->current_matrix);
10580 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
10581 try_window (FRAME_ROOT_WINDOW (f), pos);
10583 /* Compute width and height of the tooltip. */
10584 width = height = 0;
10585 for (i = 0; i < w->desired_matrix->nrows; ++i)
10587 struct glyph_row *row = &w->desired_matrix->rows[i];
10588 struct glyph *last;
10589 int row_width;
10591 /* Stop at the first empty row at the end. */
10592 if (!row->enabled_p || !row->displays_text_p)
10593 break;
10595 /* Let the row go over the full width of the frame. */
10596 row->full_width_p = 1;
10598 /* There's a glyph at the end of rows that is used to place
10599 the cursor there. Don't include the width of this glyph. */
10600 if (row->used[TEXT_AREA])
10602 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
10603 row_width = row->pixel_width - last->pixel_width;
10605 else
10606 row_width = row->pixel_width;
10608 height += row->height;
10609 width = max (width, row_width);
10612 /* Add the frame's internal border to the width and height the X
10613 window should have. */
10614 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10615 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
10617 /* User-specified position? */
10618 left = Fcdr (Fassq (Qleft, parms));
10619 top = Fcdr (Fassq (Qtop, parms));
10621 /* Move the tooltip window where the mouse pointer is. Resize and
10622 show it. */
10623 BLOCK_INPUT;
10624 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
10625 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
10626 UNBLOCK_INPUT;
10628 root_x += XINT (dx);
10629 root_y += XINT (dy);
10631 if (INTEGERP (left))
10632 root_x = XINT (left);
10633 if (INTEGERP (top))
10634 root_y = XINT (top);
10636 BLOCK_INPUT;
10637 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10638 root_x, root_y - height, width, height);
10639 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10640 UNBLOCK_INPUT;
10642 /* Draw into the window. */
10643 w->must_be_updated_p = 1;
10644 update_single_window (w, 1);
10646 /* Restore original current buffer. */
10647 set_buffer_internal_1 (old_buffer);
10648 windows_or_buffers_changed = old_windows_or_buffers_changed;
10650 /* Let the tip disappear after timeout seconds. */
10651 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
10652 intern ("x-hide-tip"));
10654 UNGCPRO;
10655 return unbind_to (count, Qnil);
10659 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
10660 "Hide the current tooltip window, if there is any.\n\
10661 Value is t is tooltip was open, nil otherwise.")
10664 int count = specpdl_ptr - specpdl;
10665 int deleted_p = 0;
10667 specbind (Qinhibit_redisplay, Qt);
10669 if (!NILP (tip_timer))
10671 call1 (intern ("cancel-timer"), tip_timer);
10672 tip_timer = Qnil;
10675 if (tip_frame)
10677 Lisp_Object frame;
10679 XSETFRAME (frame, tip_frame);
10680 Fdelete_frame (frame, Qt);
10681 tip_frame = NULL;
10682 deleted_p = 1;
10685 return unbind_to (count, deleted_p ? Qt : Qnil);
10690 /***********************************************************************
10691 File selection dialog
10692 ***********************************************************************/
10694 #ifdef USE_MOTIF
10696 /* Callback for "OK" and "Cancel" on file selection dialog. */
10698 static void
10699 file_dialog_cb (widget, client_data, call_data)
10700 Widget widget;
10701 XtPointer call_data, client_data;
10703 int *result = (int *) client_data;
10704 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
10705 *result = cb->reason;
10709 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
10710 "Read file name, prompting with PROMPT in directory DIR.\n\
10711 Use a file selection dialog.\n\
10712 Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
10713 specified. Don't let the user enter a file name in the file\n\
10714 selection dialog's entry field, if MUSTMATCH is non-nil.")
10715 (prompt, dir, default_filename, mustmatch)
10716 Lisp_Object prompt, dir, default_filename, mustmatch;
10718 int result;
10719 struct frame *f = SELECTED_FRAME ();
10720 Lisp_Object file = Qnil;
10721 Widget dialog, text, list, help;
10722 Arg al[10];
10723 int ac = 0;
10724 extern XtAppContext Xt_app_con;
10725 char *title;
10726 XmString dir_xmstring, pattern_xmstring;
10727 int popup_activated_flag;
10728 int count = specpdl_ptr - specpdl;
10729 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
10731 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
10732 CHECK_STRING (prompt, 0);
10733 CHECK_STRING (dir, 1);
10735 /* Prevent redisplay. */
10736 specbind (Qinhibit_redisplay, Qt);
10738 BLOCK_INPUT;
10740 /* Create the dialog with PROMPT as title, using DIR as initial
10741 directory and using "*" as pattern. */
10742 dir = Fexpand_file_name (dir, Qnil);
10743 dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data);
10744 pattern_xmstring = XmStringCreateLocalized ("*");
10746 XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
10747 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
10748 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
10749 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
10750 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
10751 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
10752 "fsb", al, ac);
10753 XmStringFree (dir_xmstring);
10754 XmStringFree (pattern_xmstring);
10756 /* Add callbacks for OK and Cancel. */
10757 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
10758 (XtPointer) &result);
10759 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
10760 (XtPointer) &result);
10762 /* Disable the help button since we can't display help. */
10763 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
10764 XtSetSensitive (help, False);
10766 /* Mark OK button as default. */
10767 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
10768 XmNshowAsDefault, True, NULL);
10770 /* If MUSTMATCH is non-nil, disable the file entry field of the
10771 dialog, so that the user must select a file from the files list
10772 box. We can't remove it because we wouldn't have a way to get at
10773 the result file name, then. */
10774 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
10775 if (!NILP (mustmatch))
10777 Widget label;
10778 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
10779 XtSetSensitive (text, False);
10780 XtSetSensitive (label, False);
10783 /* Manage the dialog, so that list boxes get filled. */
10784 XtManageChild (dialog);
10786 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
10787 must include the path for this to work. */
10788 list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
10789 if (STRINGP (default_filename))
10791 XmString default_xmstring;
10792 int item_pos;
10794 default_xmstring
10795 = XmStringCreateLocalized (XSTRING (default_filename)->data);
10797 if (!XmListItemExists (list, default_xmstring))
10799 /* Add a new item if DEFAULT_FILENAME is not in the list. */
10800 XmListAddItem (list, default_xmstring, 0);
10801 item_pos = 0;
10803 else
10804 item_pos = XmListItemPos (list, default_xmstring);
10805 XmStringFree (default_xmstring);
10807 /* Select the item and scroll it into view. */
10808 XmListSelectPos (list, item_pos, True);
10809 XmListSetPos (list, item_pos);
10812 #ifdef HAVE_MOTIF_2_1
10814 /* Process events until the user presses Cancel or OK. */
10815 result = 0;
10816 while (result == 0 || XtAppPending (Xt_app_con))
10817 XtAppProcessEvent (Xt_app_con, XtIMAll);
10819 #else /* not HAVE_MOTIF_2_1 */
10821 /* Process all events until the user presses Cancel or OK. */
10822 for (result = 0; result == 0;)
10824 XEvent event;
10825 Widget widget, parent;
10827 XtAppNextEvent (Xt_app_con, &event);
10829 /* See if the receiver of the event is one of the widgets of
10830 the file selection dialog. If so, dispatch it. If not,
10831 discard it. */
10832 widget = XtWindowToWidget (event.xany.display, event.xany.window);
10833 parent = widget;
10834 while (parent && parent != dialog)
10835 parent = XtParent (parent);
10837 if (parent == dialog
10838 || (event.type == Expose
10839 && !process_expose_from_menu (event)))
10840 XtDispatchEvent (&event);
10843 #endif /* not HAVE_MOTIF_2_1 */
10845 /* Get the result. */
10846 if (result == XmCR_OK)
10848 XmString text;
10849 String data;
10851 XtVaGetValues (dialog, XmNtextString, &text, NULL);
10852 XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
10853 XmStringFree (text);
10854 file = build_string (data);
10855 XtFree (data);
10857 else
10858 file = Qnil;
10860 /* Clean up. */
10861 XtUnmanageChild (dialog);
10862 XtDestroyWidget (dialog);
10863 UNBLOCK_INPUT;
10864 UNGCPRO;
10866 /* Make "Cancel" equivalent to C-g. */
10867 if (NILP (file))
10868 Fsignal (Qquit, Qnil);
10870 return unbind_to (count, file);
10873 #endif /* USE_MOTIF */
10877 /***********************************************************************
10878 Initialization
10879 ***********************************************************************/
10881 void
10882 syms_of_xfns ()
10884 /* This is zero if not using X windows. */
10885 x_in_use = 0;
10887 /* The section below is built by the lisp expression at the top of the file,
10888 just above where these variables are declared. */
10889 /*&&& init symbols here &&&*/
10890 Qauto_raise = intern ("auto-raise");
10891 staticpro (&Qauto_raise);
10892 Qauto_lower = intern ("auto-lower");
10893 staticpro (&Qauto_lower);
10894 Qbar = intern ("bar");
10895 staticpro (&Qbar);
10896 Qborder_color = intern ("border-color");
10897 staticpro (&Qborder_color);
10898 Qborder_width = intern ("border-width");
10899 staticpro (&Qborder_width);
10900 Qbox = intern ("box");
10901 staticpro (&Qbox);
10902 Qcursor_color = intern ("cursor-color");
10903 staticpro (&Qcursor_color);
10904 Qcursor_type = intern ("cursor-type");
10905 staticpro (&Qcursor_type);
10906 Qgeometry = intern ("geometry");
10907 staticpro (&Qgeometry);
10908 Qicon_left = intern ("icon-left");
10909 staticpro (&Qicon_left);
10910 Qicon_top = intern ("icon-top");
10911 staticpro (&Qicon_top);
10912 Qicon_type = intern ("icon-type");
10913 staticpro (&Qicon_type);
10914 Qicon_name = intern ("icon-name");
10915 staticpro (&Qicon_name);
10916 Qinternal_border_width = intern ("internal-border-width");
10917 staticpro (&Qinternal_border_width);
10918 Qleft = intern ("left");
10919 staticpro (&Qleft);
10920 Qright = intern ("right");
10921 staticpro (&Qright);
10922 Qmouse_color = intern ("mouse-color");
10923 staticpro (&Qmouse_color);
10924 Qnone = intern ("none");
10925 staticpro (&Qnone);
10926 Qparent_id = intern ("parent-id");
10927 staticpro (&Qparent_id);
10928 Qscroll_bar_width = intern ("scroll-bar-width");
10929 staticpro (&Qscroll_bar_width);
10930 Qsuppress_icon = intern ("suppress-icon");
10931 staticpro (&Qsuppress_icon);
10932 Qundefined_color = intern ("undefined-color");
10933 staticpro (&Qundefined_color);
10934 Qvertical_scroll_bars = intern ("vertical-scroll-bars");
10935 staticpro (&Qvertical_scroll_bars);
10936 Qvisibility = intern ("visibility");
10937 staticpro (&Qvisibility);
10938 Qwindow_id = intern ("window-id");
10939 staticpro (&Qwindow_id);
10940 Qouter_window_id = intern ("outer-window-id");
10941 staticpro (&Qouter_window_id);
10942 Qx_frame_parameter = intern ("x-frame-parameter");
10943 staticpro (&Qx_frame_parameter);
10944 Qx_resource_name = intern ("x-resource-name");
10945 staticpro (&Qx_resource_name);
10946 Quser_position = intern ("user-position");
10947 staticpro (&Quser_position);
10948 Quser_size = intern ("user-size");
10949 staticpro (&Quser_size);
10950 Qscroll_bar_foreground = intern ("scroll-bar-foreground");
10951 staticpro (&Qscroll_bar_foreground);
10952 Qscroll_bar_background = intern ("scroll-bar-background");
10953 staticpro (&Qscroll_bar_background);
10954 Qscreen_gamma = intern ("screen-gamma");
10955 staticpro (&Qscreen_gamma);
10956 Qline_spacing = intern ("line-spacing");
10957 staticpro (&Qline_spacing);
10958 Qcenter = intern ("center");
10959 staticpro (&Qcenter);
10960 Qcompound_text = intern ("compound-text");
10961 staticpro (&Qcompound_text);
10962 /* This is the end of symbol initialization. */
10964 /* Text property `display' should be nonsticky by default. */
10965 Vtext_property_default_nonsticky
10966 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10969 Qlaplace = intern ("laplace");
10970 staticpro (&Qlaplace);
10971 Qemboss = intern ("emboss");
10972 staticpro (&Qemboss);
10973 Qedge_detection = intern ("edge-detection");
10974 staticpro (&Qedge_detection);
10975 Qheuristic = intern ("heuristic");
10976 staticpro (&Qheuristic);
10977 QCmatrix = intern (":matrix");
10978 staticpro (&QCmatrix);
10979 QCcolor_adjustment = intern (":color-adjustment");
10980 staticpro (&QCcolor_adjustment);
10981 QCmask = intern (":mask");
10982 staticpro (&QCmask);
10984 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10985 staticpro (&Qface_set_after_frame_default);
10987 Fput (Qundefined_color, Qerror_conditions,
10988 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10989 Fput (Qundefined_color, Qerror_message,
10990 build_string ("Undefined color"));
10992 init_x_parm_symbols ();
10994 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10995 "Non-nil means always draw a cross over disabled images.\n\
10996 Disabled images are those having an `:algorithm disabled' property.\n\
10997 A cross is always drawn on black & white displays.");
10998 cross_disabled_images = 0;
11000 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
11001 "List of directories to search for bitmap files for X.");
11002 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
11004 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
11005 "The shape of the pointer when over text.\n\
11006 Changing the value does not affect existing frames\n\
11007 unless you set the mouse color.");
11008 Vx_pointer_shape = Qnil;
11010 DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
11011 "The name Emacs uses to look up X resources.\n\
11012 `x-get-resource' uses this as the first component of the instance name\n\
11013 when requesting resource values.\n\
11014 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
11015 was invoked, or to the value specified with the `-name' or `-rn'\n\
11016 switches, if present.\n\
11018 It may be useful to bind this variable locally around a call\n\
11019 to `x-get-resource'. See also the variable `x-resource-class'.");
11020 Vx_resource_name = Qnil;
11022 DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
11023 "The class Emacs uses to look up X resources.\n\
11024 `x-get-resource' uses this as the first component of the instance class\n\
11025 when requesting resource values.\n\
11026 Emacs initially sets `x-resource-class' to \"Emacs\".\n\
11028 Setting this variable permanently is not a reasonable thing to do,\n\
11029 but binding this variable locally around a call to `x-get-resource'\n\
11030 is a reasonable practice. See also the variable `x-resource-name'.");
11031 Vx_resource_class = build_string (EMACS_CLASS);
11033 #if 0 /* This doesn't really do anything. */
11034 DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
11035 "The shape of the pointer when not over text.\n\
11036 This variable takes effect when you create a new frame\n\
11037 or when you set the mouse color.");
11038 #endif
11039 Vx_nontext_pointer_shape = Qnil;
11041 DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
11042 "The shape of the pointer when Emacs is busy.\n\
11043 This variable takes effect when you create a new frame\n\
11044 or when you set the mouse color.");
11045 Vx_busy_pointer_shape = Qnil;
11047 DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
11048 "Non-zero means Emacs displays a busy cursor on window systems.");
11049 display_busy_cursor_p = 1;
11051 DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
11052 "*Seconds to wait before displaying a busy-cursor.\n\
11053 Value must be an integer or float.");
11054 Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
11056 #if 0 /* This doesn't really do anything. */
11057 DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
11058 "The shape of the pointer when over the mode line.\n\
11059 This variable takes effect when you create a new frame\n\
11060 or when you set the mouse color.");
11061 #endif
11062 Vx_mode_pointer_shape = Qnil;
11064 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
11065 &Vx_sensitive_text_pointer_shape,
11066 "The shape of the pointer when over mouse-sensitive text.\n\
11067 This variable takes effect when you create a new frame\n\
11068 or when you set the mouse color.");
11069 Vx_sensitive_text_pointer_shape = Qnil;
11071 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
11072 "A string indicating the foreground color of the cursor box.");
11073 Vx_cursor_fore_pixel = Qnil;
11075 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
11076 "Non-nil if no X window manager is in use.\n\
11077 Emacs doesn't try to figure this out; this is always nil\n\
11078 unless you set it to something else.");
11079 /* We don't have any way to find this out, so set it to nil
11080 and maybe the user would like to set it to t. */
11081 Vx_no_window_manager = Qnil;
11083 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
11084 &Vx_pixel_size_width_font_regexp,
11085 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
11087 Since Emacs gets width of a font matching with this regexp from\n\
11088 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
11089 such a font. This is especially effective for such large fonts as\n\
11090 Chinese, Japanese, and Korean.");
11091 Vx_pixel_size_width_font_regexp = Qnil;
11093 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
11094 "Time after which cached images are removed from the cache.\n\
11095 When an image has not been displayed this many seconds, remove it\n\
11096 from the image cache. Value must be an integer or nil with nil\n\
11097 meaning don't clear the cache.");
11098 Vimage_cache_eviction_delay = make_number (30 * 60);
11100 #ifdef USE_X_TOOLKIT
11101 Fprovide (intern ("x-toolkit"));
11102 #endif
11103 #ifdef USE_MOTIF
11104 Fprovide (intern ("motif"));
11105 #endif
11107 defsubr (&Sx_get_resource);
11109 /* X window properties. */
11110 defsubr (&Sx_change_window_property);
11111 defsubr (&Sx_delete_window_property);
11112 defsubr (&Sx_window_property);
11114 defsubr (&Sxw_display_color_p);
11115 defsubr (&Sx_display_grayscale_p);
11116 defsubr (&Sxw_color_defined_p);
11117 defsubr (&Sxw_color_values);
11118 defsubr (&Sx_server_max_request_size);
11119 defsubr (&Sx_server_vendor);
11120 defsubr (&Sx_server_version);
11121 defsubr (&Sx_display_pixel_width);
11122 defsubr (&Sx_display_pixel_height);
11123 defsubr (&Sx_display_mm_width);
11124 defsubr (&Sx_display_mm_height);
11125 defsubr (&Sx_display_screens);
11126 defsubr (&Sx_display_planes);
11127 defsubr (&Sx_display_color_cells);
11128 defsubr (&Sx_display_visual_class);
11129 defsubr (&Sx_display_backing_store);
11130 defsubr (&Sx_display_save_under);
11131 defsubr (&Sx_parse_geometry);
11132 defsubr (&Sx_create_frame);
11133 defsubr (&Sx_open_connection);
11134 defsubr (&Sx_close_connection);
11135 defsubr (&Sx_display_list);
11136 defsubr (&Sx_synchronize);
11137 defsubr (&Sx_focus_frame);
11139 /* Setting callback functions for fontset handler. */
11140 get_font_info_func = x_get_font_info;
11142 #if 0 /* This function pointer doesn't seem to be used anywhere.
11143 And the pointer assigned has the wrong type, anyway. */
11144 list_fonts_func = x_list_fonts;
11145 #endif
11147 load_font_func = x_load_font;
11148 find_ccl_program_func = x_find_ccl_program;
11149 query_font_func = x_query_font;
11150 set_frame_fontset_func = x_set_font;
11151 check_window_system_func = check_x;
11153 /* Images. */
11154 Qxbm = intern ("xbm");
11155 staticpro (&Qxbm);
11156 QCtype = intern (":type");
11157 staticpro (&QCtype);
11158 QCalgorithm = intern (":algorithm");
11159 staticpro (&QCalgorithm);
11160 QCheuristic_mask = intern (":heuristic-mask");
11161 staticpro (&QCheuristic_mask);
11162 QCcolor_symbols = intern (":color-symbols");
11163 staticpro (&QCcolor_symbols);
11164 QCascent = intern (":ascent");
11165 staticpro (&QCascent);
11166 QCmargin = intern (":margin");
11167 staticpro (&QCmargin);
11168 QCrelief = intern (":relief");
11169 staticpro (&QCrelief);
11170 Qpostscript = intern ("postscript");
11171 staticpro (&Qpostscript);
11172 QCloader = intern (":loader");
11173 staticpro (&QCloader);
11174 QCbounding_box = intern (":bounding-box");
11175 staticpro (&QCbounding_box);
11176 QCpt_width = intern (":pt-width");
11177 staticpro (&QCpt_width);
11178 QCpt_height = intern (":pt-height");
11179 staticpro (&QCpt_height);
11180 QCindex = intern (":index");
11181 staticpro (&QCindex);
11182 Qpbm = intern ("pbm");
11183 staticpro (&Qpbm);
11185 #if HAVE_XPM
11186 Qxpm = intern ("xpm");
11187 staticpro (&Qxpm);
11188 #endif
11190 #if HAVE_JPEG
11191 Qjpeg = intern ("jpeg");
11192 staticpro (&Qjpeg);
11193 #endif
11195 #if HAVE_TIFF
11196 Qtiff = intern ("tiff");
11197 staticpro (&Qtiff);
11198 #endif
11200 #if HAVE_GIF
11201 Qgif = intern ("gif");
11202 staticpro (&Qgif);
11203 #endif
11205 #if HAVE_PNG
11206 Qpng = intern ("png");
11207 staticpro (&Qpng);
11208 #endif
11210 defsubr (&Sclear_image_cache);
11211 defsubr (&Simage_size);
11212 defsubr (&Simage_mask_p);
11214 busy_cursor_atimer = NULL;
11215 busy_cursor_shown_p = 0;
11217 defsubr (&Sx_show_tip);
11218 defsubr (&Sx_hide_tip);
11219 staticpro (&tip_timer);
11220 tip_timer = Qnil;
11222 #ifdef USE_MOTIF
11223 defsubr (&Sx_file_dialog);
11224 #endif
11228 void
11229 init_xfns ()
11231 image_types = NULL;
11232 Vimage_types = Qnil;
11234 define_image_type (&xbm_type);
11235 define_image_type (&gs_type);
11236 define_image_type (&pbm_type);
11238 #if HAVE_XPM
11239 define_image_type (&xpm_type);
11240 #endif
11242 #if HAVE_JPEG
11243 define_image_type (&jpeg_type);
11244 #endif
11246 #if HAVE_TIFF
11247 define_image_type (&tiff_type);
11248 #endif
11250 #if HAVE_GIF
11251 define_image_type (&gif_type);
11252 #endif
11254 #if HAVE_PNG
11255 define_image_type (&png_type);
11256 #endif
11259 #endif /* HAVE_X_WINDOWS */